Compare commits

...

63 Commits

Author SHA1 Message Date
David Tolnay 1b763da529 Release 0.9.13 2017-04-05 15:03:37 -07:00
David Tolnay b7d6c5d9f7 Remove no_std special case in forward_to_deserialize 2017-04-05 15:01:55 -07:00
David Tolnay bfabaf3789 Merge pull request #838 from serde-rs/winstr
Deserialize OsString on Windows
2017-04-04 11:33:42 -07:00
David Tolnay cf6c4ab7ec Deserialize OsString on Windows 2017-04-04 11:19:24 -07:00
David Tolnay 8eb50186e0 Merge pull request #831 from serde-rs/derivepath
Use the live serde_derive for serde doc tests
2017-03-30 22:55:33 -07:00
David Tolnay 7d985ff3fd Use the live serde_derive for serde doc tests
This is required as both are updated to Deserialize<'de> together.
2017-03-30 22:45:15 -07:00
David Tolnay 59b3961ad4 Release 0.9.12 2017-03-27 15:45:14 -07:00
David Tolnay dbc9a60c5f Merge pull request #824 from alexcrichton/osstr-osstring
Implement Serialize/Deserialize for OsStr/OsString
2017-03-27 15:39:07 -07:00
Alex Crichton ce687431f3 Implement Serialize/Deserialize for OsStr/OsString
This commit implements the two serde traits for the libstd `OsStr` and
`OsString` types. This came up as a use case during implementing sccache where
we're basically just doing IPC to communicate paths around. Additionally the
`Path` and `PathBuf` implementations have been updated to delegate to the os
string ones.

These types are platform-specific, however, so the serialization/deserialization
isn't trivial. Currently this "fakes" a newtype variant for Unix/Windows to
prevent cross-platform serialization/deserialization. This means if you're doing
IPC within the same OS (e.g. Windows to Windows) then serialization should be
infallible. If you're doing IPC across platforms (e.g.  Unix to Windows) then
using `OsString` is guaranteed to fail as bytes from one OS won't deserialize on
the other (even if they're unicode).
2017-03-27 11:44:50 -07:00
David Tolnay 71ccc5753b Merge pull request #820 from serde-rs/reexport
Re-export derives from serde
2017-03-26 20:37:12 -07:00
David Tolnay 13886435a6 Re-export derives from serde 2017-03-21 16:54:31 -07:00
David Tolnay 08e2182042 UFCS for Option::map and Result::map 2017-03-18 13:31:03 -07:00
David Tolnay d60595cc27 Use format_args! to simplify de::Error 2017-03-18 10:48:47 -07:00
David Tolnay 8c7396c35a Be consistent with UFCS and double underscores 2017-03-18 10:33:22 -07:00
David Tolnay 42b2fd8eec Improve error message parsing from and into 2017-03-18 09:22:44 -07:00
John Baublitz bc946e4fd7 Macro attributes to specify From and Into trait types for structs and enums (#817)
* serde macro support for type conversions through From and Into trait

* Revisions requested by dtolnay

* Additional changes requested by dtolnay
2017-03-18 09:22:27 -07:00
David Tolnay c488cec641 Remove RangeInclusive impl for now
The old impl is inconsistent with the new ops::Range impl.
2017-03-13 11:09:56 -07:00
David Tolnay fcc3c69a49 Range impl is defined when building with std 2017-03-09 12:04:02 -08:00
David Tolnay 350c2e835b Remove duplicate ops::Range serialize impl 2017-03-09 11:57:36 -08:00
David Tolnay a0a031677e Merge pull request #813 from rocallahan/support-range
Implement `Serialize`/`Deserialize` for `Range`
2017-03-09 11:55:21 -08:00
Robert O'Callahan cc0d045f5c Add Deserialize impl for std::ops::Range
Resolves #796
2017-03-10 08:39:34 +13:00
Robert O'Callahan aebe1fddab Add Serialize impl for std::ops::Range 2017-03-10 00:35:04 +13:00
David Tolnay 77ee306b57 Format serde with rustfmt 0.8.0 2017-03-08 21:11:17 -08:00
David Tolnay 6750fdaae1 Merge pull request #811 from jonhoo/deserialize-cstr
Add Deserialize impl for CStr
2017-03-08 21:06:09 -08:00
David Tolnay dd6989d551 Actually run unstable tests 2017-03-08 21:02:15 -08:00
Jon Gjengset 0c2fed49e2 Add Deserialize impl for CStr
Fixes #810
2017-03-08 23:57:26 -05:00
Oliver Schneider a4ee9bd045 Merge pull request #808 from serde-rs/u32
Implement deserialize_enum for U32Deserializer
2017-03-07 18:58:29 +01:00
David Tolnay 6d9397d573 Implement deserialize_enum for U32Deserializer 2017-03-07 09:05:33 -08:00
David Tolnay dc9445f873 Release 0.9.11 2017-03-05 16:51:44 -08:00
David Tolnay 17bc40ec1c Merge pull request #789 from nox/display
Introduce Serializer::collect_str (fixes #786)
2017-03-05 16:47:22 -08:00
David Tolnay 2184fef82f Add format_args example to collect_str 2017-03-05 16:43:31 -08:00
David Tolnay 7e1b5c6ce4 Neater collect_str variable name for rustdoc 2017-03-05 16:26:05 -08:00
David Tolnay 36da8a5cee Error message geared toward serializer users
The previous message was targeted toward Serializer implementors, which is not
the group that will be seeing this message most often.
2017-03-05 16:24:48 -08:00
David Tolnay fbe85f399d Force no_std formats to implement collect_str in the future 2017-03-05 16:22:02 -08:00
David Tolnay 880b27b19e Identical signature for std and no_std collect_str 2017-03-05 16:17:03 -08:00
David Tolnay cc06f070d1 Use the existing CString error message 2017-03-05 13:59:18 -08:00
David Tolnay 2f988aa5e6 Merge pull request #801 from jonhoo/ffi-strings
impls for null-terminated FFI string types
2017-03-05 13:51:09 -08:00
Jon Gjengset d294a10e83 Only include ByteBuf when ser/de is on for std 2017-03-03 23:48:00 -05:00
Jon Gjengset defcbef7ab Use a non-stupid path for bytes::ByteBuf 2017-03-03 23:28:35 -05:00
Jon Gjengset d90eecd4a2 Add tests for CStr(ing) ser/de 2017-03-03 18:06:04 -05:00
Jon Gjengset 0d6d077e6a Serialize and deserialize CString through [u8] 2017-03-03 18:05:08 -05:00
Jon Gjengset be09fc9bbb Remove unsafe Deserialize impl for CStr
See also https://github.com/rust-lang/rust/issues/40248
2017-03-03 17:34:01 -05:00
Jon Gjengset fc9d78e26b Use serialize_bytes for speed 2017-03-03 17:14:39 -05:00
Jon Gjengset 9f83164c40 Don't serialize trailing NULL 2017-03-03 17:14:28 -05:00
Jon Gjengset 857974ab8a impls for null-terminated FFI string types
Fixes #800.
2017-03-03 16:09:41 -05:00
David Tolnay d70636f4d4 Merge pull request #794 from clarcharr/master
Documentation for serde_test.
2017-03-02 11:53:05 -08:00
Clar Charr 09e467cc4c Documentation for serde_test. 2017-02-28 18:20:27 -05:00
David Tolnay 51ed9c2a40 Release 0.9.10 2017-02-28 12:45:39 -08:00
Anthony Ramine a9a05350a9 Introduce Serializer::collect_str (fixes #786)
The default implementation collects the Display value into a String
and then passes that to Serializer::serialize_str when the std or collections
features are enabled, otherwise it unconditionally returns an error.
2017-02-28 12:11:47 +01:00
David Tolnay fe9ea3b4b4 Fix needless_pass_by_value lint 2017-02-27 19:43:42 -08:00
David Tolnay f944b453c4 Merge pull request #792 from elliottslaughter/fix_serialize_tuple_docs
Fix documentation of serialize_tuple and SerializeTuple
2017-02-27 14:05:15 -08:00
Elliott Slaughter a993630cf9 Fix documentation of serialize_tuple and SerializeTuple. 2017-02-27 14:00:21 -08:00
David Tolnay abc081ce9c Test rename_all attribute 2017-02-25 11:58:34 -08:00
David Tolnay 207940046b Merge pull request #788 from 46bit/issue-140
`rename_all` container attribute to have all children fit a naming convention
2017-02-25 11:38:33 -08:00
David Tolnay 47efbc6d75 Don't need to pass back the input here 2017-02-25 11:32:27 -08:00
David Tolnay 17279e8a4f Simplify case conversion implementation 2017-02-25 11:32:22 -08:00
David Tolnay 06c631db05 Bring in the tests 2017-02-25 11:02:51 -08:00
David Tolnay 7952bad41f Move case conversion to its own file 2017-02-25 11:02:25 -08:00
Michael Mokrysz 3308f81c3a Saving progress on naming convention conversion code to try new Inflector changes. #788 2017-02-25 13:24:49 +00:00
David Tolnay 75e6da02d3 Split up test suite so it compiles in parallel 2017-02-24 15:39:18 -08:00
Michael Mokrysz 84915268ee Minor fixes for pull request. Cheers @dtolnay. 2017-02-24 01:55:31 +00:00
Michael Mokrysz 3b59d47e07 Heavily refactored rename_all and switched to SCREAMING_SNAKE_CASE. 2017-02-23 23:22:54 +00:00
Michael Mokrysz fc94c5399a Implementing rename_all container attribute using Inflector trait. #140 2017-02-23 18:58:41 +00:00
42 changed files with 1779 additions and 599 deletions
+17
View File
@@ -0,0 +1,17 @@
environment:
matrix:
- APPVEYOR_RUST_CHANNEL: stable
- APPVEYOR_RUST_CHANNEL: nightly
install:
# Install rust, x86_64-pc-windows-msvc host
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
- rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain %APPVEYOR_RUST_CHANNEL%
- set PATH=C:\msys64\usr\bin;%PATH%;C:\Users\appveyor\.cargo\bin
- rustc -vV
- cargo -vV
build: false
test_script:
- sh -c 'PATH=`rustc --print sysroot`/bin:$PATH ./travis.sh'
+4 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "serde"
version = "0.9.9"
version = "0.9.13"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
@@ -17,6 +17,7 @@ travis-ci = { repository = "serde-rs/serde" }
[features]
default = ["std"]
derive = ["serde_derive"]
std = []
unstable = []
@@ -28,7 +29,7 @@ unstable-testing = ["unstable", "std"]
playground = ["serde_derive"]
[dependencies]
serde_derive = { version = "0.9", optional = true }
serde_derive = { version = "0.9", optional = true, path = "../serde_derive" }
[dev-dependencies]
serde_derive = "0.9"
serde_derive = { version = "0.9", path = "../serde_derive" }
+147 -86
View File
@@ -510,9 +510,9 @@ impl<T> Visitor for TaggedContentVisitor<T>
None => Err(de::Error::missing_field(self.tag_name)),
Some(tag) => {
Ok(TaggedContent {
tag: tag,
content: Content::Map(vec),
})
tag: tag,
content: Content::Map(vec),
})
}
}
}
@@ -604,8 +604,10 @@ impl<E> Deserializer for ContentDeserializer<E>
Ok(value)
}
Content::Map(v) => {
let map = v.into_iter()
.map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v)));
let map = v.into_iter().map(|(k, v)| {
(ContentDeserializer::new(k),
ContentDeserializer::new(v))
});
let mut map_visitor = de::value::MapDeserializer::new(map);
let value = try!(visitor.visit_map(&mut map_visitor));
try!(map_visitor.end());
@@ -632,8 +634,12 @@ impl<E> Deserializer for ContentDeserializer<E>
visitor.visit_newtype_struct(self)
}
fn deserialize_enum<V>(self, _name: &str, _variants: &'static [&'static str], visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
fn deserialize_enum<V>(self,
_name: &str,
_variants: &'static [&'static str],
visitor: V)
-> Result<V::Value, Self::Error>
where V: Visitor
{
let (variant, value) = match self.content {
Content::Map(value) => {
@@ -641,12 +647,14 @@ impl<E> Deserializer for ContentDeserializer<E>
let (variant, value) = match iter.next() {
Some(v) => v,
None => {
return Err(de::Error::invalid_value(de::Unexpected::Map, &"map with a single key"));
return Err(de::Error::invalid_value(de::Unexpected::Map,
&"map with a single key"));
}
};
// enums are encoded in json as maps with a single key:value pair
if iter.next().is_some() {
return Err(de::Error::invalid_value(de::Unexpected::Map, &"map with a single key"));
return Err(de::Error::invalid_value(de::Unexpected::Map,
&"map with a single key"));
}
(variant, Some(value))
}
@@ -657,10 +665,10 @@ impl<E> Deserializer for ContentDeserializer<E>
};
visitor.visit_enum(EnumDeserializer {
variant: variant,
value: value,
err: PhantomData,
})
variant: variant,
value: value,
err: PhantomData,
})
}
forward_to_deserialize! {
@@ -680,30 +688,43 @@ impl<E> ContentDeserializer<E> {
}
}
struct EnumDeserializer<E> where E: de::Error {
struct EnumDeserializer<E>
where E: de::Error
{
variant: Content,
value: Option<Content>,
err: PhantomData<E>,
}
impl<E> de::EnumVisitor for EnumDeserializer<E> where E: de::Error {
impl<E> de::EnumVisitor for EnumDeserializer<E>
where E: de::Error
{
type Error = E;
type Variant = VariantDeserializer<Self::Error>;
fn visit_variant_seed<V>(self, seed: V) -> Result<(V::Value, VariantDeserializer<E>), Self::Error>
where V: de::DeserializeSeed,
fn visit_variant_seed<V>(self,
seed: V)
-> Result<(V::Value, VariantDeserializer<E>), Self::Error>
where V: de::DeserializeSeed
{
let visitor = VariantDeserializer { value: self.value, err: PhantomData, };
let visitor = VariantDeserializer {
value: self.value,
err: PhantomData,
};
seed.deserialize(ContentDeserializer::new(self.variant)).map(|v| (v, visitor))
}
}
struct VariantDeserializer<E> where E: de::Error {
struct VariantDeserializer<E>
where E: de::Error
{
value: Option<Content>,
err: PhantomData<E>,
}
impl<E> de::VariantVisitor for VariantDeserializer<E> where E: de::Error {
impl<E> de::VariantVisitor for VariantDeserializer<E>
where E: de::Error
{
type Error = E;
fn visit_unit(self) -> Result<(), E> {
@@ -722,11 +743,7 @@ impl<E> de::VariantVisitor for VariantDeserializer<E> where E: de::Error {
}
}
fn visit_tuple<V>(
self,
_len: usize,
visitor: V
) -> Result<V::Value, Self::Error>
fn visit_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor
{
match self.value {
@@ -734,15 +751,14 @@ impl<E> de::VariantVisitor for VariantDeserializer<E> where E: de::Error {
de::Deserializer::deserialize(SeqDeserializer::new(v), visitor)
}
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"tuple variant")),
None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant"))
None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant")),
}
}
fn visit_struct<V>(
self,
_fields: &'static [&'static str],
visitor: V
) -> Result<V::Value, Self::Error>
fn visit_struct<V>(self,
_fields: &'static [&'static str],
visitor: V)
-> Result<V::Value, Self::Error>
where V: de::Visitor
{
match self.value {
@@ -750,17 +766,21 @@ impl<E> de::VariantVisitor for VariantDeserializer<E> where E: de::Error {
de::Deserializer::deserialize(MapDeserializer::new(v), visitor)
}
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant")),
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"))
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant")),
}
}
}
struct SeqDeserializer<E> where E: de::Error {
struct SeqDeserializer<E>
where E: de::Error
{
iter: <Vec<Content> as IntoIterator>::IntoIter,
err: PhantomData<E>,
}
impl<E> SeqDeserializer<E> where E: de::Error {
impl<E> SeqDeserializer<E>
where E: de::Error
{
fn new(vec: Vec<Content>) -> Self {
SeqDeserializer {
iter: vec.into_iter(),
@@ -769,12 +789,14 @@ impl<E> SeqDeserializer<E> where E: de::Error {
}
}
impl<E> de::Deserializer for SeqDeserializer<E> where E: de::Error {
impl<E> de::Deserializer for SeqDeserializer<E>
where E: de::Error
{
type Error = E;
#[inline]
fn deserialize<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
where V: de::Visitor
{
let len = self.iter.len();
if len == 0 {
@@ -797,11 +819,13 @@ impl<E> de::Deserializer for SeqDeserializer<E> where E: de::Error {
}
}
impl<E> de::SeqVisitor for SeqDeserializer<E> where E: de::Error {
impl<E> de::SeqVisitor for SeqDeserializer<E>
where E: de::Error
{
type Error = E;
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where T: de::DeserializeSeed,
where T: de::DeserializeSeed
{
match self.iter.next() {
Some(value) => seed.deserialize(ContentDeserializer::new(value)).map(Some),
@@ -814,13 +838,17 @@ impl<E> de::SeqVisitor for SeqDeserializer<E> where E: de::Error {
}
}
struct MapDeserializer<E> where E: de::Error {
struct MapDeserializer<E>
where E: de::Error
{
iter: <Vec<(Content, Content)> as IntoIterator>::IntoIter,
value: Option<Content>,
err: PhantomData<E>,
}
impl<E> MapDeserializer<E> where E: de::Error {
impl<E> MapDeserializer<E>
where E: de::Error
{
fn new(map: Vec<(Content, Content)>) -> Self {
MapDeserializer {
iter: map.into_iter(),
@@ -830,11 +858,13 @@ impl<E> MapDeserializer<E> where E: de::Error {
}
}
impl<E> de::MapVisitor for MapDeserializer<E> where E: de::Error {
impl<E> de::MapVisitor for MapDeserializer<E>
where E: de::Error
{
type Error = E;
fn visit_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where T: de::DeserializeSeed,
where T: de::DeserializeSeed
{
match self.iter.next() {
Some((key, value)) => {
@@ -846,7 +876,7 @@ impl<E> de::MapVisitor for MapDeserializer<E> where E: de::Error {
}
fn visit_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
where T: de::DeserializeSeed,
where T: de::DeserializeSeed
{
match self.value.take() {
Some(value) => seed.deserialize(ContentDeserializer::new(value)),
@@ -859,12 +889,14 @@ impl<E> de::MapVisitor for MapDeserializer<E> where E: de::Error {
}
}
impl<E> de::Deserializer for MapDeserializer<E> where E: de::Error {
impl<E> de::Deserializer for MapDeserializer<E>
where E: de::Error
{
type Error = E;
#[inline]
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
where V: de::Visitor
{
visitor.visit_map(self)
}
@@ -920,8 +952,9 @@ impl<'a, E> Deserializer for ContentRefDeserializer<'a, E>
}
Content::Map(ref v) => {
let map = v.into_iter().map(|&(ref k, ref v)| {
(ContentRefDeserializer::new(k), ContentRefDeserializer::new(v))
});
(ContentRefDeserializer::new(k),
ContentRefDeserializer::new(v))
});
let mut map_visitor = de::value::MapDeserializer::new(map);
let value = try!(visitor.visit_map(&mut map_visitor));
try!(map_visitor.end());
@@ -948,8 +981,12 @@ impl<'a, E> Deserializer for ContentRefDeserializer<'a, E>
visitor.visit_newtype_struct(self)
}
fn deserialize_enum<V>(self, _name: &str, _variants: &'static [&'static str], visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
fn deserialize_enum<V>(self,
_name: &str,
_variants: &'static [&'static str],
visitor: V)
-> Result<V::Value, Self::Error>
where V: Visitor
{
let (variant, value) = match *self.content {
Content::Map(ref value) => {
@@ -957,12 +994,14 @@ impl<'a, E> Deserializer for ContentRefDeserializer<'a, E>
let &(ref variant, ref value) = match iter.next() {
Some(v) => v,
None => {
return Err(de::Error::invalid_value(de::Unexpected::Map, &"map with a single key"));
return Err(de::Error::invalid_value(de::Unexpected::Map,
&"map with a single key"));
}
};
// enums are encoded in json as maps with a single key:value pair
if iter.next().is_some() {
return Err(de::Error::invalid_value(de::Unexpected::Map, &"map with a single key"));
return Err(de::Error::invalid_value(de::Unexpected::Map,
&"map with a single key"));
}
(variant, Some(value))
}
@@ -973,10 +1012,10 @@ impl<'a, E> Deserializer for ContentRefDeserializer<'a, E>
};
visitor.visit_enum(EnumRefDeserializer {
variant: variant,
value: value,
err: PhantomData,
})
variant: variant,
value: value,
err: PhantomData,
})
}
forward_to_deserialize! {
@@ -996,30 +1035,41 @@ impl<'a, E> ContentRefDeserializer<'a, E> {
}
}
struct EnumRefDeserializer<'a, E> where E: de::Error {
struct EnumRefDeserializer<'a, E>
where E: de::Error
{
variant: &'a Content,
value: Option<&'a Content>,
err: PhantomData<E>,
}
impl<'a, E> de::EnumVisitor for EnumRefDeserializer<'a, E> where E: de::Error {
impl<'a, E> de::EnumVisitor for EnumRefDeserializer<'a, E>
where E: de::Error
{
type Error = E;
type Variant = VariantRefDeserializer<'a, Self::Error>;
fn visit_variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where V: de::DeserializeSeed,
where V: de::DeserializeSeed
{
let visitor = VariantRefDeserializer { value: self.value, err: PhantomData, };
let visitor = VariantRefDeserializer {
value: self.value,
err: PhantomData,
};
seed.deserialize(ContentRefDeserializer::new(self.variant)).map(|v| (v, visitor))
}
}
struct VariantRefDeserializer<'a, E> where E: de::Error {
struct VariantRefDeserializer<'a, E>
where E: de::Error
{
value: Option<&'a Content>,
err: PhantomData<E>,
}
impl<'a, E> de::VariantVisitor for VariantRefDeserializer<'a, E> where E: de::Error {
impl<'a, E> de::VariantVisitor for VariantRefDeserializer<'a, E>
where E: de::Error
{
type Error = E;
fn visit_unit(self) -> Result<(), E> {
@@ -1038,11 +1088,7 @@ impl<'a, E> de::VariantVisitor for VariantRefDeserializer<'a, E> where E: de::Er
}
}
fn visit_tuple<V>(
self,
_len: usize,
visitor: V
) -> Result<V::Value, Self::Error>
fn visit_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor
{
match self.value {
@@ -1050,15 +1096,14 @@ impl<'a, E> de::VariantVisitor for VariantRefDeserializer<'a, E> where E: de::Er
de::Deserializer::deserialize(SeqRefDeserializer::new(v), visitor)
}
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"tuple variant")),
None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant"))
None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant")),
}
}
fn visit_struct<V>(
self,
_fields: &'static [&'static str],
visitor: V
) -> Result<V::Value, Self::Error>
fn visit_struct<V>(self,
_fields: &'static [&'static str],
visitor: V)
-> Result<V::Value, Self::Error>
where V: de::Visitor
{
match self.value {
@@ -1066,17 +1111,21 @@ impl<'a, E> de::VariantVisitor for VariantRefDeserializer<'a, E> where E: de::Er
de::Deserializer::deserialize(MapRefDeserializer::new(v), visitor)
}
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant")),
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"))
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant")),
}
}
}
struct SeqRefDeserializer<'a, E> where E: de::Error {
struct SeqRefDeserializer<'a, E>
where E: de::Error
{
iter: <&'a [Content] as IntoIterator>::IntoIter,
err: PhantomData<E>,
}
impl<'a, E> SeqRefDeserializer<'a, E> where E: de::Error {
impl<'a, E> SeqRefDeserializer<'a, E>
where E: de::Error
{
fn new(vec: &'a [Content]) -> Self {
SeqRefDeserializer {
iter: vec.into_iter(),
@@ -1085,12 +1134,14 @@ impl<'a, E> SeqRefDeserializer<'a, E> where E: de::Error {
}
}
impl<'a, E> de::Deserializer for SeqRefDeserializer<'a, E> where E: de::Error {
impl<'a, E> de::Deserializer for SeqRefDeserializer<'a, E>
where E: de::Error
{
type Error = E;
#[inline]
fn deserialize<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
where V: de::Visitor
{
let len = self.iter.len();
if len == 0 {
@@ -1113,11 +1164,13 @@ impl<'a, E> de::Deserializer for SeqRefDeserializer<'a, E> where E: de::Error {
}
}
impl<'a, E> de::SeqVisitor for SeqRefDeserializer<'a, E> where E: de::Error {
impl<'a, E> de::SeqVisitor for SeqRefDeserializer<'a, E>
where E: de::Error
{
type Error = E;
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where T: de::DeserializeSeed,
where T: de::DeserializeSeed
{
match self.iter.next() {
Some(value) => seed.deserialize(ContentRefDeserializer::new(value)).map(Some),
@@ -1130,13 +1183,17 @@ impl<'a, E> de::SeqVisitor for SeqRefDeserializer<'a, E> where E: de::Error {
}
}
struct MapRefDeserializer<'a, E> where E: de::Error {
struct MapRefDeserializer<'a, E>
where E: de::Error
{
iter: <&'a [(Content, Content)] as IntoIterator>::IntoIter,
value: Option<&'a Content>,
err: PhantomData<E>,
}
impl<'a, E> MapRefDeserializer<'a, E> where E: de::Error {
impl<'a, E> MapRefDeserializer<'a, E>
where E: de::Error
{
fn new(map: &'a [(Content, Content)]) -> Self {
MapRefDeserializer {
iter: map.into_iter(),
@@ -1146,11 +1203,13 @@ impl<'a, E> MapRefDeserializer<'a, E> where E: de::Error {
}
}
impl<'a, E> de::MapVisitor for MapRefDeserializer<'a, E> where E: de::Error {
impl<'a, E> de::MapVisitor for MapRefDeserializer<'a, E>
where E: de::Error
{
type Error = E;
fn visit_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where T: de::DeserializeSeed,
where T: de::DeserializeSeed
{
match self.iter.next() {
Some(&(ref key, ref value)) => {
@@ -1162,7 +1221,7 @@ impl<'a, E> de::MapVisitor for MapRefDeserializer<'a, E> where E: de::Error {
}
fn visit_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
where T: de::DeserializeSeed,
where T: de::DeserializeSeed
{
match self.value.take() {
Some(value) => seed.deserialize(ContentRefDeserializer::new(value)),
@@ -1175,12 +1234,14 @@ impl<'a, E> de::MapVisitor for MapRefDeserializer<'a, E> where E: de::Error {
}
}
impl<'a, E> de::Deserializer for MapRefDeserializer<'a, E> where E: de::Error {
impl<'a, E> de::Deserializer for MapRefDeserializer<'a, E>
where E: de::Error
{
type Error = E;
#[inline]
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
where V: de::Visitor
{
visitor.visit_map(self)
}
+284
View File
@@ -25,6 +25,10 @@ use std::net;
#[cfg(feature = "std")]
use std::path;
use core::str;
#[cfg(feature = "std")]
use std::ffi::{CString, OsString};
#[cfg(all(feature = "std", feature="unstable"))]
use std::ffi::CStr;
#[cfg(feature = "std")]
use std::rc::Rc;
@@ -42,6 +46,9 @@ use alloc::boxed::Box;
#[cfg(feature = "std")]
use std::time::Duration;
#[cfg(feature = "std")]
use std;
#[cfg(feature = "unstable")]
use core::nonzero::{NonZero, Zeroable};
@@ -53,6 +60,9 @@ use de::{Deserialize, Deserializer, EnumVisitor, Error, MapVisitor, SeqVisitor,
VariantVisitor, Visitor};
use de::from_primitive::FromPrimitive;
#[cfg(feature = "std")]
use bytes::ByteBuf;
///////////////////////////////////////////////////////////////////////////////
/// A visitor that produces a `()`.
@@ -295,6 +305,28 @@ impl Deserialize for String {
///////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "std", feature="unstable"))]
impl Deserialize for Box<CStr> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer
{
let s = try!(CString::deserialize(deserializer));
Ok(s.into_boxed_c_str())
}
}
#[cfg(feature = "std")]
impl Deserialize for CString {
fn deserialize<D>(deserializer: D) -> Result<CString, D::Error>
where D: Deserializer
{
let bytes = try!(ByteBuf::deserialize(deserializer));
CString::new(bytes).map_err(Error::custom)
}
}
///////////////////////////////////////////////////////////////////////////////
struct OptionVisitor<T> {
marker: PhantomData<T>,
}
@@ -878,6 +910,7 @@ impl Visitor for PathBufVisitor {
}
}
#[cfg(feature = "std")]
impl Deserialize for path::PathBuf {
fn deserialize<D>(deserializer: D) -> Result<path::PathBuf, D::Error>
@@ -889,6 +922,126 @@ impl Deserialize for path::PathBuf {
///////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "std", any(unix, windows)))]
enum OsStringKind {
Unix,
Windows,
}
#[cfg(all(feature = "std", any(unix, windows)))]
static OSSTR_VARIANTS: &'static [&'static str] = &["Unix", "Windows"];
#[cfg(all(feature = "std", any(unix, windows)))]
impl Deserialize for OsStringKind {
fn deserialize<D>(deserializer: D) -> Result<OsStringKind, D::Error>
where D: Deserializer
{
struct KindVisitor;
impl Visitor for KindVisitor {
type Value = OsStringKind;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("`Unix` or `Windows`")
}
fn visit_u32<E>(self, value: u32) -> Result<OsStringKind, E>
where E: Error,
{
match value {
0 => Ok(OsStringKind::Unix),
1 => Ok(OsStringKind::Windows),
_ => Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self))
}
}
fn visit_str<E>(self, value: &str) -> Result<OsStringKind, E>
where E: Error,
{
match value {
"Unix" => Ok(OsStringKind::Unix),
"Windows" => Ok(OsStringKind::Windows),
_ => Err(Error::unknown_variant(value, OSSTR_VARIANTS)),
}
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<OsStringKind, E>
where E: Error,
{
match value {
b"Unix" => Ok(OsStringKind::Unix),
b"Windows" => Ok(OsStringKind::Windows),
_ => {
match str::from_utf8(value) {
Ok(value) => Err(Error::unknown_variant(value, OSSTR_VARIANTS)),
Err(_) => {
Err(Error::invalid_value(Unexpected::Bytes(value), &self))
}
}
}
}
}
}
deserializer.deserialize(KindVisitor)
}
}
#[cfg(all(feature = "std", any(unix, windows)))]
struct OsStringVisitor;
#[cfg(all(feature = "std", any(unix, windows)))]
impl Visitor for OsStringVisitor {
type Value = OsString;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("os string")
}
#[cfg(unix)]
fn visit_enum<V>(self, visitor: V) -> Result<OsString, V::Error>
where V: EnumVisitor,
{
use std::os::unix::ffi::OsStringExt;
match try!(visitor.visit_variant()) {
(OsStringKind::Unix, variant) => {
variant.visit_newtype().map(OsString::from_vec)
}
(OsStringKind::Windows, _) => {
Err(Error::custom("cannot deserialize Windows OS string on Unix"))
}
}
}
#[cfg(windows)]
fn visit_enum<V>(self, visitor: V) -> Result<OsString, V::Error>
where V: EnumVisitor,
{
use std::os::windows::ffi::OsStringExt;
match try!(visitor.visit_variant()) {
(OsStringKind::Windows, variant) => {
variant.visit_newtype::<Vec<u16>>().map(|vec| OsString::from_wide(&vec))
}
(OsStringKind::Unix, _) => {
Err(Error::custom("cannot deserialize Unix OS string on Windows"))
}
}
}
}
#[cfg(all(feature = "std", any(unix, windows)))]
impl Deserialize for OsString {
fn deserialize<D>(deserializer: D) -> Result<OsString, D::Error>
where D: Deserializer
{
deserializer.deserialize_enum("OsString", OSSTR_VARIANTS, OsStringVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Deserialize> Deserialize for Box<T> {
fn deserialize<D>(deserializer: D) -> Result<Box<T>, D::Error>
@@ -1079,6 +1232,137 @@ impl Deserialize for Duration {
}
}
///////////////////////////////////////////////////////////////////////////////
// Similar to:
//
// #[derive(Deserialize)]
// #[serde(deny_unknown_fields)]
// struct Range {
// start: u64,
// end: u32,
// }
#[cfg(feature = "std")]
impl<Idx: Deserialize> Deserialize for std::ops::Range<Idx> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer
{
enum Field {
Start,
End,
};
impl Deserialize for Field {
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
where D: Deserializer
{
struct FieldVisitor;
impl Visitor for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("`start` or `end`")
}
fn visit_str<E>(self, value: &str) -> Result<Field, E>
where E: Error
{
match value {
"start" => Ok(Field::Start),
"end" => Ok(Field::End),
_ => Err(Error::unknown_field(value, FIELDS)),
}
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E>
where E: Error
{
match value {
b"start" => Ok(Field::Start),
b"end" => Ok(Field::End),
_ => {
let value = String::from_utf8_lossy(value);
Err(Error::unknown_field(&value, FIELDS))
}
}
}
}
deserializer.deserialize_struct_field(FieldVisitor)
}
}
struct RangeVisitor<Idx> {
phantom: PhantomData<Idx>,
}
impl<Idx: Deserialize> Visitor for RangeVisitor<Idx> {
type Value = std::ops::Range<Idx>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("struct Range")
}
fn visit_seq<V>(self, mut visitor: V) -> Result<std::ops::Range<Idx>, V::Error>
where V: SeqVisitor
{
let start: Idx = match try!(visitor.visit()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(0, &self));
}
};
let end: Idx = match try!(visitor.visit()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(1, &self));
}
};
Ok(start..end)
}
fn visit_map<V>(self, mut visitor: V) -> Result<std::ops::Range<Idx>, V::Error>
where V: MapVisitor
{
let mut start: Option<Idx> = None;
let mut end: Option<Idx> = None;
while let Some(key) = try!(visitor.visit_key::<Field>()) {
match key {
Field::Start => {
if start.is_some() {
return Err(<V::Error as Error>::duplicate_field("start"));
}
start = Some(try!(visitor.visit_value()));
}
Field::End => {
if end.is_some() {
return Err(<V::Error as Error>::duplicate_field("end"));
}
end = Some(try!(visitor.visit_value()));
}
}
}
let start = match start {
Some(start) => start,
None => return Err(<V::Error as Error>::missing_field("start")),
};
let end = match end {
Some(end) => end,
None => return Err(<V::Error as Error>::missing_field("end")),
};
Ok(start..end)
}
}
const FIELDS: &'static [&'static str] = &["start", "end"];
deserializer.deserialize_struct("Range", FIELDS, RangeVisitor { phantom: PhantomData })
}
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")]
+19 -99
View File
@@ -172,19 +172,7 @@ pub trait Error: Sized + error::Error {
/// containing an integer, the unexpected type is the integer and the
/// expected type is the string.
fn invalid_type(unexp: Unexpected, exp: &Expected) -> Self {
struct InvalidType<'a> {
unexp: Unexpected<'a>,
exp: &'a Expected,
}
impl<'a> Display for InvalidType<'a> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "invalid type: {}, expected {}", self.unexp, self.exp)
}
}
Error::custom(InvalidType {
unexp: unexp,
exp: exp,
})
Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
}
/// Raised when a `Deserialize` receives a value of the right type but that
@@ -201,19 +189,7 @@ pub trait Error: Sized + error::Error {
/// that is not valid UTF-8, the unexpected value is the bytes and the
/// expected value is a string.
fn invalid_value(unexp: Unexpected, exp: &Expected) -> Self {
struct InvalidValue<'a> {
unexp: Unexpected<'a>,
exp: &'a Expected,
}
impl<'a> Display for InvalidValue<'a> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "invalid value: {}, expected {}", self.unexp, self.exp)
}
}
Error::custom(InvalidValue {
unexp: unexp,
exp: exp,
})
Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp))
}
/// Raised when deserializing a sequence or map and the input data contains
@@ -226,102 +202,46 @@ pub trait Error: Sized + error::Error {
/// expected. For example `exp` might say that a tuple of size 6 was
/// expected.
fn invalid_length(len: usize, exp: &Expected) -> Self {
struct InvalidLength<'a> {
len: usize,
exp: &'a Expected,
}
impl<'a> Display for InvalidLength<'a> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "invalid length {}, expected {}", self.len, self.exp)
}
}
Error::custom(InvalidLength {
len: len,
exp: exp,
})
Error::custom(format_args!("invalid length {}, expected {}", len, exp))
}
/// Raised when a `Deserialize` enum type received a variant with an
/// unrecognized name.
fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
struct UnknownVariant<'a> {
variant: &'a str,
expected: &'static [&'static str],
if expected.is_empty() {
Error::custom(format_args!("unknown variant `{}`, there are no variants",
variant))
} else {
Error::custom(format_args!("unknown variant `{}`, expected {}",
variant,
OneOf { names: expected }))
}
impl<'a> Display for UnknownVariant<'a> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
if self.expected.is_empty() {
write!(formatter,
"unknown variant `{}`, there are no variants",
self.variant)
} else {
write!(formatter,
"unknown variant `{}`, expected {}",
self.variant,
OneOf { names: self.expected })
}
}
}
Error::custom(UnknownVariant {
variant: variant,
expected: expected,
})
}
/// Raised when a `Deserialize` struct type received a field with an
/// unrecognized name.
fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
struct UnknownField<'a> {
field: &'a str,
expected: &'static [&'static str],
if expected.is_empty() {
Error::custom(format_args!("unknown field `{}`, there are no fields",
field))
} else {
Error::custom(format_args!("unknown field `{}`, expected {}",
field,
OneOf { names: expected }))
}
impl<'a> Display for UnknownField<'a> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
if self.expected.is_empty() {
write!(formatter,
"unknown field `{}`, there are no fields",
self.field)
} else {
write!(formatter,
"unknown field `{}`, expected {}",
self.field,
OneOf { names: self.expected })
}
}
}
Error::custom(UnknownField {
field: field,
expected: expected,
})
}
/// Raised when a `Deserialize` struct type expected to receive a required
/// field with a particular name but that field was not present in the
/// input.
fn missing_field(field: &'static str) -> Self {
struct MissingField {
field: &'static str,
}
impl Display for MissingField {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "missing field `{}`", self.field)
}
}
Error::custom(MissingField { field: field })
Error::custom(format_args!("missing field `{}`", field))
}
/// Raised when a `Deserialize` struct type received more than one of the
/// same field.
fn duplicate_field(field: &'static str) -> Self {
struct DuplicateField {
field: &'static str,
}
impl Display for DuplicateField {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "duplicate field `{}`", self.field)
}
}
Error::custom(DuplicateField { field: field })
Error::custom(format_args!("duplicate field `{}`", field))
}
}
+60 -1
View File
@@ -183,13 +183,72 @@ primitive_deserializer!(i64, I64Deserializer, visit_i64);
primitive_deserializer!(isize, IsizeDeserializer, visit_i64 as i64);
primitive_deserializer!(u8, U8Deserializer, visit_u8);
primitive_deserializer!(u16, U16Deserializer, visit_u16);
primitive_deserializer!(u32, U32Deserializer, visit_u32);
primitive_deserializer!(u64, U64Deserializer, visit_u64);
primitive_deserializer!(usize, UsizeDeserializer, visit_u64 as u64);
primitive_deserializer!(f32, F32Deserializer, visit_f32);
primitive_deserializer!(f64, F64Deserializer, visit_f64);
primitive_deserializer!(char, CharDeserializer, visit_char);
/// A helper deserializer that deserializes a number.
pub struct U32Deserializer<E> {
value: u32,
marker: PhantomData<E>,
}
impl<E> ValueDeserializer<E> for u32
where E: de::Error
{
type Deserializer = U32Deserializer<E>;
fn into_deserializer(self) -> U32Deserializer<E> {
U32Deserializer {
value: self,
marker: PhantomData,
}
}
}
impl<E> de::Deserializer for U32Deserializer<E>
where E: de::Error
{
type Error = E;
forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct
struct struct_field tuple ignored_any byte_buf
}
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor
{
visitor.visit_u32(self.value)
}
fn deserialize_enum<V>(self,
_name: &str,
_variants: &'static [&'static str],
visitor: V)
-> Result<V::Value, Self::Error>
where V: de::Visitor
{
visitor.visit_enum(self)
}
}
impl<E> de::EnumVisitor for U32Deserializer<E>
where E: de::Error
{
type Error = E;
type Variant = private::UnitOnly<E>;
fn visit_variant_seed<T>(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error>
where T: de::DeserializeSeed
{
seed.deserialize(self).map(private::unit_only)
}
}
///////////////////////////////////////////////////////////////////////////////
/// A helper deserializer that deserializes a `&str`.
+2
View File
@@ -6,6 +6,8 @@ use std::borrow::Cow;
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::borrow::Cow;
pub use core::clone::Clone;
pub use core::convert::{From, Into};
pub use core::default::Default;
pub use core::fmt;
pub use core::marker::PhantomData;
+50 -2
View File
@@ -61,7 +61,7 @@
#![doc(html_root_url="https://docs.serde.rs")]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "unstable", feature(inclusive_range, nonzero, specialization, zero_one))]
#![cfg_attr(feature = "unstable", feature(nonzero, specialization, zero_one, into_boxed_c_str))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "collections", feature(collections))]
#![cfg_attr(feature = "cargo-clippy", allow(linkedlist, type_complexity, doc_markdown))]
@@ -79,7 +79,8 @@ extern crate core as actual_core;
#[cfg(feature = "std")]
mod core {
pub use std::{ops, hash, fmt, cmp, marker, mem, i8, i16, i32, i64, u8, u16, u32, u64, isize,
usize, f32, f64, char, str, num, slice, iter, cell, default, result, option};
usize, f32, f64, char, str, num, slice, iter, cell, default, result, option,
clone, convert};
#[cfg(feature = "unstable")]
pub use actual_core::nonzero;
}
@@ -105,3 +106,50 @@ mod utils;
// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;
// Re-export #[derive(Serialize, Deserialize)].
//
// This is a workaround for https://github.com/rust-lang/cargo/issues/1286.
// Without this re-export, crates that put Serde derives behind a cfg_attr would
// need to use some silly feature name that depends on both serde and
// serde_derive.
//
// [features]
// serde-impls = ["serde", "serde_derive"]
//
// [dependencies]
// serde = { version = "1.0", optional = true }
// serde_derive = { version = "1.0", optional = true }
//
// # Used like this:
// # #[cfg(feature = "serde-impls")]
// # #[macro_use]
// # extern crate serde_derive;
// #
// # #[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
// # struct S { /* ... */ }
//
// The re-exported derives allow crates to use "serde" as the name of their
// Serde feature which is more intuitive.
//
// [dependencies]
// serde = { version = "1.0", optional = true, features = ["derive"] }
//
// # Used like this:
// # #[cfg(feature = "serde")]
// # #[macro_use]
// # extern crate serde;
// #
// # #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
// # struct S { /* ... */ }
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;
+1 -16
View File
@@ -1,24 +1,9 @@
#[cfg(feature = "std")]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_method {
($func:ident($($arg:ty),*)) => {
#[inline]
fn $func<__V>(self, $(_: $arg,)* visitor: __V) -> ::std::result::Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor
{
self.deserialize(visitor)
}
};
}
#[cfg(not(feature = "std"))]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_method {
($func:ident($($arg:ty),*)) => {
#[inline]
fn $func<__V>(self, $(_: $arg,)* visitor: __V) -> ::core::result::Result<__V::Value, Self::Error>
fn $func<__V>(self, $(_: $arg,)* visitor: __V) -> $crate::export::Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor
{
self.deserialize(visitor)
+62 -90
View File
@@ -33,10 +33,7 @@ impl<M> ser::SerializeTupleVariant for SerializeTupleVariantAsMapValue<M>
type Ok = M::Ok;
type Error = M::Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
value: &T)
-> Result<(), M::Error>
{
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), M::Error> {
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push(value);
Ok(())
@@ -73,8 +70,7 @@ impl<M> ser::SerializeStructVariant for SerializeStructVariantAsMapValue<M>
fn serialize_field<T: ?Sized + Serialize>(&mut self,
key: &'static str,
value: &T)
-> Result<(), M::Error>
{
-> Result<(), M::Error> {
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push((key, value));
Ok(())
@@ -151,7 +147,9 @@ impl Serialize for Content {
Content::UnitStruct(n) => serializer.serialize_unit_struct(n),
Content::UnitVariant(n, i, v) => serializer.serialize_unit_variant(n, i, v),
Content::NewtypeStruct(n, ref c) => serializer.serialize_newtype_struct(n, &**c),
Content::NewtypeVariant(n, i, v, ref c) => serializer.serialize_newtype_variant(n, i, v, &**c),
Content::NewtypeVariant(n, i, v, ref c) => {
serializer.serialize_newtype_variant(n, i, v, &**c)
}
Content::Seq(ref elements) => elements.serialize(serializer),
Content::SeqFixedSize(ref elements) => {
use ser::SerializeSeq;
@@ -219,9 +217,7 @@ struct ContentSerializer<E> {
impl<E> ContentSerializer<E> {
fn new() -> Self {
ContentSerializer {
error: PhantomData,
}
ContentSerializer { error: PhantomData }
}
}
@@ -299,9 +295,7 @@ impl<E> Serializer for ContentSerializer<E>
Ok(Content::None)
}
fn serialize_some<T: ?Sized + Serialize>(self,
value: &T)
-> Result<Content, E> {
fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Content, E> {
Ok(Content::Some(Box::new(try!(value.serialize(self)))))
}
@@ -309,9 +303,7 @@ impl<E> Serializer for ContentSerializer<E>
Ok(Content::Unit)
}
fn serialize_unit_struct(self,
name: &'static str)
-> Result<Content, E> {
fn serialize_unit_struct(self, name: &'static str) -> Result<Content, E> {
Ok(Content::UnitStruct(name))
}
@@ -336,36 +328,33 @@ impl<E> Serializer for ContentSerializer<E>
variant: &'static str,
value: &T)
-> Result<Content, E> {
Ok(Content::NewtypeVariant(name, variant_index, variant, Box::new(try!(value.serialize(self)))))
Ok(Content::NewtypeVariant(name,
variant_index,
variant,
Box::new(try!(value.serialize(self)))))
}
fn serialize_seq(self,
len: Option<usize>)
-> Result<Self::SerializeSeq, E> {
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, E> {
Ok(SerializeSeq {
fixed_size: false,
elements: Vec::with_capacity(len.unwrap_or(0)),
error: PhantomData,
})
fixed_size: false,
elements: Vec::with_capacity(len.unwrap_or(0)),
error: PhantomData,
})
}
fn serialize_seq_fixed_size(self,
size: usize)
-> Result<Self::SerializeSeq, E> {
fn serialize_seq_fixed_size(self, size: usize) -> Result<Self::SerializeSeq, E> {
Ok(SerializeSeq {
fixed_size: true,
elements: Vec::with_capacity(size),
error: PhantomData,
})
fixed_size: true,
elements: Vec::with_capacity(size),
error: PhantomData,
})
}
fn serialize_tuple(self,
len: usize)
-> Result<Self::SerializeTuple, E> {
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, E> {
Ok(SerializeTuple {
elements: Vec::with_capacity(len),
error: PhantomData,
})
elements: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_tuple_struct(self,
@@ -373,10 +362,10 @@ impl<E> Serializer for ContentSerializer<E>
len: usize)
-> Result<Self::SerializeTupleStruct, E> {
Ok(SerializeTupleStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
})
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_tuple_variant(self,
@@ -386,33 +375,28 @@ impl<E> Serializer for ContentSerializer<E>
len: usize)
-> Result<Self::SerializeTupleVariant, E> {
Ok(SerializeTupleVariant {
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
})
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_map(self,
len: Option<usize>)
-> Result<Self::SerializeMap, E> {
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, E> {
Ok(SerializeMap {
entries: Vec::with_capacity(len.unwrap_or(0)),
key: None,
error: PhantomData,
})
entries: Vec::with_capacity(len.unwrap_or(0)),
key: None,
error: PhantomData,
})
}
fn serialize_struct(self,
name: &'static str,
len: usize)
-> Result<Self::SerializeStruct, E> {
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct, E> {
Ok(SerializeStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
})
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_struct_variant(self,
@@ -422,12 +406,12 @@ impl<E> Serializer for ContentSerializer<E>
len: usize)
-> Result<Self::SerializeStructVariant, E> {
Ok(SerializeStructVariant {
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
})
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
}
@@ -443,9 +427,7 @@ impl<E> ser::SerializeSeq for SerializeSeq<E>
type Ok = Content;
type Error = E;
fn serialize_element<T: ?Sized + Serialize>(&mut self,
value: &T)
-> Result<(), E> {
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.elements.push(value);
Ok(())
@@ -453,10 +435,10 @@ impl<E> ser::SerializeSeq for SerializeSeq<E>
fn end(self) -> Result<Content, E> {
Ok(if self.fixed_size {
Content::SeqFixedSize(self.elements)
} else {
Content::Seq(self.elements)
})
Content::SeqFixedSize(self.elements)
} else {
Content::Seq(self.elements)
})
}
}
@@ -471,9 +453,7 @@ impl<E> ser::SerializeTuple for SerializeTuple<E>
type Ok = Content;
type Error = E;
fn serialize_element<T: ?Sized + Serialize>(&mut self,
value: &T)
-> Result<(), E> {
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.elements.push(value);
Ok(())
@@ -496,9 +476,7 @@ impl<E> ser::SerializeTupleStruct for SerializeTupleStruct<E>
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
value: &T)
-> Result<(), E> {
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push(value);
Ok(())
@@ -523,9 +501,7 @@ impl<E> ser::SerializeTupleVariant for SerializeTupleVariant<E>
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
value: &T)
-> Result<(), E> {
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push(value);
Ok(())
@@ -548,17 +524,13 @@ impl<E> ser::SerializeMap for SerializeMap<E>
type Ok = Content;
type Error = E;
fn serialize_key<T: ?Sized + Serialize>(&mut self,
key: &T)
-> Result<(), E> {
fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<(), E> {
let key = try!(key.serialize(ContentSerializer::<E>::new()));
self.key = Some(key);
Ok(())
}
fn serialize_value<T: ?Sized + Serialize>(&mut self,
value: &T)
-> Result<(), E> {
fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), E> {
let key = self.key.take().expect("serialize_value called before serialize_key");
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.entries.push((key, value));
+68 -30
View File
@@ -13,15 +13,15 @@ use collections::borrow::ToOwned;
#[cfg(feature = "std")]
use core::hash::{Hash, BuildHasher};
#[cfg(feature = "unstable")]
use core::iter;
#[cfg(feature = "std")]
use std::net;
#[cfg(feature = "unstable")]
#[cfg(any(feature = "std", feature = "unstable"))]
use core::ops;
#[cfg(feature = "std")]
use std::path;
#[cfg(feature = "std")]
use std::ffi::{CString, CStr, OsString, OsStr};
#[cfg(feature = "std")]
use std::rc::Rc;
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::rc::Rc;
@@ -98,6 +98,28 @@ impl Serialize for String {
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl Serialize for CStr {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
serializer.serialize_bytes(self.to_bytes())
}
}
#[cfg(feature = "std")]
impl Serialize for CString {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
serializer.serialize_bytes(self.to_bytes())
}
}
///////////////////////////////////////////////////////////////////////////////
impl<T> Serialize for Option<T>
where T: Serialize
{
@@ -238,37 +260,18 @@ impl<T> Serialize for VecDeque<T>
serialize_seq!();
}
#[cfg(feature = "unstable")]
impl<A> Serialize for ops::Range<A>
where ops::Range<A>: ExactSizeIterator + iter::Iterator<Item = A> + Clone,
A: Serialize
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
let mut seq = try!(serializer.serialize_seq(Some(self.len())));
for e in self.clone() {
try!(seq.serialize_element(&e));
}
seq.end()
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")]
impl<A> Serialize for ops::RangeInclusive<A>
where ops::RangeInclusive<A>: ExactSizeIterator + iter::Iterator<Item = A> + Clone,
A: Serialize
{
#[inline]
#[cfg(feature = "std")]
impl<Idx: Serialize> Serialize for ops::Range<Idx> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
let mut seq = try!(serializer.serialize_seq(Some(self.len())));
for e in self.clone() {
try!(seq.serialize_element(&e));
}
seq.end()
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("Range", 2));
try!(state.serialize_field("start", &self.start));
try!(state.serialize_field("end", &self.end));
state.end()
}
}
@@ -711,6 +714,41 @@ impl Serialize for path::PathBuf {
}
}
#[cfg(all(feature = "std", any(unix, windows)))]
impl Serialize for OsStr {
#[cfg(unix)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
use std::os::unix::ffi::OsStrExt;
serializer.serialize_newtype_variant("OsString",
0,
"Unix",
self.as_bytes())
}
#[cfg(windows)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
use std::os::windows::ffi::OsStrExt;
let val = self.encode_wide().collect::<Vec<_>>();
serializer.serialize_newtype_variant("OsString",
1,
"Windows",
&val)
}
}
#[cfg(all(feature = "std", any(unix, windows)))]
#[cfg(feature = "std")]
impl Serialize for OsString {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
self.as_os_str().serialize(serializer)
}
}
#[cfg(feature = "unstable")]
impl<T> Serialize for NonZero<T>
where T: Serialize + Zeroable
+76 -9
View File
@@ -71,12 +71,11 @@
//! - VecDeque\<T\>
//! - Vec\<T\>
//! - EnumSet\<T\> (unstable)
//! - Range\<T\> (unstable)
//! - RangeInclusive\<T\> (unstable)
//! - **Miscellaneous standard library types**:
//! - Duration
//! - Path
//! - PathBuf
//! - Range\<T\>
//! - NonZero\<T\> (unstable)
//! - **Net types**:
//! - IpAddr
@@ -98,7 +97,11 @@ use std::error;
#[cfg(not(feature = "std"))]
use error;
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::string::String;
use core::fmt::Display;
#[cfg(any(feature = "std", feature = "collections"))]
use core::fmt::Write;
use core::iter::IntoIterator;
mod impls;
@@ -466,13 +469,13 @@ pub trait Serializer: Sized {
fn serialize_seq_fixed_size(self, size: usize) -> Result<Self::SerializeSeq, Self::Error>;
/// Begin to serialize a tuple. This call must be followed by zero or more
/// calls to `serialize_field`, then a call to `end`.
/// calls to `serialize_element`, then a call to `end`.
///
/// ```rust,ignore
/// let mut tup = serializer.serialize_tuple(3)?;
/// tup.serialize_field(&self.0)?;
/// tup.serialize_field(&self.1)?;
/// tup.serialize_field(&self.2)?;
/// tup.serialize_element(&self.0)?;
/// tup.serialize_element(&self.1)?;
/// tup.serialize_element(&self.2)?;
/// tup.end()
/// ```
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error>;
@@ -616,6 +619,70 @@ pub trait Serializer: Sized {
}
serializer.end()
}
/// Serialize a string produced by an implementation of `Display`.
///
/// The default implementation builds a heap-allocated `String` and
/// delegates to `serialize_str`. Serializers are encouraged to provide a
/// more efficient implementation if possible.
///
/// ```rust
/// # use serde::{Serialize, Serializer};
/// # struct DateTime;
/// # impl DateTime {
/// # fn naive_local(&self) -> () { () }
/// # fn offset(&self) -> () { () }
/// # }
/// impl Serialize for DateTime {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// {
/// serializer.collect_str(&format_args!("{:?}{:?}",
/// self.naive_local(),
/// self.offset()))
/// }
/// }
/// ```
#[cfg(any(feature = "std", feature = "collections"))]
fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
where T: Display
{
let mut string = String::new();
write!(string, "{}", value).unwrap();
self.serialize_str(&string)
}
/// Serialize a string produced by an implementation of `Display`.
///
/// The default implementation returns an error unconditionally when
/// compiled with `no_std`.
///
/// ```rust
/// # use serde::{Serialize, Serializer};
/// # struct DateTime;
/// # impl DateTime {
/// # fn naive_local(&self) -> () { () }
/// # fn offset(&self) -> () { () }
/// # }
/// impl Serialize for DateTime {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// {
/// serializer.collect_str(&format_args!("{:?}{:?}",
/// self.naive_local(),
/// self.offset()))
/// }
/// }
/// ```
#[cfg(not(any(feature = "std", feature = "collections")))]
fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
where T: Display
{
// TODO https://github.com/serde-rs/serde/issues/805
// Remove this impl and force no_std formats to implement collect_str.
let _ = value;
Err(Error::custom("this no_std format does not support serializing strings with collect_str"))
}
}
/// Returned from `Serializer::serialize_seq` and
@@ -646,9 +713,9 @@ pub trait SerializeSeq {
///
/// ```rust,ignore
/// let mut tup = serializer.serialize_tuple(3)?;
/// tup.serialize_field(&self.0)?;
/// tup.serialize_field(&self.1)?;
/// tup.serialize_field(&self.2)?;
/// tup.serialize_element(&self.0)?;
/// tup.serialize_element(&self.1)?;
/// tup.serialize_element(&self.2)?;
/// tup.end()
/// ```
pub trait SerializeTuple {
+14 -12
View File
@@ -11,18 +11,18 @@ pub fn serialize_tagged_newtype<S, T>(serializer: S,
variant_ident: &'static str,
tag: &'static str,
variant_name: &'static str,
value: T)
value: &T)
-> Result<S::Ok, S::Error>
where S: Serializer,
T: Serialize
{
value.serialize(TaggedSerializer {
type_ident: type_ident,
variant_ident: variant_ident,
tag: tag,
variant_name: variant_name,
delegate: serializer,
})
type_ident: type_ident,
variant_ident: variant_ident,
tag: tag,
variant_name: variant_name,
delegate: serializer,
})
}
struct TaggedSerializer<S> {
@@ -81,7 +81,9 @@ impl Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter,
"cannot serialize tagged newtype variant {}::{} containing {}",
self.type_ident, self.variant_ident, self.ty)
self.type_ident,
self.variant_ident,
self.ty)
}
}
@@ -90,10 +92,10 @@ impl<S> TaggedSerializer<S>
{
fn bad_type(self, what: Unsupported) -> S::Error {
ser::Error::custom(Error {
type_ident: self.type_ident,
variant_ident: self.variant_ident,
ty: what,
})
type_ident: self.type_ident,
variant_ident: self.variant_ident,
ty: what,
})
}
}
+2 -2
View File
@@ -59,8 +59,8 @@ const Pattern_White_Space_table: &'static [(char, char)] = &[('\u{9}', '\u{d}'),
fn bsearch_range_table(c: char, r: &'static [(char, char)]) -> bool {
use core::cmp::Ordering::{Equal, Less, Greater};
r.binary_search_by(|&(lo, hi)| if c < lo {
Greater
} else if hi < c {
Greater
} else if hi < c {
Less
} else {
Equal
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_codegen_internals"
version = "0.14.0"
version = "0.14.2"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "AST representation used by Serde codegen. Unstable."
+17 -1
View File
@@ -38,7 +38,7 @@ impl<'a> Item<'a> {
pub fn from_ast(cx: &Ctxt, item: &'a syn::MacroInput) -> Item<'a> {
let attrs = attr::Item::from_ast(cx, item);
let body = match item.body {
let mut body = match item.body {
syn::Body::Enum(ref variants) => Body::Enum(enum_from_ast(cx, variants)),
syn::Body::Struct(ref variant_data) => {
let (style, fields) = struct_from_ast(cx, variant_data);
@@ -46,6 +46,22 @@ impl<'a> Item<'a> {
}
};
match body {
Body::Enum(ref mut variants) => {
for ref mut variant in variants {
variant.attrs.rename_by_rule(attrs.rename_all());
for ref mut field in &mut variant.fields {
field.attrs.rename_by_rule(variant.attrs.rename_all());
}
}
}
Body::Struct(_, ref mut fields) => {
for field in fields {
field.attrs.rename_by_rule(attrs.rename_all());
}
}
}
Item {
ident: item.ident.clone(),
attrs: attrs,
+129 -6
View File
@@ -2,6 +2,7 @@ use Ctxt;
use syn;
use syn::MetaItem::{List, NameValue, Word};
use syn::NestedMetaItem::{Literal, MetaItem};
use std::str::FromStr;
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
// are `attr::Item::from_ast`, `attr::Variant::from_ast`, and
@@ -11,6 +12,8 @@ use syn::NestedMetaItem::{Literal, MetaItem};
// user will see errors simultaneously for all bad attributes in the crate
// rather than just the first.
pub use case::RenameRule;
struct Attr<'c, T> {
cx: &'c Ctxt,
name: &'static str,
@@ -91,9 +94,12 @@ pub struct Item {
name: Name,
deny_unknown_fields: bool,
default: Default,
rename_all: RenameRule,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
tag: EnumTag,
from_type: Option<syn::Ty>,
into_type: Option<syn::Ty>,
}
/// Styles of representing an enum.
@@ -135,11 +141,14 @@ impl Item {
let mut de_name = Attr::none(cx, "rename");
let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields");
let mut default = Attr::none(cx, "default");
let mut rename_all = Attr::none(cx, "rename_all");
let mut ser_bound = Attr::none(cx, "bound");
let mut de_bound = Attr::none(cx, "bound");
let mut untagged = BoolAttr::none(cx, "untagged");
let mut internal_tag = Attr::none(cx, "tag");
let mut content = Attr::none(cx, "content");
let mut from_type = Attr::none(cx, "from");
let mut into_type = Attr::none(cx, "into");
for meta_items in item.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
@@ -160,6 +169,20 @@ impl Item {
}
}
// Parse `#[serde(rename_all="foo")]`
MetaItem(NameValue(ref name, ref lit)) if name == "rename_all" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match RenameRule::from_str(&s) {
Ok(rename_rule) => rename_all.set(rename_rule),
Err(()) => {
cx.error(format!("unknown rename rule for #[serde(rename_all \
= {:?})]",
s))
}
}
}
}
// Parse `#[serde(deny_unknown_fields)]`
MetaItem(Word(ref name)) if name == "deny_unknown_fields" => {
deny_unknown_fields.set_true();
@@ -244,12 +267,27 @@ impl Item {
content.set(s);
}
syn::Body::Struct(_) => {
cx.error("#[serde(content = \"...\")] can only be used on enums")
cx.error("#[serde(content = \"...\")] can only be used on \
enums")
}
}
}
}
// Parse `#[serde(from = "Type")]
MetaItem(NameValue(ref name, ref lit)) if name == "from" => {
if let Ok(from_ty) = parse_lit_into_ty(cx, name.as_ref(), lit) {
from_type.set_opt(Some(from_ty));
}
}
// Parse `#[serde(into = "Type")]
MetaItem(NameValue(ref name, ref lit)) if name == "into" => {
if let Ok(into_ty) = parse_lit_into_ty(cx, name.as_ref(), lit) {
into_type.set_opt(Some(into_ty));
}
}
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde container attribute `{}`",
meta_item.name()));
@@ -297,7 +335,10 @@ impl Item {
EnumTag::External
}
(false, Some(tag), Some(content)) => {
EnumTag::Adjacent { tag: tag, content: content }
EnumTag::Adjacent {
tag: tag,
content: content,
}
}
(true, Some(_), Some(_)) => {
cx.error("untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]");
@@ -312,9 +353,12 @@ impl Item {
},
deny_unknown_fields: deny_unknown_fields.get(),
default: default.get().unwrap_or(Default::None),
rename_all: rename_all.get().unwrap_or(RenameRule::None),
ser_bound: ser_bound.get(),
de_bound: de_bound.get(),
tag: tag,
from_type: from_type.get(),
into_type: into_type.get(),
}
}
@@ -322,6 +366,10 @@ impl Item {
&self.name
}
pub fn rename_all(&self) -> &RenameRule {
&self.rename_all
}
pub fn deny_unknown_fields(&self) -> bool {
self.deny_unknown_fields
}
@@ -341,12 +389,23 @@ impl Item {
pub fn tag(&self) -> &EnumTag {
&self.tag
}
pub fn from_type(&self) -> Option<&syn::Ty> {
self.from_type.as_ref()
}
pub fn into_type(&self) -> Option<&syn::Ty> {
self.into_type.as_ref()
}
}
/// Represents variant attribute information
#[derive(Debug)]
pub struct Variant {
name: Name,
ser_renamed: bool,
de_renamed: bool,
rename_all: RenameRule,
skip_deserializing: bool,
skip_serializing: bool,
}
@@ -357,6 +416,7 @@ impl Variant {
let mut de_name = Attr::none(cx, "rename");
let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing");
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
let mut rename_all = Attr::none(cx, "rename_all");
for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
@@ -376,6 +436,21 @@ impl Variant {
de_name.set_opt(de);
}
}
// Parse `#[serde(rename_all="foo")]`
MetaItem(NameValue(ref name, ref lit)) if name == "rename_all" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match RenameRule::from_str(&s) {
Ok(rename_rule) => rename_all.set(rename_rule),
Err(()) => {
cx.error(format!("unknown rename rule for #[serde(rename_all \
= {:?})]",
s))
}
}
}
}
// Parse `#[serde(skip_deserializing)]`
MetaItem(Word(ref name)) if name == "skip_deserializing" => {
skip_deserializing.set_true();
@@ -396,11 +471,18 @@ impl Variant {
}
}
let ser_name = ser_name.get();
let ser_renamed = ser_name.is_some();
let de_name = de_name.get();
let de_renamed = de_name.is_some();
Variant {
name: Name {
serialize: ser_name.get().unwrap_or_else(|| variant.ident.to_string()),
deserialize: de_name.get().unwrap_or_else(|| variant.ident.to_string()),
serialize: ser_name.unwrap_or_else(|| variant.ident.to_string()),
deserialize: de_name.unwrap_or_else(|| variant.ident.to_string()),
},
ser_renamed: ser_renamed,
de_renamed: de_renamed,
rename_all: rename_all.get().unwrap_or(RenameRule::None),
skip_deserializing: skip_deserializing.get(),
skip_serializing: skip_serializing.get(),
}
@@ -410,6 +492,19 @@ impl Variant {
&self.name
}
pub fn rename_by_rule(&mut self, rule: &RenameRule) {
if !self.ser_renamed {
self.name.serialize = rule.apply_to_variant(&self.name.serialize);
}
if !self.de_renamed {
self.name.deserialize = rule.apply_to_variant(&self.name.deserialize);
}
}
pub fn rename_all(&self) -> &RenameRule {
&self.rename_all
}
pub fn skip_deserializing(&self) -> bool {
self.skip_deserializing
}
@@ -423,6 +518,8 @@ impl Variant {
#[derive(Debug)]
pub struct Field {
name: Name,
ser_renamed: bool,
de_renamed: bool,
skip_serializing: bool,
skip_deserializing: bool,
skip_serializing_if: Option<syn::Path>,
@@ -571,11 +668,17 @@ impl Field {
default.set_if_none(Default::Default);
}
let ser_name = ser_name.get();
let ser_renamed = ser_name.is_some();
let de_name = de_name.get();
let de_renamed = de_name.is_some();
Field {
name: Name {
serialize: ser_name.get().unwrap_or_else(|| ident.clone()),
deserialize: de_name.get().unwrap_or(ident),
serialize: ser_name.unwrap_or_else(|| ident.clone()),
deserialize: de_name.unwrap_or(ident),
},
ser_renamed: ser_renamed,
de_renamed: de_renamed,
skip_serializing: skip_serializing.get(),
skip_deserializing: skip_deserializing.get(),
skip_serializing_if: skip_serializing_if.get(),
@@ -591,6 +694,15 @@ impl Field {
&self.name
}
pub fn rename_by_rule(&mut self, rule: &RenameRule) {
if !self.ser_renamed {
self.name.serialize = rule.apply_to_field(&self.name.serialize);
}
if !self.de_renamed {
self.name.deserialize = rule.apply_to_field(&self.name.deserialize);
}
}
pub fn skip_serializing(&self) -> bool {
self.skip_serializing
}
@@ -713,3 +825,14 @@ fn parse_lit_into_where(cx: &Ctxt,
syn::parse_where_clause(&where_string).map(|wh| wh.predicates).map_err(|err| cx.error(err))
}
fn parse_lit_into_ty(cx: &Ctxt,
attr_name: &str,
lit: &syn::Lit)
-> Result<syn::Ty, ()> {
let string = try!(get_string_from_lit(cx, attr_name, attr_name, lit));
syn::parse_type(&string).map_err(|_| {
cx.error(format!("failed to parse type: {} = {:?}", attr_name, string))
})
}
+115
View File
@@ -0,0 +1,115 @@
use std::ascii::AsciiExt;
use std::str::FromStr;
use self::RenameRule::*;
#[derive(Debug, PartialEq)]
pub enum RenameRule {
/// Don't apply a default rename rule.
None,
/// Rename direct children to "PascalCase" style, as typically used for enum variants.
PascalCase,
/// Rename direct children to "camelCase" style.
CamelCase,
/// Rename direct children to "snake_case" style, as commonly used for fields.
SnakeCase,
/// Rename direct children to "SCREAMING_SNAKE_CASE" style, as commonly used for constants.
ScreamingSnakeCase,
/// Rename direct children to "kebab-case" style.
KebabCase,
}
impl RenameRule {
pub fn apply_to_variant(&self, variant: &str) -> String {
match *self {
None | PascalCase => variant.to_owned(),
CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
SnakeCase => {
let mut snake = String::new();
for (i, ch) in variant.char_indices() {
if i > 0 && ch.is_uppercase() {
snake.push('_');
}
snake.push(ch.to_ascii_lowercase());
}
snake
}
ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(),
KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"),
}
}
pub fn apply_to_field(&self, field: &str) -> String {
match *self {
None | SnakeCase => field.to_owned(),
PascalCase => {
let mut pascal = String::new();
let mut capitalize = true;
for ch in field.chars() {
if ch == '_' {
capitalize = true;
} else if capitalize {
pascal.push(ch.to_ascii_uppercase());
capitalize = false;
} else {
pascal.push(ch);
}
}
pascal
}
CamelCase => {
let pascal = PascalCase.apply_to_field(field);
pascal[..1].to_ascii_lowercase() + &pascal[1..]
}
ScreamingSnakeCase => field.to_ascii_uppercase(),
KebabCase => field.replace('_', "-"),
}
}
}
impl FromStr for RenameRule {
type Err = ();
fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> {
match rename_all_str {
"PascalCase" => Ok(PascalCase),
"camelCase" => Ok(CamelCase),
"snake_case" => Ok(SnakeCase),
"SCREAMING_SNAKE_CASE" => Ok(ScreamingSnakeCase),
"kebab-case" => Ok(KebabCase),
_ => Err(()),
}
}
}
#[test]
fn rename_variants() {
for &(original, camel, snake, screaming, kebab) in
&[("Outcome", "outcome", "outcome", "OUTCOME", "outcome"),
("VeryTasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty"),
("A", "a", "a", "A", "a"),
("Z42", "z42", "z42", "Z42", "z42")] {
assert_eq!(None.apply_to_variant(original), original);
assert_eq!(PascalCase.apply_to_variant(original), original);
assert_eq!(CamelCase.apply_to_variant(original), camel);
assert_eq!(SnakeCase.apply_to_variant(original), snake);
assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming);
assert_eq!(KebabCase.apply_to_variant(original), kebab);
}
}
#[test]
fn rename_fields() {
for &(original, pascal, camel, screaming, kebab) in
&[("outcome", "Outcome", "outcome", "OUTCOME", "outcome"),
("very_tasty", "VeryTasty", "veryTasty", "VERY_TASTY", "very-tasty"),
("a", "A", "a", "A", "a"),
("z42", "Z42", "z42", "Z42", "z42")] {
assert_eq!(None.apply_to_field(original), original);
assert_eq!(PascalCase.apply_to_field(original), pascal);
assert_eq!(CamelCase.apply_to_field(original), camel);
assert_eq!(SnakeCase.apply_to_field(original), original);
assert_eq!(ScreamingSnakeCase.apply_to_field(original), screaming);
assert_eq!(KebabCase.apply_to_field(original), kebab);
}
}
+2
View File
@@ -5,3 +5,5 @@ pub mod attr;
mod ctxt;
pub use ctxt::Ctxt;
mod case;
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_derive"
version = "0.9.9"
version = "0.9.13"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
@@ -23,5 +23,5 @@ proc-macro = true
[dependencies]
quote = "0.3.8"
serde_codegen_internals = { version = "=0.14.0", default-features = false, path = "../serde_codegen_internals" }
serde_codegen_internals = { version = "=0.14.2", default-features = false, path = "../serde_codegen_internals" }
syn = { version = "0.11", features = ["visit"] }
+118 -106
View File
@@ -27,7 +27,7 @@ pub fn expand_derive_deserialize(item: &syn::DeriveInput) -> Result<Tokens, Stri
extern crate serde as _serde;
#[automatically_derived]
impl #impl_generics _serde::Deserialize for #ident #ty_generics #where_clause {
fn deserialize<__D>(deserializer: __D) -> _serde::export::Result<Self, __D::Error>
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where __D: _serde::Deserializer
{
#body
@@ -85,36 +85,46 @@ fn requires_default(attrs: &attr::Field) -> bool {
}
fn deserialize_body(item: &Item, generics: &syn::Generics) -> Fragment {
match item.body {
Body::Enum(ref variants) => {
deserialize_item_enum(&item.ident, generics, variants, &item.attrs)
}
Body::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) {
panic!("struct has unnamed fields");
if let Some(from_type) = item.attrs.from_type() {
deserialize_from(from_type)
} else {
match item.body {
Body::Enum(ref variants) => {
deserialize_item_enum(&item.ident, generics, variants, &item.attrs)
}
deserialize_struct(&item.ident,
None,
generics,
fields,
&item.attrs,
None)
}
Body::Struct(Style::Tuple, ref fields) |
Body::Struct(Style::Newtype, ref fields) => {
if fields.iter().any(|field| field.ident.is_some()) {
panic!("tuple struct has named fields");
Body::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) {
panic!("struct has unnamed fields");
}
deserialize_struct(&item.ident,
None,
generics,
fields,
&item.attrs,
None)
}
deserialize_tuple(&item.ident,
None,
generics,
fields,
&item.attrs,
None)
Body::Struct(Style::Tuple, ref fields) |
Body::Struct(Style::Newtype, ref fields) => {
if fields.iter().any(|field| field.ident.is_some()) {
panic!("tuple struct has named fields");
}
deserialize_tuple(&item.ident,
None,
generics,
fields,
&item.attrs,
None)
}
Body::Struct(Style::Unit, _) => deserialize_unit_struct(&item.ident, &item.attrs),
}
Body::Struct(Style::Unit, _) => deserialize_unit_struct(&item.ident, &item.attrs),
}
}
fn deserialize_from(from_type: &syn::Ty) -> Fragment {
quote_block! {
_serde::export::Result::map(
<#from_type as _serde::Deserialize>::deserialize(__deserializer),
_serde::export::From::from)
}
}
@@ -135,20 +145,20 @@ fn deserialize_unit_struct(ident: &syn::Ident, item_attrs: &attr::Item) -> Fragm
#[inline]
fn visit_unit<__E>(self) -> _serde::export::Result<#ident, __E>
where __E: _serde::de::Error,
where __E: _serde::de::Error
{
_serde::export::Ok(#ident)
}
#[inline]
fn visit_seq<__V>(self, _: __V) -> _serde::export::Result<#ident, __V::Error>
where __V: _serde::de::SeqVisitor,
where __V: _serde::de::SeqVisitor
{
_serde::export::Ok(#ident)
}
}
deserializer.deserialize_unit_struct(#type_name, __Visitor)
_serde::Deserializer::deserialize_unit_struct(__deserializer, #type_name, __Visitor)
}
}
@@ -187,20 +197,20 @@ fn deserialize_tuple(ident: &syn::Ident,
let dispatch = if let Some(deserializer) = deserializer {
quote!(_serde::Deserializer::deserialize_tuple(#deserializer, #nfields, #visitor_expr))
} else if is_enum {
quote!(_serde::de::VariantVisitor::visit_tuple(visitor, #nfields, #visitor_expr))
quote!(_serde::de::VariantVisitor::visit_tuple(__visitor, #nfields, #visitor_expr))
} else if nfields == 1 {
let type_name = item_attrs.name().deserialize_name();
quote!(_serde::Deserializer::deserialize_newtype_struct(deserializer, #type_name, #visitor_expr))
quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr))
} else {
let type_name = item_attrs.name().deserialize_name();
quote!(_serde::Deserializer::deserialize_tuple_struct(deserializer, #type_name, #nfields, #visitor_expr))
quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #nfields, #visitor_expr))
};
let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing());
let visitor_var = if all_skipped {
quote!(_)
} else {
quote!(mut visitor)
quote!(mut __visitor)
};
quote_block! {
@@ -255,21 +265,22 @@ fn deserialize_seq(ident: &syn::Ident,
let visit = match field.attrs.deserialize_with() {
None => {
let field_ty = &field.ty;
quote!(try!(_serde::de::SeqVisitor::visit::<#field_ty>(&mut visitor)))
quote!(try!(_serde::de::SeqVisitor::visit::<#field_ty>(&mut __visitor)))
}
Some(path) => {
let (wrapper, wrapper_ty) = wrap_deserialize_with(
ident, generics, field.ty, path);
quote!({
#wrapper
try!(_serde::de::SeqVisitor::visit::<#wrapper_ty>(&mut visitor))
.map(|wrap| wrap.value)
_serde::export::Option::map(
try!(_serde::de::SeqVisitor::visit::<#wrapper_ty>(&mut __visitor)),
|__wrap| __wrap.value)
})
}
};
let assign = quote! {
let #var = match #visit {
Some(value) => { value },
Some(__value) => __value,
None => {
return _serde::export::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting));
}
@@ -321,7 +332,7 @@ fn deserialize_newtype_struct(ident: &syn::Ident,
quote! {
#[inline]
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
where __E: _serde::Deserializer,
where __E: _serde::Deserializer
{
_serde::export::Ok(#type_path(#value))
}
@@ -366,12 +377,12 @@ fn deserialize_struct(ident: &syn::Ident,
}
} else if is_enum {
quote! {
_serde::de::VariantVisitor::visit_struct(visitor, FIELDS, #visitor_expr)
_serde::de::VariantVisitor::visit_struct(__visitor, FIELDS, #visitor_expr)
}
} else {
let type_name = item_attrs.name().deserialize_name();
quote! {
_serde::Deserializer::deserialize_struct(deserializer, #type_name, FIELDS, #visitor_expr)
_serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr)
}
};
@@ -379,7 +390,7 @@ fn deserialize_struct(ident: &syn::Ident,
let visitor_var = if all_skipped {
quote!(_)
} else {
quote!(mut visitor)
quote!(mut __visitor)
};
let visit_seq = if is_untagged {
@@ -413,7 +424,7 @@ fn deserialize_struct(ident: &syn::Ident,
#visit_seq
#[inline]
fn visit_map<__V>(self, mut visitor: __V) -> _serde::export::Result<Self::Value, __V::Error>
fn visit_map<__V>(self, mut __visitor: __V) -> _serde::export::Result<Self::Value, __V::Error>
where __V: _serde::de::MapVisitor
{
#visit_map
@@ -495,7 +506,7 @@ fn deserialize_externally_tagged_enum(ident: &syn::Ident,
item_attrs));
quote! {
(__Field::#variant_name, visitor) => #block
(__Field::#variant_name, __visitor) => #block
}
});
@@ -505,14 +516,15 @@ fn deserialize_externally_tagged_enum(ident: &syn::Ident,
// all variants have `#[serde(skip_deserializing)]`.
quote! {
// FIXME: Once we drop support for Rust 1.15:
// let _serde::export::Err(err) = _serde::de::EnumVisitor::visit_variant::<__Field>(visitor);
// _serde::export::Err(err)
_serde::de::EnumVisitor::visit_variant::<__Field>(visitor)
.map(|(impossible, _)| match impossible {})
// let _serde::export::Err(__err) = _serde::de::EnumVisitor::visit_variant::<__Field>(__visitor);
// _serde::export::Err(__err)
_serde::export::Result::map(
_serde::de::EnumVisitor::visit_variant::<__Field>(__visitor),
|(__impossible, _)| match __impossible {})
}
} else {
quote! {
match try!(_serde::de::EnumVisitor::visit_variant(visitor)) {
match try!(_serde::de::EnumVisitor::visit_variant(__visitor)) {
#(#variant_arms)*
}
}
@@ -532,8 +544,8 @@ fn deserialize_externally_tagged_enum(ident: &syn::Ident,
_serde::export::fmt::Formatter::write_str(formatter, #expecting)
}
fn visit_enum<__V>(self, visitor: __V) -> _serde::export::Result<Self::Value, __V::Error>
where __V: _serde::de::EnumVisitor,
fn visit_enum<__V>(self, __visitor: __V) -> _serde::export::Result<Self::Value, __V::Error>
where __V: _serde::de::EnumVisitor
{
#match_variant
}
@@ -541,7 +553,7 @@ fn deserialize_externally_tagged_enum(ident: &syn::Ident,
#variants_stmt
_serde::Deserializer::deserialize_enum(deserializer, #type_name, VARIANTS,
_serde::Deserializer::deserialize_enum(__deserializer, #type_name, VARIANTS,
__Visitor {
marker: _serde::export::PhantomData::<#ident #ty_generics>,
})
@@ -581,7 +593,7 @@ fn deserialize_internally_tagged_enum(ident: &syn::Ident,
generics,
variant,
item_attrs,
quote!(_serde::de::private::ContentDeserializer::<__D::Error>::new(_tagged.content)),
quote!(_serde::de::private::ContentDeserializer::<__D::Error>::new(__tagged.content)),
));
quote! {
@@ -594,11 +606,11 @@ fn deserialize_internally_tagged_enum(ident: &syn::Ident,
#variants_stmt
let _tagged = try!(_serde::Deserializer::deserialize(
deserializer,
let __tagged = try!(_serde::Deserializer::deserialize(
__deserializer,
_serde::de::private::TaggedContentVisitor::<__Field>::new(#tag)));
match _tagged.tag {
match __tagged.tag {
#(#variant_arms)*
}
}
@@ -639,7 +651,7 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
generics,
variant,
item_attrs,
quote!(_deserializer),
quote!(__deserializer),
));
quote! {
@@ -696,7 +708,7 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
let visit_third_key = quote! {
// Visit the third key in the map, hopefully there isn't one.
match try!(_serde::de::MapVisitor::visit_key_seed(&mut visitor, #tag_or_content)) {
match try!(_serde::de::MapVisitor::visit_key_seed(&mut __visitor, #tag_or_content)) {
_serde::export::Some(_serde::de::private::TagOrContentField::Tag) => {
_serde::export::Err(<__V::Error as _serde::de::Error>::duplicate_field(#tag))
}
@@ -720,7 +732,7 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
impl #impl_generics _serde::de::DeserializeSeed for __Seed #ty_generics #where_clause {
type Value = #ident #ty_generics;
fn deserialize<__D>(self, _deserializer: __D) -> _serde::export::Result<Self::Value, __D::Error>
fn deserialize<__D>(self, __deserializer: __D) -> _serde::export::Result<Self::Value, __D::Error>
where __D: _serde::Deserializer
{
match self.field {
@@ -740,24 +752,24 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
_serde::export::fmt::Formatter::write_str(formatter, #expecting)
}
fn visit_map<__V>(self, mut visitor: __V) -> _serde::export::Result<Self::Value, __V::Error>
fn visit_map<__V>(self, mut __visitor: __V) -> _serde::export::Result<Self::Value, __V::Error>
where __V: _serde::de::MapVisitor
{
// Visit the first key.
match try!(_serde::de::MapVisitor::visit_key_seed(&mut visitor, #tag_or_content)) {
match try!(_serde::de::MapVisitor::visit_key_seed(&mut __visitor, #tag_or_content)) {
// First key is the tag.
_serde::export::Some(_serde::de::private::TagOrContentField::Tag) => {
// Parse the tag.
let __field = try!(_serde::de::MapVisitor::visit_value(&mut visitor));
let __field = try!(_serde::de::MapVisitor::visit_value(&mut __visitor));
// Visit the second key.
match try!(_serde::de::MapVisitor::visit_key_seed(&mut visitor, #tag_or_content)) {
match try!(_serde::de::MapVisitor::visit_key_seed(&mut __visitor, #tag_or_content)) {
// Second key is a duplicate of the tag.
_serde::export::Some(_serde::de::private::TagOrContentField::Tag) => {
_serde::export::Err(<__V::Error as _serde::de::Error>::duplicate_field(#tag))
}
// Second key is the content.
_serde::export::Some(_serde::de::private::TagOrContentField::Content) => {
let __ret = try!(_serde::de::MapVisitor::visit_value_seed(&mut visitor, __Seed { field: __field, marker: _serde::export::PhantomData }));
let __ret = try!(_serde::de::MapVisitor::visit_value_seed(&mut __visitor, __Seed { field: __field, marker: _serde::export::PhantomData }));
// Visit the third key, hopefully there isn't one.
#visit_third_key
}
@@ -768,14 +780,14 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
// First key is the content.
_serde::export::Some(_serde::de::private::TagOrContentField::Content) => {
// Buffer up the content.
let __content = try!(_serde::de::MapVisitor::visit_value::<_serde::de::private::Content>(&mut visitor));
let __content = try!(_serde::de::MapVisitor::visit_value::<_serde::de::private::Content>(&mut __visitor));
// Visit the second key.
match try!(_serde::de::MapVisitor::visit_key_seed(&mut visitor, #tag_or_content)) {
match try!(_serde::de::MapVisitor::visit_key_seed(&mut __visitor, #tag_or_content)) {
// Second key is the tag.
_serde::export::Some(_serde::de::private::TagOrContentField::Tag) => {
let _deserializer = _serde::de::private::ContentDeserializer::<__V::Error>::new(__content);
let __deserializer = _serde::de::private::ContentDeserializer::<__V::Error>::new(__content);
// Parse the tag.
let __ret = try!(match try!(_serde::de::MapVisitor::visit_value(&mut visitor)) {
let __ret = try!(match try!(_serde::de::MapVisitor::visit_value(&mut __visitor)) {
// Deserialize the buffered content now that we know the variant.
#(#variant_arms)*
});
@@ -799,14 +811,14 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
}
}
fn visit_seq<__V>(self, mut visitor: __V) -> _serde::export::Result<Self::Value, __V::Error>
fn visit_seq<__V>(self, mut __visitor: __V) -> _serde::export::Result<Self::Value, __V::Error>
where __V: _serde::de::SeqVisitor
{
// Visit the first element - the tag.
match try!(_serde::de::SeqVisitor::visit(&mut visitor)) {
match try!(_serde::de::SeqVisitor::visit(&mut __visitor)) {
_serde::export::Some(__field) => {
// Visit the second element - the content.
match try!(_serde::de::SeqVisitor::visit_seed(&mut visitor, __Seed { field: __field, marker: _serde::export::PhantomData })) {
match try!(_serde::de::SeqVisitor::visit_seed(&mut __visitor, __Seed { field: __field, marker: _serde::export::PhantomData })) {
_serde::export::Some(__ret) => _serde::export::Ok(__ret),
// There is no second element.
_serde::export::None => {
@@ -823,7 +835,7 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
}
const FIELDS: &'static [&'static str] = &[#tag, #content];
_serde::Deserializer::deserialize_struct(deserializer, #type_name, FIELDS,
_serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS,
__Visitor { marker: _serde::export::PhantomData::<#ident #ty_generics> })
}
}
@@ -841,7 +853,7 @@ fn deserialize_untagged_enum(ident: &syn::Ident,
generics,
variant,
item_attrs,
quote!(_serde::de::private::ContentRefDeserializer::<__D::Error>::new(&_content)),
quote!(_serde::de::private::ContentRefDeserializer::<__D::Error>::new(&__content)),
))
});
@@ -854,11 +866,11 @@ fn deserialize_untagged_enum(ident: &syn::Ident,
let fallthrough_msg = format!("data did not match any variant of untagged enum {}", ident);
quote_block! {
let _content = try!(<_serde::de::private::Content as _serde::Deserialize>::deserialize(deserializer));
let __content = try!(<_serde::de::private::Content as _serde::Deserialize>::deserialize(__deserializer));
#(
if let _serde::export::Ok(ok) = #attempts {
return _serde::export::Ok(ok);
if let _serde::export::Ok(__ok) = #attempts {
return _serde::export::Ok(__ok);
}
)*
@@ -876,7 +888,7 @@ fn deserialize_externally_tagged_variant(ident: &syn::Ident,
match variant.style {
Style::Unit => {
quote_block! {
try!(_serde::de::VariantVisitor::visit_unit(visitor));
try!(_serde::de::VariantVisitor::visit_unit(__visitor));
_serde::export::Ok(#ident::#variant_ident)
}
}
@@ -990,7 +1002,7 @@ fn deserialize_externally_tagged_newtype_variant(ident: &syn::Ident,
let field_ty = &field.ty;
quote_expr! {
_serde::export::Result::map(
_serde::de::VariantVisitor::visit_newtype::<#field_ty>(visitor),
_serde::de::VariantVisitor::visit_newtype::<#field_ty>(__visitor),
#ident::#variant_ident)
}
}
@@ -1000,8 +1012,8 @@ fn deserialize_externally_tagged_newtype_variant(ident: &syn::Ident,
quote_block! {
#wrapper
_serde::export::Result::map(
_serde::de::VariantVisitor::visit_newtype::<#wrapper_ty>(visitor),
|_wrapper| #ident::#variant_ident(_wrapper.value))
_serde::de::VariantVisitor::visit_newtype::<#wrapper_ty>(__visitor),
|__wrapper| #ident::#variant_ident(__wrapper.value))
}
}
}
@@ -1029,7 +1041,7 @@ fn deserialize_untagged_newtype_variant(ident: &syn::Ident,
#wrapper
_serde::export::Result::map(
<#wrapper_ty as _serde::Deserialize>::deserialize(#deserializer),
|_wrapper| #ident::#variant_ident(_wrapper.value))
|__wrapper| #ident::#variant_ident(__wrapper.value))
}
}
}
@@ -1053,15 +1065,15 @@ fn deserialize_field_visitor(fields: Vec<(String, Ident)>,
let variant_indices = 0u32..;
let fallthrough_msg = format!("variant index 0 <= i < {}", fields.len());
Some(quote! {
fn visit_u32<__E>(self, value: u32) -> _serde::export::Result<__Field, __E>
fn visit_u32<__E>(self, __value: u32) -> _serde::export::Result<__Field, __E>
where __E: _serde::de::Error
{
match value {
match __value {
#(
#variant_indices => _serde::export::Ok(__Field::#field_idents),
)*
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(value as u64),
_serde::de::Unexpected::Unsigned(__value as u64),
&#fallthrough_msg))
}
}
@@ -1072,11 +1084,11 @@ fn deserialize_field_visitor(fields: Vec<(String, Ident)>,
let fallthrough_arm = if is_variant {
quote! {
_serde::export::Err(_serde::de::Error::unknown_variant(value, VARIANTS))
_serde::export::Err(_serde::de::Error::unknown_variant(__value, VARIANTS))
}
} else if item_attrs.deny_unknown_fields() {
quote! {
_serde::export::Err(_serde::de::Error::unknown_field(value, FIELDS))
_serde::export::Err(_serde::de::Error::unknown_field(__value, FIELDS))
}
} else {
quote! {
@@ -1086,7 +1098,7 @@ fn deserialize_field_visitor(fields: Vec<(String, Ident)>,
let bytes_to_str = if is_variant || item_attrs.deny_unknown_fields() {
Some(quote! {
let value = &_serde::export::from_utf8_lossy(value);
let __value = &_serde::export::from_utf8_lossy(__value);
})
} else {
None
@@ -1101,8 +1113,8 @@ fn deserialize_field_visitor(fields: Vec<(String, Ident)>,
impl _serde::Deserialize for __Field {
#[inline]
fn deserialize<__D>(deserializer: __D) -> _serde::export::Result<__Field, __D::Error>
where __D: _serde::Deserializer,
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<__Field, __D::Error>
where __D: _serde::Deserializer
{
struct __FieldVisitor;
@@ -1115,10 +1127,10 @@ fn deserialize_field_visitor(fields: Vec<(String, Ident)>,
#visit_index
fn visit_str<__E>(self, value: &str) -> _serde::export::Result<__Field, __E>
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<__Field, __E>
where __E: _serde::de::Error
{
match value {
match __value {
#(
#field_strs => _serde::export::Ok(__Field::#field_idents),
)*
@@ -1126,10 +1138,10 @@ fn deserialize_field_visitor(fields: Vec<(String, Ident)>,
}
}
fn visit_bytes<__E>(self, value: &[u8]) -> _serde::export::Result<__Field, __E>
fn visit_bytes<__E>(self, __value: &[u8]) -> _serde::export::Result<__Field, __E>
where __E: _serde::de::Error
{
match value {
match __value {
#(
#field_bytes => _serde::export::Ok(__Field::#field_idents),
)*
@@ -1141,7 +1153,7 @@ fn deserialize_field_visitor(fields: Vec<(String, Ident)>,
}
}
_serde::Deserializer::deserialize_struct_field(deserializer, __FieldVisitor)
_serde::Deserializer::deserialize_struct_field(__deserializer, __FieldVisitor)
}
}
}
@@ -1205,7 +1217,7 @@ fn deserialize_map(ident: &syn::Ident,
None => {
let field_ty = &field.ty;
quote! {
try!(_serde::de::MapVisitor::visit_value::<#field_ty>(&mut visitor))
try!(_serde::de::MapVisitor::visit_value::<#field_ty>(&mut __visitor))
}
}
Some(path) => {
@@ -1213,7 +1225,7 @@ fn deserialize_map(ident: &syn::Ident,
ident, generics, field.ty, path);
quote!({
#wrapper
try!(_serde::de::MapVisitor::visit_value::<#wrapper_ty>(&mut visitor)).value
try!(_serde::de::MapVisitor::visit_value::<#wrapper_ty>(&mut __visitor)).value
})
}
};
@@ -1232,7 +1244,7 @@ fn deserialize_map(ident: &syn::Ident,
None
} else {
Some(quote! {
_ => { let _ = try!(_serde::de::MapVisitor::visit_value::<_serde::de::impls::IgnoredAny>(&mut visitor)); }
_ => { let _ = try!(_serde::de::MapVisitor::visit_value::<_serde::de::impls::IgnoredAny>(&mut __visitor)); }
})
};
@@ -1240,14 +1252,15 @@ fn deserialize_map(ident: &syn::Ident,
let match_keys = if item_attrs.deny_unknown_fields() && all_skipped {
quote! {
// FIXME: Once we drop support for Rust 1.15:
// let _serde::export::None::<__Field> = try!(_serde::de::MapVisitor::visit_key(&mut visitor));
try!(_serde::de::MapVisitor::visit_key::<__Field>(&mut visitor))
.map(|impossible| match impossible {});
// let _serde::export::None::<__Field> = try!(_serde::de::MapVisitor::visit_key(&mut __visitor));
_serde::export::Option::map(
try!(_serde::de::MapVisitor::visit_key::<__Field>(&mut __visitor)),
|__impossible| match __impossible {});
}
} else {
quote! {
while let _serde::export::Some(key) = try!(_serde::de::MapVisitor::visit_key::<__Field>(&mut visitor)) {
match key {
while let _serde::export::Some(__key) = try!(_serde::de::MapVisitor::visit_key::<__Field>(&mut __visitor)) {
match __key {
#(#value_arms)*
#ignored_arm
}
@@ -1330,12 +1343,11 @@ fn wrap_deserialize_with(ident: &syn::Ident,
}
impl #impl_generics _serde::Deserialize for __DeserializeWith #ty_generics #where_clause {
fn deserialize<__D>(__d: __D) -> _serde::export::Result<Self, __D::Error>
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where __D: _serde::Deserializer
{
let value = try!(#deserialize_with(__d));
_serde::export::Ok(__DeserializeWith {
value: value,
value: try!(#deserialize_with(__deserializer)),
phantom: _serde::export::PhantomData,
})
}
+49 -39
View File
@@ -23,7 +23,7 @@ pub fn expand_derive_serialize(item: &syn::DeriveInput) -> Result<Tokens, String
extern crate serde as _serde;
#[automatically_derived]
impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause {
fn serialize<__S>(&self, _serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
{
#body
@@ -61,28 +61,38 @@ fn needs_serialize_bound(attrs: &attr::Field) -> bool {
}
fn serialize_body(item: &Item, generics: &syn::Generics) -> Fragment {
match item.body {
Body::Enum(ref variants) => {
serialize_item_enum(&item.ident, generics, variants, &item.attrs)
}
Body::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) {
panic!("struct has unnamed fields");
if let Some(into_type) = item.attrs.into_type() {
serialize_into(into_type)
} else {
match item.body {
Body::Enum(ref variants) => {
serialize_item_enum(&item.ident, generics, variants, &item.attrs)
}
serialize_struct(&item.ident, generics, fields, &item.attrs)
}
Body::Struct(Style::Tuple, ref fields) => {
if fields.iter().any(|field| field.ident.is_some()) {
panic!("tuple struct has named fields");
Body::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) {
panic!("struct has unnamed fields");
}
serialize_struct(&item.ident, generics, fields, &item.attrs)
}
Body::Struct(Style::Tuple, ref fields) => {
if fields.iter().any(|field| field.ident.is_some()) {
panic!("tuple struct has named fields");
}
serialize_tuple_struct(&item.ident, generics, fields, &item.attrs)
}
Body::Struct(Style::Newtype, ref fields) => {
serialize_newtype_struct(&item.ident, generics, &fields[0], &item.attrs)
}
Body::Struct(Style::Unit, _) => serialize_unit_struct(&item.attrs),
}
}
}
serialize_tuple_struct(&item.ident, generics, fields, &item.attrs)
}
Body::Struct(Style::Newtype, ref fields) => {
serialize_newtype_struct(&item.ident, generics, &fields[0], &item.attrs)
}
Body::Struct(Style::Unit, _) => serialize_unit_struct(&item.attrs),
fn serialize_into(into_type: &syn::Ty) -> Fragment {
quote_block! {
_serde::Serialize::serialize(
&<Self as _serde::export::Into<#into_type>>::into(_serde::export::Clone::clone(self)),
__serializer)
}
}
@@ -90,7 +100,7 @@ fn serialize_unit_struct(item_attrs: &attr::Item) -> Fragment {
let type_name = item_attrs.name().serialize_name();
quote_expr! {
_serde::Serializer::serialize_unit_struct(_serializer, #type_name)
_serde::Serializer::serialize_unit_struct(__serializer, #type_name)
}
}
@@ -107,7 +117,7 @@ fn serialize_newtype_struct(ident: &syn::Ident,
}
quote_expr! {
_serde::Serializer::serialize_newtype_struct(_serializer, #type_name, #field_expr)
_serde::Serializer::serialize_newtype_struct(__serializer, #type_name, #field_expr)
}
}
@@ -128,7 +138,7 @@ fn serialize_tuple_struct(ident: &syn::Ident,
let let_mut = mut_if(len > 0);
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(_serializer, #type_name, #len));
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len));
#(#serialize_stmts)*
_serde::ser::SerializeTupleStruct::end(__serde_state)
}
@@ -166,7 +176,7 @@ fn serialize_struct(ident: &syn::Ident,
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(_serializer, #type_name, #len));
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(__serializer, #type_name, #len));
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
@@ -292,7 +302,7 @@ fn serialize_externally_tagged_variant(ident: &syn::Ident,
Style::Unit => {
quote_expr! {
_serde::Serializer::serialize_unit_variant(
_serializer,
__serializer,
#type_name,
#variant_index,
#variant_name,
@@ -308,7 +318,7 @@ fn serialize_externally_tagged_variant(ident: &syn::Ident,
quote_expr! {
_serde::Serializer::serialize_newtype_variant(
_serializer,
__serializer,
#type_name,
#variant_index,
#variant_name,
@@ -355,7 +365,7 @@ fn serialize_internally_tagged_variant(ident: &syn::Ident,
Style::Unit => {
quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
_serializer, #type_name, 1));
__serializer, #type_name, 1));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
_serde::ser::SerializeStruct::end(__struct)
@@ -370,7 +380,7 @@ fn serialize_internally_tagged_variant(ident: &syn::Ident,
quote_expr! {
_serde::ser::private::serialize_tagged_newtype(
_serializer,
__serializer,
#enum_ident_str,
#variant_ident_str,
#tag,
@@ -407,7 +417,7 @@ fn serialize_adjacently_tagged_variant(ident: &syn::Ident,
Style::Unit => {
return quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
_serializer, #type_name, 1));
__serializer, #type_name, 1));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
_serde::ser::SerializeStruct::end(__struct)
@@ -421,7 +431,7 @@ fn serialize_adjacently_tagged_variant(ident: &syn::Ident,
}
quote_expr! {
_serde::Serialize::serialize(#field_expr, _serializer)
_serde::Serialize::serialize(#field_expr, __serializer)
}
}
Style::Tuple => {
@@ -468,7 +478,7 @@ fn serialize_adjacently_tagged_variant(ident: &syn::Ident,
}
impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, _serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
{
let (#(#fields_ident,)*) = self.data;
@@ -477,7 +487,7 @@ fn serialize_adjacently_tagged_variant(ident: &syn::Ident,
}
let mut __struct = try!(_serde::Serializer::serialize_struct(
_serializer, #type_name, 2));
__serializer, #type_name, 2));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
try!(_serde::ser::SerializeStruct::serialize_field(
@@ -497,7 +507,7 @@ fn serialize_untagged_variant(ident: &syn::Ident,
match variant.style {
Style::Unit => {
quote_expr! {
_serde::Serializer::serialize_unit(_serializer)
_serde::Serializer::serialize_unit(__serializer)
}
}
Style::Newtype => {
@@ -508,7 +518,7 @@ fn serialize_untagged_variant(ident: &syn::Ident,
}
quote_expr! {
_serde::Serialize::serialize(#field_expr, _serializer)
_serde::Serialize::serialize(#field_expr, __serializer)
}
}
Style::Tuple => {
@@ -556,7 +566,7 @@ fn serialize_tuple_variant(context: TupleVariant,
TupleVariant::ExternallyTagged { type_name, variant_index, variant_name } => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_variant(
_serializer,
__serializer,
#type_name,
#variant_index,
#variant_name,
@@ -568,7 +578,7 @@ fn serialize_tuple_variant(context: TupleVariant,
TupleVariant::Untagged => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple(
_serializer,
__serializer,
#len));
#(#serialize_stmts)*
_serde::ser::SerializeTuple::end(__serde_state)
@@ -622,7 +632,7 @@ fn serialize_struct_variant<'a>(context: StructVariant<'a>,
StructVariant::ExternallyTagged { variant_index, variant_name } => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct_variant(
_serializer,
__serializer,
#name,
#variant_index,
#variant_name,
@@ -635,7 +645,7 @@ fn serialize_struct_variant<'a>(context: StructVariant<'a>,
StructVariant::InternallyTagged { tag, variant_name } => {
quote_block! {
let mut __serde_state = try!(_serde::Serializer::serialize_struct(
_serializer,
__serializer,
#name,
#len + 1,
));
@@ -651,7 +661,7 @@ fn serialize_struct_variant<'a>(context: StructVariant<'a>,
StructVariant::Untagged => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(
_serializer,
__serializer,
#name,
#len,
));
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_test"
version = "0.9.9"
version = "0.9.13"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations"
+5 -2
View File
@@ -7,6 +7,7 @@ use token::Token;
use std::fmt::Debug;
/// Runs both `assert_ser_tokens` and `assert_de_tokens`.
pub fn assert_tokens<T>(value: &T, tokens: &[Token<'static>])
where T: Serialize + Deserialize + PartialEq + Debug
{
@@ -14,6 +15,7 @@ pub fn assert_tokens<T>(value: &T, tokens: &[Token<'static>])
assert_de_tokens(value, tokens);
}
/// Asserts that `value` serializes to the given `tokens`.
pub fn assert_ser_tokens<T>(value: &T, tokens: &[Token])
where T: Serialize
{
@@ -22,7 +24,7 @@ pub fn assert_ser_tokens<T>(value: &T, tokens: &[Token])
assert_eq!(ser.next_token(), None);
}
/// Expect an error serializing `T`.
/// Asserts that `value` serializes to the given `tokens`, and then yields `error`.
pub fn assert_ser_tokens_error<T>(value: &T, tokens: &[Token], error: Error)
where T: Serialize + PartialEq + Debug
{
@@ -32,6 +34,7 @@ pub fn assert_ser_tokens_error<T>(value: &T, tokens: &[Token], error: Error)
assert_eq!(ser.next_token(), None);
}
/// Asserts that the given `tokens` deserialize into `value`.
pub fn assert_de_tokens<T>(value: &T, tokens: &[Token<'static>])
where T: Deserialize + PartialEq + Debug
{
@@ -41,7 +44,7 @@ pub fn assert_de_tokens<T>(value: &T, tokens: &[Token<'static>])
assert_eq!(de.next_token(), None);
}
/// Expect an error deserializing tokens into a `T`.
/// Asserts that the given `tokens` yield `error` when deserializing.
pub fn assert_de_tokens_error<T>(tokens: &[Token<'static>], error: Error)
where T: Deserialize + PartialEq + Debug
{
+4
View File
@@ -7,6 +7,7 @@ use serde::de::value::{ValueDeserializer, MapVisitorDeserializer, SeqVisitorDese
use error::Error;
use token::Token;
/// A `Deserializer` that reads from a list of tokens.
pub struct Deserializer<I>
where I: Iterator<Item = Token<'static>>
{
@@ -16,14 +17,17 @@ pub struct Deserializer<I>
impl<I> Deserializer<I>
where I: Iterator<Item = Token<'static>>
{
/// Creates the deserializer.
pub fn new(tokens: I) -> Deserializer<I> {
Deserializer { tokens: tokens.peekable() }
}
/// Pulls the next token off of the deserializer, ignoring it.
pub fn next_token(&mut self) -> Option<Token<'static>> {
self.tokens.next()
}
/// Pulls the next token off of the deserializer and checks if it matches an expected token.
pub fn expect_token(&mut self, expected: Token) -> Result<(), Error> {
match self.tokens.next() {
Some(token) => {
+8
View File
@@ -5,11 +5,19 @@ use serde::{ser, de};
use token::Token;
/// Error returned by the test `Serializer` and `Deserializer`.
#[derive(Clone, PartialEq, Debug)]
pub enum Error {
/// A custom error.
Message(String),
/// `Deserialize` was expecting a struct of one name, and another was found.
InvalidName(&'static str),
/// `Serialize` generated a token that didn't match the test.
UnexpectedToken(Token<'static>),
/// The expected token list was too short.
EndOfTokens,
}
+3
View File
@@ -5,6 +5,7 @@ use serde::{ser, Serialize};
use error::Error;
use token::Token;
/// A `Serializer` that ensures that a value serializes to a given list of tokens.
pub struct Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
@@ -15,6 +16,7 @@ pub struct Serializer<'a, I>
impl<'a, I> Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
/// Creates the serializer.
pub fn new(tokens: I) -> Serializer<'a, I> {
Serializer {
tokens: tokens,
@@ -22,6 +24,7 @@ impl<'a, I> Serializer<'a, I>
}
}
/// Pulls the next token off of the serializer, ignoring it.
pub fn next_token(&mut self) -> Option<&'a Token<'a>> {
self.tokens.next()
}
+111
View File
@@ -1,59 +1,170 @@
#[derive(Clone, PartialEq, Debug)]
pub enum Token<'a> {
/// A serialized `bool`.
Bool(bool),
/// A serialized `i8`.
I8(i8),
/// A serialized `i16`.
I16(i16),
/// A serialized `i32`.
I32(i32),
/// A serialized `i64`.
I64(i64),
/// A serialized `u8`.
U8(u8),
/// A serialized `u16`.
U16(u16),
/// A serialized `u32`.
U32(u32),
/// A serialized `u64`.
U64(u64),
/// A serialized `f32`.
F32(f32),
/// A serialized `f64`.
F64(f64),
/// A serialized `char`.
Char(char),
/// A serialized `str`.
Str(&'a str),
/// A serialized `String`.
String(String),
/// A serialized `[u8]`
Bytes(&'a [u8]),
/// A serialized `ByteBuf`
ByteBuf(Vec<u8>),
/// The header to a serialized `Option<T>`.
///
/// `None` is serialized as `Option(false)`, while `Some` is serialized as `Option(true)`, then
/// the value contained in the option.
Option(bool),
/// A serialized `()`.
Unit,
/// A serialized unit struct of the given name.
UnitStruct(&'a str),
/// The header to a serialized newtype struct of the given name.
///
/// Newtype structs are serialized with this header, followed by the value contained in the
/// newtype struct.
StructNewType(&'a str),
/// The header to an enum of the given name.
///
/// This token is only used for deserializers, and ensures that the following tokens are read as
/// an enum. Because this is never emitted by serializers, calling `assert_ser_tokens` or
/// `assert_tokens` will fail if this token is used.
///
/// TODO: Trash this.
EnumStart(&'a str),
/// A unit variant of an enum of the given name, of the given name.
///
/// The first string represents the name of the enum, and the second represents the name of the
/// variant.
EnumUnit(&'a str, &'a str),
/// The header to a newtype variant of an enum of the given name, of the given name.
///
/// The first string represents the name of the enum, and the second represents the name of the
/// variant. The value contained within this enum works the same as `StructNewType`.
EnumNewType(&'a str, &'a str),
/// The header to a sequence of the given length.
///
/// These are serialized via `serialize_seq`, which takes an optional length. After this
/// header is a list of elements, followed by `SeqEnd`.
SeqStart(Option<usize>),
/// The header to an array of the given length.
///
/// These are serialized via `serialize_seq_fized_size`, which requires a length. After this
/// header is a list of elements, followed by `SeqEnd`.
SeqArrayStart(usize),
/// A separator, which occurs *before* every element in a sequence.
///
/// Elements in sequences are represented by a `SeqSep`, followed by the value of the element.
SeqSep,
/// An indicator of the end of a sequence.
SeqEnd,
/// The header to a tuple of the given length, similar to `SeqArrayStart`.
TupleStart(usize),
/// A separator, similar to `SeqSep`.
TupleSep,
/// An indicator of the end of a tuple, similar to `SeqEnd`.
TupleEnd,
/// The header to a tuple struct of the given name and length.
TupleStructStart(&'a str, usize),
/// A separator, similar to `TupleSep`.
TupleStructSep,
/// An indicator of the end of a tuple struct, similar to `TupleEnd`.
TupleStructEnd,
/// The header to a map of the given length.
///
/// These are serialized via `serialize_map`, which takes an optional length. After this header
/// is a list of key-value pairs, followed by `MapEnd`.
MapStart(Option<usize>),
/// A separator, which occurs *before* every key-value pair in a map.
///
/// Elements in maps are represented by a `MapSep`, followed by a serialized key, followed
/// by a serialized value.
MapSep,
/// An indicator of the end of a map.
MapEnd,
/// The header of a struct of the given name and length, similar to `MapStart`.
StructStart(&'a str, usize),
/// A separator, similar to `MapSep`.
StructSep,
/// An indicator of the end of a struct, similar to `MapEnd`.
StructEnd,
/// The header to a tuple variant of an enum of the given name, of the given name and length.
EnumSeqStart(&'a str, &'a str, usize),
/// A separator, similar to `TupleSep`.
EnumSeqSep,
/// An indicator of the end of a tuple variant, similar to `TupleEnd`.
EnumSeqEnd,
/// The header of a struct variant of an enum of the given name, of the given name and length,
/// similar to `StructStart`.
EnumMapStart(&'a str, &'a str, usize),
/// A separator, similar to `StructSep`.
EnumMapSep,
/// An indicator of the end of a struct, similar to `StructEnd`.
EnumMapEnd,
}
+1 -8
View File
@@ -5,10 +5,7 @@ authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
publish = false
[features]
unstable-testing = [
"compiletest_rs",
"serde/unstable-testing",
]
unstable = ["serde/unstable", "compiletest_rs"]
[dev-dependencies]
fnv = "1.0"
@@ -19,7 +16,3 @@ serde_test = { path = "../serde_test" }
[dependencies]
compiletest_rs = { version = "0.2", optional = true }
[[test]]
name = "test"
path = "tests/test.rs"
+2 -1
View File
@@ -1,7 +1,8 @@
#![feature(lang_items, start, libc)]
#![feature(lang_items, start, libc, compiler_builtins_lib)]
#![no_std]
extern crate libc;
extern crate compiler_builtins;
#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
@@ -0,0 +1,11 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(from = "Option<T")] //~^ HELP: failed to parse type: from = "Option<T"
enum TestOne {
Testing,
One,
Two,
Three,
}
@@ -0,0 +1,11 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(into = "Option<T")] //~^ HELP: failed to parse type: into = "Option<T"
enum TestOne {
Testing,
One,
Two,
Three,
}
+2
View File
@@ -1,3 +1,5 @@
#![cfg(feature = "unstable")]
extern crate compiletest_rs as compiletest;
use std::env;
-23
View File
@@ -1,23 +0,0 @@
#![cfg_attr(feature = "unstable-testing", feature(test, non_ascii_idents))]
#[cfg(feature = "unstable-testing")]
extern crate test;
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_test;
#[macro_use]
mod macros;
mod test_annotations;
mod test_bytes;
mod test_de;
mod test_gen;
mod test_macros;
mod test_ser;
#[cfg(feature = "unstable-testing")]
mod compiletest;
+83
View File
@@ -1,3 +1,6 @@
#[macro_use]
extern crate serde_derive;
extern crate serde;
use self::serde::{Serialize, Serializer, Deserialize, Deserializer};
@@ -974,3 +977,83 @@ fn test_invalid_length_enum() {
Error::Message("invalid length 1, expected tuple of 2 elements".to_owned()),
);
}
#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
#[serde(into="EnumToU32", from="EnumToU32")]
struct StructFromEnum(Option<u32>);
impl Into<EnumToU32> for StructFromEnum {
fn into(self) -> EnumToU32 {
match self {
StructFromEnum(v) => v.into()
}
}
}
impl From<EnumToU32> for StructFromEnum {
fn from(v: EnumToU32) -> Self {
StructFromEnum(v.into())
}
}
#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
#[serde(into="Option<u32>", from="Option<u32>")]
enum EnumToU32 {
One,
Two,
Three,
Four,
Nothing
}
impl Into<Option<u32>> for EnumToU32 {
fn into(self) -> Option<u32> {
match self {
EnumToU32::One => Some(1),
EnumToU32::Two => Some(2),
EnumToU32::Three => Some(3),
EnumToU32::Four => Some(4),
EnumToU32::Nothing => None
}
}
}
impl From<Option<u32>> for EnumToU32 {
fn from(v: Option<u32>) -> Self {
match v {
Some(1) => EnumToU32::One,
Some(2) => EnumToU32::Two,
Some(3) => EnumToU32::Three,
Some(4) => EnumToU32::Four,
_ => EnumToU32::Nothing
}
}
}
#[test]
fn test_from_into_traits() {
assert_ser_tokens::<EnumToU32>(&EnumToU32::One,
&[Token::Option(true),
Token::U32(1)
]
);
assert_ser_tokens::<EnumToU32>(&EnumToU32::Nothing,
&[Token::Option(false)]
);
assert_de_tokens::<EnumToU32>(&EnumToU32::Two,
&[Token::Option(true),
Token::U32(2)
]
);
assert_ser_tokens::<StructFromEnum>(&StructFromEnum(Some(5)),
&[Token::Option(false)]
);
assert_ser_tokens::<StructFromEnum>(&StructFromEnum(None),
&[Token::Option(false)]
);
assert_de_tokens::<StructFromEnum>(&StructFromEnum(Some(2)),
&[Token::Option(true),
Token::U32(2)
]
);
}
+3
View File
@@ -1,4 +1,7 @@
extern crate serde;
use serde::bytes::{ByteBuf, Bytes};
extern crate serde_test;
use serde_test::{assert_tokens, assert_ser_tokens, assert_de_tokens, Token};
#[test]
+132 -1
View File
@@ -1,9 +1,19 @@
#![cfg_attr(feature = "unstable", feature(into_boxed_c_str))]
#[macro_use]
extern crate serde_derive;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::net;
use std::path::PathBuf;
use std::time::Duration;
use std::default::Default;
use std::ffi::{CString, OsString};
#[cfg(feature = "unstable")]
use std::ffi::CStr;
extern crate serde;
use serde::Deserialize;
extern crate fnv;
@@ -17,6 +27,9 @@ use self::serde_test::{
assert_de_tokens_error,
};
#[macro_use]
mod macros;
//////////////////////////////////////////////////////////////////////////
#[derive(Copy, Clone, PartialEq, Debug, Deserialize)]
@@ -855,6 +868,28 @@ declare_tests! {
Token::SeqEnd,
],
}
test_range {
1u32..2u32 => &[
Token::StructStart("Range", 2),
Token::StructSep,
Token::Str("start"),
Token::U32(1),
Token::StructSep,
Token::Str("end"),
Token::U32(2),
Token::StructEnd,
],
1u32..2u32 => &[
Token::SeqStart(Some(2)),
Token::SeqSep,
Token::U64(1),
Token::SeqSep,
Token::U64(2),
Token::SeqEnd,
],
}
test_net_ipv4addr {
"1.2.3.4".parse::<net::Ipv4Addr>().unwrap() => &[Token::Str("1.2.3.4")],
}
@@ -871,17 +906,101 @@ declare_tests! {
Token::String("/usr/local/lib".to_owned()),
],
}
test_cstring {
CString::new("abc").unwrap() => &[
Token::Bytes(b"abc"),
],
}
}
#[cfg(unix)]
#[test]
fn test_osstring() {
use std::os::unix::ffi::OsStringExt;
let value = OsString::from_vec(vec![1, 2, 3]);
let tokens = [
Token::EnumStart("OsString"),
Token::Str("Unix"),
Token::SeqStart(Some(2)),
Token::SeqSep,
Token::U8(1),
Token::SeqSep,
Token::U8(2),
Token::SeqSep,
Token::U8(3),
Token::SeqEnd,
];
assert_de_tokens(&value, &tokens);
assert_de_tokens_ignore(&tokens);
}
#[cfg(windows)]
#[test]
fn test_osstring() {
use std::os::windows::ffi::OsStringExt;
let value = OsString::from_wide(&[1, 2, 3]);
let tokens = [
Token::EnumStart("OsString"),
Token::Str("Windows"),
Token::SeqStart(Some(2)),
Token::SeqSep,
Token::U16(1),
Token::SeqSep,
Token::U16(2),
Token::SeqSep,
Token::U16(3),
Token::SeqEnd,
];
assert_de_tokens(&value, &tokens);
assert_de_tokens_ignore(&tokens);
}
#[cfg(feature = "unstable")]
#[test]
fn test_cstr() {
assert_de_tokens::<Box<CStr>>(&CString::new("abc").unwrap().into_boxed_c_str(),
&[Token::Bytes(b"abc")]);
}
#[cfg(feature = "unstable")]
#[test]
fn test_net_ipaddr() {
assert_de_tokens(
"1.2.3.4".parse::<net::IpAddr>().unwrap(),
&"1.2.3.4".parse::<net::IpAddr>().unwrap(),
&[Token::Str("1.2.3.4")],
);
}
#[cfg(feature = "unstable")]
#[test]
fn test_cstr_internal_null() {
assert_de_tokens_error::<Box<CStr>>(
&[
Token::Bytes(b"a\0c"),
],
Error::Message("nul byte found in provided data at position: 1".into())
);
}
#[cfg(feature = "unstable")]
#[test]
fn test_cstr_internal_null_end() {
assert_de_tokens_error::<Box<CStr>>(
&[
Token::Bytes(b"ac\0"),
],
Error::Message("nul byte found in provided data at position: 2".into())
);
}
declare_error_tests! {
test_unknown_field<StructDenyUnknown> {
&[
@@ -988,4 +1107,16 @@ declare_error_tests! {
],
Error::Message("invalid length 1, expected an array of length 3".into()),
}
test_cstring_internal_null<CString> {
&[
Token::Bytes(b"a\0c"),
],
Error::Message("nul byte found in provided data at position: 1".into()),
}
test_cstring_internal_null_end<CString> {
&[
Token::Bytes(b"ac\0"),
],
Error::Message("nul byte found in provided data at position: 2".into()),
}
}
+15 -10
View File
@@ -2,6 +2,11 @@
// successfully when there are a variety of generics and non-(de)serializable
// types involved.
#![cfg_attr(feature = "unstable", feature(non_ascii_idents))]
#[macro_use]
extern crate serde_derive;
extern crate serde;
use self::serde::ser::{Serialize, Serializer};
use self::serde::de::{Deserialize, Deserializer};
@@ -215,8 +220,8 @@ fn test_gen() {
}
assert::<EmptyEnumVariant>();
#[cfg(feature = "unstable-testing")]
#[cfg_attr(feature = "unstable-testing", derive(Serialize, Deserialize))]
#[cfg(feature = "unstable")]
#[derive(Serialize, Deserialize)]
struct NonAsciiIdents {
σ: f64
}
@@ -241,12 +246,12 @@ fn test_gen() {
f: u8,
}
#[cfg(feature = "unstable-testing")]
#[cfg_attr(feature = "unstable-testing", derive(Serialize, Deserialize))]
#[cfg(feature = "unstable")]
#[derive(Serialize, Deserialize)]
struct EmptyTuple();
#[cfg(feature = "unstable-testing")]
#[cfg_attr(feature = "unstable-testing", derive(Serialize, Deserialize))]
#[cfg(feature = "unstable")]
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct EmptyTupleDenyUnknown();
@@ -271,8 +276,8 @@ fn test_gen() {
Variant,
}
#[cfg(feature = "unstable-testing")]
#[cfg_attr(feature = "unstable-testing", derive(Serialize, Deserialize))]
#[cfg(feature = "unstable")]
#[derive(Serialize, Deserialize)]
enum EmptyVariants {
Braced {},
Tuple(),
@@ -283,8 +288,8 @@ fn test_gen() {
TupleSkip(#[serde(skip_deserializing)] u8),
}
#[cfg(feature = "unstable-testing")]
#[cfg_attr(feature = "unstable-testing", derive(Serialize, Deserialize))]
#[cfg(feature = "unstable")]
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
enum EmptyVariantsDenyUnknown {
Braced {},
+89
View File
@@ -1,3 +1,6 @@
#[macro_use]
extern crate serde_derive;
extern crate serde_test;
use self::serde_test::{
Error,
@@ -1222,3 +1225,89 @@ fn test_enum_in_untagged_enum() {
]
);
}
#[test]
fn test_rename_all() {
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(rename_all = "snake_case")]
enum E {
#[serde(rename_all = "camelCase")]
Serialize {
serialize: bool,
serialize_seq: bool,
},
#[serde(rename_all = "kebab-case")]
SerializeSeq {
serialize: bool,
serialize_seq: bool,
},
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
SerializeMap {
serialize: bool,
serialize_seq: bool,
},
}
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(rename_all = "PascalCase")]
struct S {
serialize: bool,
serialize_seq: bool,
}
assert_tokens(
&E::Serialize { serialize: true, serialize_seq: true },
&[
Token::EnumMapStart("E", "serialize", 2),
Token::EnumMapSep,
Token::Str("serialize"),
Token::Bool(true),
Token::EnumMapSep,
Token::Str("serializeSeq"),
Token::Bool(true),
Token::EnumMapEnd,
]
);
assert_tokens(
&E::SerializeSeq { serialize: true, serialize_seq: true },
&[
Token::EnumMapStart("E", "serialize_seq", 2),
Token::EnumMapSep,
Token::Str("serialize"),
Token::Bool(true),
Token::EnumMapSep,
Token::Str("serialize-seq"),
Token::Bool(true),
Token::EnumMapEnd,
]
);
assert_tokens(
&E::SerializeMap { serialize: true, serialize_seq: true },
&[
Token::EnumMapStart("E", "serialize_map", 2),
Token::EnumMapSep,
Token::Str("SERIALIZE"),
Token::Bool(true),
Token::EnumMapSep,
Token::Str("SERIALIZE_SEQ"),
Token::Bool(true),
Token::EnumMapEnd,
]
);
assert_tokens(
&S { serialize: true, serialize_seq: true },
&[
Token::StructStart("S", 2),
Token::StructSep,
Token::Str("Serialize"),
Token::Bool(true),
Token::StructSep,
Token::Str("SerializeSeq"),
Token::Bool(true),
Token::StructEnd,
]
);
}
+33 -46
View File
@@ -1,8 +1,14 @@
#[macro_use]
extern crate serde_derive;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::net;
use std::path::{Path, PathBuf};
use std::str;
use std::time::Duration;
use std::ffi::CString;
extern crate serde;
extern crate serde_test;
use self::serde_test::{
@@ -15,8 +21,8 @@ use self::serde_test::{
extern crate fnv;
use self::fnv::FnvHasher;
#[cfg(feature = "unstable")]
use serde::ser::iterator;
#[macro_use]
mod macros;
//////////////////////////////////////////////////////////////////////////
@@ -360,6 +366,19 @@ declare_tests! {
Token::StructEnd,
],
}
test_range {
1u32..2u32 => &[
Token::StructStart("Range", 2),
Token::StructSep,
Token::Str("start"),
Token::U32(1),
Token::StructSep,
Token::Str("end"),
Token::U32(2),
Token::StructEnd,
],
}
test_net_ipv4addr {
"1.2.3.4".parse::<net::Ipv4Addr>().unwrap() => &[Token::Str("1.2.3.4")],
}
@@ -381,61 +400,29 @@ declare_tests! {
Token::Str("/usr/local/lib"),
],
}
}
#[cfg(feature = "unstable")]
#[test]
fn test_iterator() {
assert_ser_tokens(iterator([0; 0].iter()), &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
]);
assert_ser_tokens(iterator([1, 2, 3].iter()), &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(1),
Token::SeqSep,
Token::I32(2),
Token::SeqSep,
Token::I32(3),
Token::SeqEnd,
]);
assert_ser_tokens(iterator([1, 2, 3].iter().map(|x| x * 2)), &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(2),
Token::SeqSep,
Token::I32(4),
Token::SeqSep,
Token::I32(6),
Token::SeqEnd,
]);
assert_ser_tokens(iterator([1, 2, 3].iter().filter(|&x| x % 2 != 0)), &[
Token::SeqStart(None),
Token::SeqSep,
Token::I32(1),
Token::SeqSep,
Token::I32(3),
Token::SeqEnd,
]);
test_cstring {
CString::new("abc").unwrap() => &[
Token::Bytes(b"abc"),
],
}
test_cstr {
(&*CString::new("abc").unwrap()) => &[
Token::Bytes(b"abc"),
],
}
}
#[cfg(feature = "unstable")]
#[test]
fn test_net_ipaddr() {
assert_ser_tokens(
"1.2.3.4".parse::<net::IpAddr>().unwrap(),
&"1.2.3.4".parse::<net::IpAddr>().unwrap(),
&[Token::Str("1.2.3.4")],
);
}
#[test]
#[cfg(unix)]
fn test_cannot_serialize_paths() {
let path = unsafe {
str::from_utf8_unchecked(b"Hello \xF0\x90\x80World")
+19
View File
@@ -0,0 +1,19 @@
#[macro_use]
extern crate serde_derive;
extern crate serde;
use serde::Deserialize;
use serde::de::value::{self, ValueDeserializer};
#[test]
fn test_u32_to_enum() {
#[derive(Deserialize, Debug, PartialEq)]
enum E {
A,
B,
}
let deserializer = ValueDeserializer::<value::Error>::into_deserializer(1u32);
let e: E = E::deserialize(deserializer).unwrap();
assert_eq!(E::B, e);
}
+7 -2
View File
@@ -10,6 +10,11 @@ channel() {
pwd
(set -x; cargo "$@")
fi
elif [ -n "${APPVEYOR}" ]; then
if [ "${APPVEYOR_RUST_CHANNEL}" = "${CHANNEL}" ]; then
pwd
(set -x; cargo "$@")
fi
else
pwd
(set -x; cargo "+${CHANNEL}" "$@")
@@ -30,7 +35,7 @@ if [ -n "${CLIPPY}" ]; then
cargo clippy --features unstable-testing -- -Dclippy
cd "$DIR/test_suite"
cargo clippy --features unstable-testing -- -Dclippy
cargo clippy --features unstable -- -Dclippy
cd "$DIR/test_suite/no_std"
cargo clippy -- -Dclippy
@@ -46,7 +51,7 @@ else
cd "$DIR/test_suite/deps"
channel build
cd "$DIR/test_suite"
channel test --features unstable-testing
channel test --features unstable
cd "$DIR/test_suite/no_std"
channel build