Merge pull request #72 from borman/bytestrings

Improved support for byte strings
This commit is contained in:
Erick Tryzelaar
2015-05-18 22:28:37 -07:00
5 changed files with 128 additions and 6 deletions
+10
View File
@@ -686,6 +686,16 @@ fn deserialize_field_visitor(
{
$body
}
fn visit_bytes<E>(&mut self, value: &[u8]) -> ::std::result::Result<__Field, E>
where E: ::serde::de::Error,
{
// TODO: would be better to generate a byte string literal match
match ::std::str::from_utf8(value) {
Ok(s) => self.visit_str(s),
_ => Err(::serde::de::Error::syntax_error()),
}
}
}
deserializer.visit(
+43 -4
View File
@@ -1,6 +1,8 @@
//! Helper module to enable serializing bytes more efficiently
use std::ops;
use std::fmt;
use std::ascii;
use ser;
use de;
@@ -8,10 +10,17 @@ use de;
///////////////////////////////////////////////////////////////////////////////
/// `Bytes` wraps a `&[u8]` in order to serialize into a byte array.
#[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct Bytes<'a> {
bytes: &'a [u8],
}
impl<'a> fmt::Debug for Bytes<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "b\"{}\"", escape_bytestring(self.bytes))
}
}
impl<'a> From<&'a [u8]> for Bytes<'a> {
fn from(bytes: &'a [u8]) -> Self {
Bytes {
@@ -28,6 +37,12 @@ impl<'a> From<&'a Vec<u8>> for Bytes<'a> {
}
}
impl<'a> Into<&'a [u8]> for Bytes<'a> {
fn into(self) -> &'a [u8] {
self.bytes
}
}
impl<'a> ops::Deref for Bytes<'a> {
type Target = [u8];
@@ -46,7 +61,7 @@ impl<'a> ser::Serialize for Bytes<'a> {
///////////////////////////////////////////////////////////////////////////////
/// `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)]
#[derive(Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct ByteBuf {
bytes: Vec<u8>,
}
@@ -65,10 +80,22 @@ impl ByteBuf {
}
}
impl<T> From<T> for ByteBuf where T: Into<Vec<u8>> {
fn from(bytes: T) -> Self {
impl fmt::Debug for ByteBuf {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "b\"{}\"", escape_bytestring(self.bytes.as_ref()))
}
}
impl Into<Vec<u8>> for ByteBuf {
fn into(self) -> Vec<u8> {
self.bytes
}
}
impl From<Vec<u8>> for ByteBuf {
fn from(bytes: Vec<u8>) -> Self {
ByteBuf {
bytes: bytes.into(),
bytes: bytes,
}
}
}
@@ -172,3 +199,15 @@ impl de::Deserialize for ByteBuf {
deserializer.visit_bytes(ByteBufVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
fn escape_bytestring(bytes: &[u8]) -> String {
let mut result = String::new();
for &b in bytes {
for esc in ascii::escape_default(b) {
result.push(esc as char);
}
}
result
}
+19
View File
@@ -3,6 +3,7 @@ use std::hash::Hash;
use std::marker::PhantomData;
use std::path;
use std::rc::Rc;
use std::str;
use std::sync::Arc;
use std::str;
@@ -216,6 +217,24 @@ impl Visitor for StringVisitor {
{
Ok(v)
}
fn visit_bytes<E>(&mut self, v: &[u8]) -> Result<String, E>
where E: Error,
{
match str::from_utf8(v) {
Ok(s) => Ok(s.to_string()),
Err(_) => Err(Error::syntax_error()),
}
}
fn visit_byte_buf<'a, E>(&mut self, v: Vec<u8>) -> Result<String, E>
where E: Error,
{
match String::from_utf8(v) {
Ok(s) => Ok(s),
Err(_) => Err(Error::syntax_error()),
}
}
}
impl Deserialize for String {
+2 -2
View File
@@ -272,10 +272,10 @@ pub trait Visitor {
Err(Error::syntax_error())
}
fn visit_byte_buf<E>(&mut self, _v: Vec<u8>) -> Result<Self::Value, E>
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
self.visit_bytes(&v)
}
}
+54
View File
@@ -12,6 +12,7 @@ use std::hash::Hash;
use std::vec;
use de;
use bytes;
///////////////////////////////////////////////////////////////////////////////
@@ -409,3 +410,56 @@ impl<K, V> ValueDeserializer for HashMap<K, V>
MapDeserializer::new(self.into_iter(), len)
}
}
///////////////////////////////////////////////////////////////////////////////
impl<'a> ValueDeserializer for bytes::Bytes<'a>
{
type Deserializer = BytesDeserializer<'a>;
fn into_deserializer(self) -> BytesDeserializer<'a> {
BytesDeserializer(Some(self.into()))
}
}
pub struct BytesDeserializer<'a> (Option<&'a [u8]>);
impl<'a> de::Deserializer for BytesDeserializer<'a> {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.0.take() {
Some(bytes) => visitor.visit_bytes(bytes),
None => Err(de::Error::end_of_stream_error()),
}
}
}
///////////////////////////////////////////////////////////////////////////////
impl ValueDeserializer for bytes::ByteBuf
{
type Deserializer = ByteBufDeserializer;
fn into_deserializer(self) -> Self::Deserializer {
ByteBufDeserializer(Some(self.into()))
}
}
pub struct ByteBufDeserializer(Option<Vec<u8>>);
impl de::Deserializer for ByteBufDeserializer {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.0.take() {
Some(bytes) => visitor.visit_byte_buf(bytes),
None => Err(de::Error::end_of_stream_error()),
}
}
}