mirror of
https://github.com/serde-rs/serde.git
synced 2025-10-02 15:25:38 +00:00
Add bytes type to enable {,de}serializing to a byte array
This commit is contained in:
parent
4beb86ab7e
commit
aa8d13456a
171
src/bytes.rs
Normal file
171
src/bytes.rs
Normal file
@ -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<T> 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<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
|
where S: ser::Serializer
|
||||||
|
{
|
||||||
|
serializer.visit_bytes(self.bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// `ByteBuf` wraps a `Vec<u8>` 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<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ByteBuf {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
ByteBuf {
|
||||||
|
bytes: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_capacity(cap: usize) -> Self {
|
||||||
|
ByteBuf {
|
||||||
|
bytes: Vec::with_capacity(cap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<T> for ByteBuf where T: Into<Vec<u8>> {
|
||||||
|
fn from(bytes: T) -> Self {
|
||||||
|
ByteBuf {
|
||||||
|
bytes: bytes.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<Vec<u8>> for ByteBuf {
|
||||||
|
fn as_ref(&self) -> &Vec<u8> {
|
||||||
|
&self.bytes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<[u8]> for ByteBuf {
|
||||||
|
fn as_ref(&self) -> &[u8] {
|
||||||
|
&self.bytes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsMut<Vec<u8>> for ByteBuf {
|
||||||
|
fn as_mut(&mut self) -> &mut Vec<u8> {
|
||||||
|
&mut self.bytes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsMut<[u8]> for ByteBuf {
|
||||||
|
fn as_mut(&mut self) -> &mut [u8] {
|
||||||
|
&mut self.bytes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<Vec<u8>> for ByteBuf {
|
||||||
|
fn into(self) -> Vec<u8> {
|
||||||
|
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<S>(&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<E>(&mut self) -> Result<ByteBuf, E>
|
||||||
|
where E: de::Error,
|
||||||
|
{
|
||||||
|
Ok(ByteBuf {
|
||||||
|
bytes: Vec::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<ByteBuf, V::Error>
|
||||||
|
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<E>(&mut self, v: &[u8]) -> Result<ByteBuf, E>
|
||||||
|
where E: de::Error,
|
||||||
|
{
|
||||||
|
self.visit_byte_buf(v.to_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<ByteBuf, E>
|
||||||
|
where E: de::Error,
|
||||||
|
{
|
||||||
|
Ok(ByteBuf {
|
||||||
|
bytes: v,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl de::Deserialize for ByteBuf {
|
||||||
|
#[inline]
|
||||||
|
fn deserialize<D>(deserializer: &mut D) -> Result<ByteBuf, D::Error>
|
||||||
|
where D: de::Deserializer
|
||||||
|
{
|
||||||
|
deserializer.visit_bytes(ByteBufVisitor)
|
||||||
|
}
|
||||||
|
}
|
24
src/de.rs
24
src/de.rs
@ -103,6 +103,16 @@ pub trait Deserializer {
|
|||||||
{
|
{
|
||||||
Err(Error::syntax_error())
|
Err(Error::syntax_error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `visit_bytes` method allows a `Deserialize` type to inform the `Deserializer` that it's
|
||||||
|
/// expecting a `Vec<u8>`. This allows deserializers that provide a custom byte vector
|
||||||
|
/// serialization to properly deserialize the type.
|
||||||
|
#[inline]
|
||||||
|
fn visit_bytes<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where V: Visitor,
|
||||||
|
{
|
||||||
|
self.visit(visitor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -247,6 +257,18 @@ pub trait Visitor {
|
|||||||
{
|
{
|
||||||
Err(Error::syntax_error())
|
Err(Error::syntax_error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_bytes<E>(&mut self, _v: &[u8]) -> Result<Self::Value, E>
|
||||||
|
where E: Error,
|
||||||
|
{
|
||||||
|
Err(Error::syntax_error())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_byte_buf<E>(&mut self, _v: Vec<u8>) -> Result<Self::Value, E>
|
||||||
|
where E: Error,
|
||||||
|
{
|
||||||
|
Err(Error::syntax_error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -981,7 +1003,7 @@ impl Visitor for PathBufVisitor {
|
|||||||
fn visit_str<E>(&mut self, v: &str) -> Result<path::PathBuf, E>
|
fn visit_str<E>(&mut self, v: &str) -> Result<path::PathBuf, E>
|
||||||
where E: Error,
|
where E: Error,
|
||||||
{
|
{
|
||||||
Ok(path::PathBuf::new(&v))
|
Ok(From::from(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_string<E>(&mut self, v: String) -> Result<path::PathBuf, E>
|
fn visit_string<E>(&mut self, v: String) -> Result<path::PathBuf, E>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#![feature(core, std_misc, unicode)]
|
#![feature(convert, core, std_misc, unicode)]
|
||||||
|
|
||||||
extern crate unicode;
|
extern crate unicode;
|
||||||
|
|
||||||
@ -8,3 +8,4 @@ pub use de::{Deserialize, Deserializer, Error};
|
|||||||
pub mod ser;
|
pub mod ser;
|
||||||
pub mod de;
|
pub mod de;
|
||||||
pub mod json;
|
pub mod json;
|
||||||
|
pub mod bytes;
|
||||||
|
10
src/ser.rs
10
src/ser.rs
@ -73,6 +73,8 @@ pub trait Serializer {
|
|||||||
|
|
||||||
fn visit_f64(&mut self, v: f64) -> Result<(), Self::Error>;
|
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]
|
#[inline]
|
||||||
fn visit_char(&mut self, v: char) -> Result<(), Self::Error> {
|
fn visit_char(&mut self, v: char) -> Result<(), Self::Error> {
|
||||||
// The unwraps in here should be safe.
|
// The unwraps in here should be safe.
|
||||||
@ -81,8 +83,16 @@ pub trait Serializer {
|
|||||||
self.visit_str(str::from_utf8(&s[..len]).unwrap())
|
self.visit_str(str::from_utf8(&s[..len]).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `visit_str` serializes a `&str`.
|
||||||
fn visit_str(&mut self, value: &str) -> Result<(), Self::Error>;
|
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>;
|
fn visit_unit(&mut self) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
210
tests/test_bytes.rs
Normal file
210
tests/test_bytes.rs
Normal file
@ -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<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BytesSerializer {
|
||||||
|
fn new(bytes: Vec<u8>) -> 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<V>(&mut self, _value: V) -> Result<(), Error>
|
||||||
|
where V: serde::Serialize,
|
||||||
|
{
|
||||||
|
Err(Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_seq<V>(&mut self, _visitor: V) -> Result<(), Error>
|
||||||
|
where V: serde::ser::SeqVisitor,
|
||||||
|
{
|
||||||
|
Err(Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_seq_elt<T>(&mut self, _value: T) -> Result<(), Error>
|
||||||
|
where T: serde::Serialize
|
||||||
|
{
|
||||||
|
Err(Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_map<V>(&mut self, _visitor: V) -> Result<(), Error>
|
||||||
|
where V: serde::ser::MapVisitor,
|
||||||
|
{
|
||||||
|
Err(Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_map_elt<K, V>(&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<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BytesDeserializer {
|
||||||
|
fn new(bytes: Vec<u8>) -> Self {
|
||||||
|
BytesDeserializer {
|
||||||
|
bytes: Some(bytes),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl serde::Deserializer for BytesDeserializer {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn visit<V>(&mut self, _visitor: V) -> Result<V::Value, Error>
|
||||||
|
where V: serde::de::Visitor,
|
||||||
|
{
|
||||||
|
Err(Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bytes<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
|
||||||
|
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])));
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user