Skip to content

Commit

Permalink
Merge pull request #837 from serde-rs/borrow
Browse files Browse the repository at this point in the history
Derive for borrowed fields
  • Loading branch information
dtolnay authored Apr 4, 2017
2 parents 8c3e72f + 20ff9ba commit 7c27e10
Show file tree
Hide file tree
Showing 15 changed files with 712 additions and 103 deletions.
8 changes: 4 additions & 4 deletions serde/src/de/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,9 @@ impl<'a> Visitor<'a> for StrVisitor {
}
}

impl<'a> Deserialize<'a> for &'a str {
impl<'de: 'a, 'a> Deserialize<'de> for &'a str {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'a>
where D: Deserializer<'de>
{
deserializer.deserialize_str(StrVisitor)
}
Expand Down Expand Up @@ -360,9 +360,9 @@ impl<'a> Visitor<'a> for BytesVisitor {
}
}

impl<'a> Deserialize<'a> for &'a [u8] {
impl<'de: 'a, 'a> Deserialize<'de> for &'a [u8] {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'a>
where D: Deserializer<'de>
{
deserializer.deserialize_bytes(BytesVisitor)
}
Expand Down
132 changes: 132 additions & 0 deletions serde/src/de/private.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
#[cfg(any(feature = "std", feature = "collections"))]
use core::{fmt, str};

use core::marker::PhantomData;

#[cfg(feature = "collections")]
use collections::borrow::ToOwned;

#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::borrow::Cow;

#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::{String, Vec};

use de::{Deserialize, Deserializer, Error, Visitor};

#[cfg(any(feature = "std", feature = "collections"))]
use de::Unexpected;

#[cfg(any(feature = "std", feature = "collections"))]
pub use de::content::{Content, ContentRefDeserializer, ContentDeserializer, TaggedContentVisitor,
TagOrContentField, TagOrContentFieldVisitor, InternallyTaggedUnitVisitor,
Expand Down Expand Up @@ -42,3 +59,118 @@ pub fn missing_field<'de, V, E>(field: &'static str) -> Result<V, E>
let deserializer = MissingFieldDeserializer(field, PhantomData);
Deserialize::deserialize(deserializer)
}

#[cfg(any(feature = "std", feature = "collections"))]
pub fn borrow_cow_str<'de: 'a, 'a, D>(deserializer: D) -> Result<Cow<'a, str>, D::Error>
where D: Deserializer<'de>
{
struct CowStrVisitor;

impl<'a> Visitor<'a> for CowStrVisitor {
type Value = Cow<'a, str>;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string")
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where E: Error
{
Ok(Cow::Owned(v.to_owned()))
}

fn visit_borrowed_str<E>(self, v: &'a str) -> Result<Self::Value, E>
where E: Error
{
Ok(Cow::Borrowed(v))
}

fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where E: Error
{
Ok(Cow::Owned(v))
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where E: Error
{
match str::from_utf8(v) {
Ok(s) => Ok(Cow::Owned(s.to_owned())),
Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)),
}
}

fn visit_borrowed_bytes<E>(self, v: &'a [u8]) -> Result<Self::Value, E>
where E: Error
{
match str::from_utf8(v) {
Ok(s) => Ok(Cow::Borrowed(s)),
Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)),
}
}

fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where E: Error
{
match String::from_utf8(v) {
Ok(s) => Ok(Cow::Owned(s)),
Err(e) => Err(Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self)),
}
}
}

deserializer.deserialize_str(CowStrVisitor)
}

#[cfg(any(feature = "std", feature = "collections"))]
pub fn borrow_cow_bytes<'de: 'a, 'a, D>(deserializer: D) -> Result<Cow<'a, [u8]>, D::Error>
where D: Deserializer<'de>
{
struct CowBytesVisitor;

impl<'a> Visitor<'a> for CowBytesVisitor {
type Value = Cow<'a, [u8]>;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a byte array")
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where E: Error
{
Ok(Cow::Owned(v.as_bytes().to_vec()))
}

fn visit_borrowed_str<E>(self, v: &'a str) -> Result<Self::Value, E>
where E: Error
{
Ok(Cow::Borrowed(v.as_bytes()))
}

fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where E: Error
{
Ok(Cow::Owned(v.into_bytes()))
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where E: Error
{
Ok(Cow::Owned(v.to_vec()))
}

fn visit_borrowed_bytes<E>(self, v: &'a [u8]) -> Result<Self::Value, E>
where E: Error
{
Ok(Cow::Borrowed(v))
}

fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where E: Error
{
Ok(Cow::Owned(v))
}
}

deserializer.deserialize_str(CowBytesVisitor)
}
3 changes: 2 additions & 1 deletion serde_codegen_internals/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ readme = "../README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]

[dependencies]
syn = { version = "0.11", default-features = false, features = ["parsing"] }
syn = { version = "0.11.10", default-features = false, features = ["parsing"] }
synom = "0.11"

[badges]
travis-ci = { repository = "serde-rs/serde" }
Loading

0 comments on commit 7c27e10

Please sign in to comment.