Compare commits

...

147 Commits

Author SHA1 Message Date
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
David Tolnay 59ec931d8f Release 0.9.9 2017-02-24 13:57:52 -08:00
David Tolnay 4b3c5ea99e Fix clippy lint in content serializer 2017-02-24 13:56:44 -08:00
David Tolnay d4ea4a7eef Add test for enums containing enums
Fixes #775.
2017-02-24 13:50:47 -08:00
David Tolnay 5fbdadefb2 Deserializing enums in serde_test 2017-02-24 13:47:04 -08:00
David Tolnay 4da77e4200 Serialize to Content 2017-02-24 12:59:35 -08:00
David Tolnay d797504407 Deserialize enums from &Content 2017-02-24 09:32:14 -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
David Tolnay 8e5f472e27 Merge pull request #787 from 46bit/issue-775
Fix internally tagged enums by implementing ContentDeserializer::deserialize_enum
2017-02-22 18:23:18 -08:00
David Tolnay 5e7883945b Fix clippy lint in Content::unexpected 2017-02-22 18:16:51 -08:00
David Tolnay a4bd6b9a96 Fix content's SeqDeserializer on no_std 2017-02-22 18:14:56 -08:00
Michael Mokrysz 4c253748c2 Compiles and fixes internally tagged testcases. 2017-02-23 01:05:44 +00:00
Michael Mokrysz 8f6e1fb5b3 Resolved error typing. Needs to adapt to Content::Map with non-String keys.
`EnumDeserializer` is being adapted from:
  `serde_json::Value::Map<Vec<(String, Value)>>`
serde has a Map variant that allows non-String keys:
  `serde::de::Content::Map<Vec<(Content, Content)>>`

There's a lot of assumptions in `EnumDeserializer` about `String` keys and I'm not sure what the adaptation should be.
2017-02-22 23:59:47 +00:00
Michael Mokrysz 4e665a71bd Attempt to port serde_json::Value::deserialize_enum for ContentDeserializer is being derailed by what error types should be used. 2017-02-22 22:55:18 +00:00
David Tolnay 017e6d304f Release 0.9.8 2017-02-21 10:59:42 -08:00
David Tolnay 89cbb81673 Include readme and licenses in crates.io archive
Fixes #772.
2017-02-20 21:11:57 -08:00
David Tolnay c36743fa05 Merge pull request #782 from serde-rs/adjacent
Deserialization of Haskell style enums
2017-02-20 21:04:17 -08:00
David Tolnay 9a3c1243f4 Deserialization of Haskell style enums 2017-02-20 20:05:06 -08:00
David Tolnay 599a1b6607 Fragments that keep track of type of syntax
Fixes #777.
2017-02-20 17:12:35 -08:00
David Tolnay 3d6e086d3e Support custom paths in container attribute serde(default="...") 2017-02-20 17:06:00 -08:00
David Tolnay ad480d2b04 Merge pull request #780 from Thomasdezeeuw/default_container
Add support for `#[serde(default)]` on structs
2017-02-20 16:10:28 -08:00
Thomas de Zeeuw 7bee779514 Only allow #[serde(default)]` on structs 2017-02-21 00:15:00 +01:00
David Tolnay dff919a926 Rename __simple_value to __field0 to be consistent with tuples 2017-02-20 14:16:54 -08:00
David Tolnay bac593573c Drop aster dependency 2017-02-20 13:50:17 -08:00
Thomas de Zeeuw 9444db5f19 Add support for #[serde(default)] on structs
This allows structs to use the default value for each field defined in
the struct’s `std::default::Default` implementation, rather then the
default value for the field’s type.

```
struct StructDefault {
    a: i32,
    b: String,
}

impl Default for StructDefault {
    fn default() -> StructDefault {
        StructDefault{
            a: 100,
            b: "default".to_string(),
        }
    }
}
```

The code above will now return `100` for field `a` and `”default”` for
`b`, rather then `0` and `””` respectively.
2017-02-20 22:35:31 +01:00
David Tolnay 3bf8cda994 Update generics handling to use split_for_impl 2017-02-20 13:04:40 -08:00
David Tolnay f98e7f6ba0 Merge pull request #778 from SimonSapin/serialize_display_bounded_length
Avoid some string allocations.
2017-02-20 11:09:32 -08:00
Simon Sapin 772b22b427 Avoid some string allocations. 2017-02-20 18:36:38 +01:00
David Tolnay 535ab1e04b Merge pull request #771 from elliottslaughter:internally_content_tagged 2017-02-19 16:08:49 -08:00
David Tolnay a3fe03c323 Serialization of Haskell style enums 2017-02-19 16:04:39 -08:00
David Tolnay 7dad6426da Merge pull request #774 from nox/limit-hints
Clamp hints coming from untrusted input to 4096
2017-02-19 13:51:21 -08:00
David Tolnay 792a5f7502 Also clamp the collection impls 2017-02-19 13:47:05 -08:00
Anthony Ramine a4c738a9f3 Clamp hints coming from untrusted input to 4096 2017-02-19 14:29:41 +01:00
Elliott Slaughter 4538143d00 Initial work to support serialization of adjacently tagged enums. 2017-02-18 20:46:37 -08:00
David Tolnay 7f08894a32 Remove dependency on unneeded syn feature 2017-02-17 21:01:42 -08:00
David Tolnay adf7b086b5 Remove outdated comment 2017-02-17 20:38:50 -08:00
David Tolnay c590df13b9 Add compile-fail test for the with attribute 2017-02-16 18:43:04 -08:00
Oliver Schneider afa6dfbbe2 Merge pull request #765 from serde-rs/with
Pair serialize_with and deserialize_with into one attribute
2017-02-15 08:33:14 +01:00
David Tolnay f500db6e91 Pair serialize_with and deserialize_with into one attribute 2017-02-14 17:36:50 -08:00
David Tolnay 090c8a7049 Merge pull request #762 from serde-rs/rustfmt
Use rustfmt
2017-02-13 01:29:25 -08:00
David Tolnay e8651a52e7 Rustfmt 2017-02-12 22:15:59 -08:00
David Tolnay 964a2dd4d1 Release 0.9.7 2017-02-09 17:52:11 -08:00
David Tolnay 8a21bbc720 Merge pull request #755 from serde-rs/playground
Playground feature to get serde_derive picked up by integer32 playground
2017-02-09 17:50:39 -08:00
Oliver Schneider 4dba260ad7 Merge pull request #756 from shepmaster/patch-2
Add missing close backtick
2017-02-09 18:01:35 +01:00
Jake Goulding 1d3044fa28 Add missing close backtick 2017-02-09 11:53:12 -05:00
David Tolnay d1f0112bfb Playground feature to get serde_derive picked up by integer32 playground 2017-02-08 12:37:40 -08:00
David Tolnay 3f25cd9a7e No longer need ser::Error import 2017-02-08 08:17:43 -08:00
David Tolnay 45a36f1219 Fix proc macro panic message in tests 2017-02-08 08:12:32 -08:00
David Tolnay 529a1cfedb Keyword no_std for serde and serde_derive 2017-02-08 07:40:02 -08:00
David Tolnay 219abd2e00 The performance is identical 2017-02-04 19:04:29 -08:00
David Tolnay 4bd10528a0 Merge pull request #736 from nox/serialize-iter
Introduce collect_seq and collect_map
2017-02-04 11:18:36 -08:00
David Tolnay b82bba2d0a Merge pull request #747 from serde-rs/phantom_tags
Content clean-up
2017-02-04 08:53:04 -08:00
Anthony Ramine 17c175a1a6 Use specialisation to optimise collect_seq and collect_map 2017-02-04 12:22:58 +01:00
Anthony Ramine 763ab9c2a1 Use serialize_seq! to implement Serialize for [T] 2017-02-04 12:21:45 +01:00
Anthony Ramine 30b8036efa Remove ser::Iterator 2017-02-04 12:17:25 +01:00
Anthony Ramine 89bb16da6b Introduce Serializer::collect_map 2017-02-04 11:49:53 +01:00
Anthony Ramine d00a895902 Introduce Serializer::collect_seq
This function serializes the given iterator as a sequence. Its iter parameter
has type I: IntoIterator, <I as IntoIterator>::Item: Serialize, which means it
will work both for iterators passed by value, therefore consuming them, and as
the value for a #[serde(serialize_with)] attribute, where it will be called as
Serializer::collect_seq(&self.field, serializer), relying on the common practice
of implementing IntoIterator for &C where C is a data type representing some
kind of collection.
2017-02-04 11:49:34 +01:00
Oliver Schneider 393b19ee8a update codegen to the content changes 2017-02-04 10:37:50 +01:00
Oliver Schneider e68888d475 remove possible sublte ambiguity with .into_deserializer 2017-02-04 10:00:04 +01:00
David Tolnay d1306a78ec Release 0.9.6 2017-02-03 08:02:47 -08:00
David Tolnay ce230adf12 Merge pull request #739 from serde-rs/tag
Untagged and internally tagged enums
2017-02-03 07:50:26 -08:00
David Tolnay 066c9a15cf Explain status of content module 2017-02-03 07:43:04 -08:00
Oliver Schneider 6277079152 move the PhantomData usage to the Deserializer 2017-02-03 15:02:40 +01:00
Oliver Schneider d60fd84b7e Merge pull request #740 from serde-rs/enumset
Remove the EnumSet impls
2017-02-03 13:38:39 +01:00
David Tolnay 02e6c04e9f Check for sequence end 2017-02-02 22:13:32 -08:00
David Tolnay 9f04b9d6e7 Remove the EnumSet impls 2017-02-02 19:13:55 -08:00
David Tolnay d298da0b4f Require std for deserializing untagged enums 2017-02-02 19:09:38 -08:00
David Tolnay ff21d557c7 Untagged and internally tagged enums 2017-02-02 18:48:30 -08:00
Oliver Schneider faaa494579 Merge pull request #738 from serde-rs/absolute
Use absolute paths to Ok, Err, and other types and methods
2017-02-02 08:16:51 +01:00
David Tolnay 661cdf4e00 Inline the trait docs at the top level 2017-02-01 12:58:24 -08:00
David Tolnay a55d812441 Even more absolute paths 2017-02-01 12:12:39 -08:00
David Tolnay b7ca574bb3 Use absolute paths to Ok and Err 2017-02-01 09:42:12 -08:00
David Tolnay d960571439 Release 0.9.5 2017-02-01 01:01:06 -08:00
David Tolnay 1ccc58e2aa Merge pull request #735 from serde-rs/travis
Allow running travis build locally
2017-02-01 00:43:27 -08:00
David Tolnay 34b39083bc No error if clippy install fails 2017-02-01 00:38:02 -08:00
David Tolnay 48f4deac55 No more travis-cargo 2017-01-31 12:18:57 -08:00
David Tolnay 9a0f05d00d Speed up the travis clippy installation 2017-01-31 12:09:44 -08:00
David Tolnay b47e1a6dc3 Allow clippy failure in travis 2017-01-31 12:07:35 -08:00
David Tolnay 39c7797633 Allow running travis build locally 2017-01-31 12:07:31 -08:00
Oliver Schneider 368784949e move to cargo clippy instead of using the clippy plugin (#733)
* move to cargo clippy instead of using the clippy plugin

fixes #729

* non-exectable scripts must be run with `sh`

* don't build serde in the clippy travis job

* only run clippy tests if installing clippy succeeds

* why is travis so picky?

* no more serde_codegen

* serde_test_suite_deps has no features

* don't use empty loops, llvm optimizes them to undefined behaviour

* abort the clippy job when clippy lints are triggered

* use caches on travis to speed up builds

* why are we even using `travis-cargo`?

* need to reinstall clippy frequently due to nightly updates

* command line tools are hard
2017-01-31 09:09:37 -08:00
Oliver Schneider 74cf80989d Merge pull request #731 from serde-rs/pubtuple
No tuple structs with private fields in public API
2017-01-31 08:56:46 +01:00
David Tolnay f0b4735781 No tuple structs with private fields in public API 2017-01-30 18:10:50 -08:00
David Tolnay 297f373548 Release 0.9.4 2017-01-30 17:42:11 -08:00
David Tolnay 81f28da8e1 Clarify the role of Impossible serializer 2017-01-30 17:41:33 -08:00
David Tolnay d4bb687032 Merge pull request #728 from nox/impossibru
Introduce ser::Impossible (fixes #694)
2017-01-30 17:26:21 -08:00
Anthony Ramine f9bc5037f5 Introduce ser::Impossible (fixes #694) 2017-01-31 02:20:04 +01:00
David Tolnay 8624ca6f1d Release 0.9.3 2017-01-28 15:01:58 -08:00
David Tolnay a9b5cc4830 Fix invalid_length message for tuples and arrays 2017-01-28 15:00:54 -08:00
David Tolnay c31f76321c Release 0.9.2 2017-01-28 09:10:39 -08:00
David Tolnay f2402dcf52 Merge pull request #724 from serde-rs/entry
SerializeMap::serialize_entry
2017-01-28 09:08:51 -08:00
David Tolnay 361402ac4d SerializeMap::serialize_entry 2017-01-28 09:03:32 -08:00
David Tolnay c52e131a03 Replace deprecated MacroInput 2017-01-27 15:42:43 -08:00
David Tolnay c0a06bdc96 Update to syn 0.11 2017-01-27 15:25:42 -08:00
David Tolnay dd13fd3a34 Isolate the compiletest dependencies 2017-01-27 14:53:30 -08:00
David Tolnay 91f628727b Clean up the compile_tests script 2017-01-27 14:37:28 -08:00
David Tolnay 571a2e4e2d Indent the travis config to look like serde_json's 2017-01-27 14:17:07 -08:00
David Tolnay 7edcf6ec3b Simplify Error::custom example 2017-01-27 14:03:40 -08:00
David Tolnay e4f7d8513c Clean up clippy lints in codegen_internals 2017-01-25 21:22:15 -08:00
David Tolnay 09c69da909 Move test macro to where it is used 2017-01-25 20:55:55 -08:00
David Tolnay 7ee175f448 Remove duplicate btreemap macro 2017-01-25 20:54:31 -08:00
David Tolnay 70ab3cdd61 Docs are built in a different repo 2017-01-25 20:51:10 -08:00
David Tolnay 8fb554e593 Rename no_std tests to underscores 2017-01-25 20:50:23 -08:00
David Tolnay 7a2bfdc1dd Consistent underscores in root directory 2017-01-25 20:45:33 -08:00
David Tolnay 9046e9d7a1 Test suite requires beta for now 2017-01-25 20:45:08 -08:00
David Tolnay 87040b4bc4 Fix clippy lints in serde_test 2017-01-25 20:42:44 -08:00
David Tolnay 68aab2424f Rename test suite crate 2017-01-25 20:40:13 -08:00
David Tolnay 9b9b697eb1 Make compiletest an optional dependency of the test suite 2017-01-25 20:39:27 -08:00
David Tolnay db449c4bf2 Set up clippy for serde_test 2017-01-25 20:38:21 -08:00
David Tolnay 948aa47687 Clean up clippy lints 2017-01-25 20:34:01 -08:00
David Tolnay 3e1e42ef9b Combine the test suites 2017-01-25 20:29:09 -08:00
David Tolnay dbdfe4f306 Remove serde_codegen from the test suite 2017-01-25 20:19:16 -08:00
David Tolnay e0d6b9d010 Merge serde_codegen into serde_derive crate 2017-01-25 20:07:55 -08:00
David Tolnay a5b8e806f8 Remove with-syntex feature of serde_codegen 2017-01-25 20:02:24 -08:00
David Tolnay d7dadd83b6 Remove the syntex example 2017-01-25 19:54:24 -08:00
101 changed files with 8350 additions and 4194 deletions
+14 -24
View File
@@ -1,27 +1,17 @@
sudo: false
language: rust
cache: cargo
# run builds for all the trains (and more)
rust:
- 1.13.0
- stable
- beta
- nightly
before_script:
- pip install 'travis-cargo<0.2' --user
- export PATH=$HOME/.local/bin:$PATH
script:
- (cd serde && travis-cargo build)
- (cd serde && travis-cargo --only beta test)
- (cd serde && travis-cargo --only nightly test -- --features unstable-testing)
- (cd serde && travis-cargo build -- --no-default-features)
- (cd serde && travis-cargo --only nightly build -- --no-default-features --features alloc)
- (cd serde && travis-cargo --only nightly build -- --no-default-features --features collections)
- (cd testing && travis-cargo --skip nightly test)
- (cd testing && travis-cargo --only nightly test -- --features unstable-testing)
- (cd serde_derive && travis-cargo --only nightly test)
- (cd serde_derive/no-std-tests && travis-cargo --only nightly build)
#- (cd examples/serde-syntex-example && travis-cargo --skip nightly run)
#- (cd examples/serde-syntex-example && travis-cargo --only nightly run -- --no-default-features --features unstable)
- (cd serde && travis-cargo --only stable doc)
env:
global:
- TRAVIS_CARGO_NIGHTLY_FEATURE=""
- 1.13.0
- stable
- beta
- nightly
matrix:
include:
- rust: nightly
env: CLIPPY=true
script: ./travis.sh
+9
View File
@@ -0,0 +1,9 @@
[workspace]
members = [
"serde",
"serde_codegen_internals",
"serde_derive",
"serde_test",
"test_suite",
"test_suite/no_std",
]
-2
View File
@@ -1,2 +0,0 @@
target
Cargo.lock
-18
View File
@@ -1,18 +0,0 @@
[package]
name = "serde-syntex-example"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
build = "build.rs"
publish = false
[features]
default = ["serde_codegen"]
unstable = ["serde_derive"]
[build-dependencies]
serde_codegen = { version = "^0.8", optional = true, path = "../../serde_codegen" }
[dependencies]
serde = "^0.8"
serde_derive = { version = "^0.8", optional = true, path = "../../serde_derive" }
serde_json = "^0.8"
-20
View File
@@ -1,20 +0,0 @@
This example demonstrates how to use Serde with Syntex. On stable or nightly
with Syntex, it can be built with:
```
% rustup run stable cargo run
Running `target/debug/serde-syntex-example`
{"x":1,"y":2}
Point { x: 1, y: 2 }
% rustup run nightly cargo run
Running `target/debug/serde-syntex-example`
{"x":1,"y":2}
Point { x: 1, y: 2 }
```
On nightly, it can use a plugin with:
```
% rustup run nightly cargo run --features unstable --no-default-features
```
-25
View File
@@ -1,25 +0,0 @@
#[cfg(not(feature = "serde_derive"))]
mod inner {
extern crate serde_codegen;
use std::env;
use std::path::Path;
pub fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let src = Path::new("src/main.rs.in");
let dst = Path::new(&out_dir).join("main.rs");
serde_codegen::expand(&src, &dst).unwrap();
}
}
#[cfg(feature = "serde_derive")]
mod inner {
pub fn main() {}
}
fn main() {
inner::main();
}
-12
View File
@@ -1,12 +0,0 @@
#[cfg(feature = "serde_derive")]
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
#[cfg(feature = "serde_derive")]
include!("main.rs.in");
#[cfg(not(feature = "serde_derive"))]
include!(concat!(env!("OUT_DIR"), "/main.rs"));
@@ -1,16 +0,0 @@
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
println!("{}", serialized);
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
println!("{:?}", deserialized);
}
+9 -6
View File
@@ -1,16 +1,16 @@
[package]
name = "serde"
version = "0.9.1"
version = "0.9.11"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde/"
readme = "../README.md"
keywords = ["serde", "serialization"]
keywords = ["serde", "serialization", "no_std"]
categories = ["encoding"]
include = ["Cargo.toml", "src/**/*.rs"]
readme = "../README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[badges]
travis-ci = { repository = "serde-rs/serde" }
@@ -22,10 +22,13 @@ std = []
unstable = []
alloc = ["unstable"]
collections = ["alloc"]
unstable-testing = ["clippy", "unstable", "std"]
unstable-testing = ["unstable", "std"]
# to get serde_derive picked up by play.integer32.com
playground = ["serde_derive"]
[dependencies]
clippy = { version = "0.*", optional = true }
serde_derive = { version = "0.9", optional = true }
[dev-dependencies]
serde_derive = "0.9"
+1
View File
@@ -0,0 +1 @@
../LICENSE-APACHE
+1
View File
@@ -0,0 +1 @@
../LICENSE-MIT
+1
View File
@@ -0,0 +1 @@
../README.md
+22 -17
View File
@@ -60,9 +60,7 @@ pub struct Bytes<'a> {
impl<'a> Bytes<'a> {
/// Wrap an existing `&[u8]`.
pub fn new(bytes: &'a [u8]) -> Self {
Bytes {
bytes: bytes,
}
Bytes { bytes: bytes }
}
}
@@ -98,7 +96,9 @@ impl<'a> Into<&'a [u8]> for Bytes<'a> {
impl<'a> ops::Deref for Bytes<'a> {
type Target = [u8];
fn deref(&self) -> &[u8] { self.bytes }
fn deref(&self) -> &[u8] {
self.bytes
}
}
impl<'a> ser::Serialize for Bytes<'a> {
@@ -114,6 +114,7 @@ impl<'a> ser::Serialize for Bytes<'a> {
#[cfg(any(feature = "std", feature = "collections"))]
mod bytebuf {
use core::cmp;
use core::ops;
use core::fmt;
use core::fmt::Write;
@@ -161,9 +162,7 @@ mod bytebuf {
/// Wrap existing bytes in a `ByteBuf`.
pub fn from<T: Into<Vec<u8>>>(bytes: T) -> Self {
ByteBuf {
bytes: bytes.into(),
}
ByteBuf { bytes: bytes.into() }
}
}
@@ -216,11 +215,15 @@ mod bytebuf {
impl ops::Deref for ByteBuf {
type Target = [u8];
fn deref(&self) -> &[u8] { &self.bytes[..] }
fn deref(&self) -> &[u8] {
&self.bytes[..]
}
}
impl ops::DerefMut for ByteBuf {
fn deref_mut(&mut self) -> &mut [u8] { &mut self.bytes[..] }
fn deref_mut(&mut self) -> &mut [u8] {
&mut self.bytes[..]
}
}
impl ser::Serialize for ByteBuf {
@@ -243,16 +246,16 @@ mod bytebuf {
#[inline]
fn visit_unit<E>(self) -> Result<ByteBuf, E>
where E: de::Error,
where E: de::Error
{
Ok(ByteBuf::new())
}
#[inline]
fn visit_seq<V>(self, mut visitor: V) -> Result<ByteBuf, V::Error>
where V: de::SeqVisitor,
where V: de::SeqVisitor
{
let (len, _) = visitor.size_hint();
let len = cmp::min(visitor.size_hint().0, 4096);
let mut values = Vec::with_capacity(len);
while let Some(value) = try!(visitor.visit()) {
@@ -264,26 +267,26 @@ mod bytebuf {
#[inline]
fn visit_bytes<E>(self, v: &[u8]) -> Result<ByteBuf, E>
where E: de::Error,
where E: de::Error
{
Ok(ByteBuf::from(v))
}
#[inline]
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<ByteBuf, E>
where E: de::Error,
where E: de::Error
{
Ok(ByteBuf::from(v))
}
fn visit_str<E>(self, v: &str) -> Result<ByteBuf, E>
where E: de::Error,
where E: de::Error
{
Ok(ByteBuf::from(v))
}
fn visit_string<E>(self, v: String) -> Result<ByteBuf, E>
where E: de::Error,
where E: de::Error
{
Ok(ByteBuf::from(v))
}
@@ -302,7 +305,9 @@ mod bytebuf {
///////////////////////////////////////////////////////////////////////////////
#[inline]
fn escape_bytestring<'a>(bytes: &'a [u8]) -> iter::FlatMap<slice::Iter<'a, u8>, char::EscapeDefault, fn(&u8) -> char::EscapeDefault> {
fn escape_bytestring<'a>
(bytes: &'a [u8])
-> iter::FlatMap<slice::Iter<'a, u8>, char::EscapeDefault, fn(&u8) -> char::EscapeDefault> {
fn f(b: &u8) -> char::EscapeDefault {
char::from_u32(*b as u32).unwrap().escape_default()
}
File diff suppressed because it is too large Load Diff
+176 -171
View File
@@ -6,32 +6,16 @@ use std::borrow::Cow;
use collections::borrow::Cow;
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::{
BinaryHeap,
BTreeMap,
BTreeSet,
LinkedList,
VecDeque,
Vec,
String,
};
use collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque, Vec, String};
#[cfg(feature = "std")]
use std::collections::{
HashMap,
HashSet,
BinaryHeap,
BTreeMap,
BTreeSet,
LinkedList,
VecDeque,
};
use std::collections::{HashMap, HashSet, BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
#[cfg(feature = "collections")]
use collections::enum_set::{CLike, EnumSet};
#[cfg(feature = "collections")]
use collections::borrow::ToOwned;
#[cfg(any(feature = "std", feature = "collections"))]
use core::cmp;
use core::fmt;
#[cfg(feature = "std")]
use core::hash::{Hash, BuildHasher};
@@ -41,6 +25,8 @@ use std::net;
#[cfg(feature = "std")]
use std::path;
use core::str;
#[cfg(feature = "std")]
use std::ffi::CString;
#[cfg(feature = "std")]
use std::rc::Rc;
@@ -65,19 +51,13 @@ use core::nonzero::{NonZero, Zeroable};
#[allow(deprecated)] // required for impl Deserialize for NonZero<T>
use core::num::Zero;
use de::{
Deserialize,
Deserializer,
EnumVisitor,
Error,
MapVisitor,
SeqVisitor,
Unexpected,
VariantVisitor,
Visitor,
};
use de::{Deserialize, Deserializer, EnumVisitor, Error, MapVisitor, SeqVisitor, Unexpected,
VariantVisitor, Visitor};
use de::from_primitive::FromPrimitive;
#[cfg(feature = "std")]
use bytes::ByteBuf;
///////////////////////////////////////////////////////////////////////////////
/// A visitor that produces a `()`.
@@ -91,13 +71,13 @@ impl Visitor for UnitVisitor {
}
fn visit_unit<E>(self) -> Result<(), E>
where E: Error,
where E: Error
{
Ok(())
}
fn visit_seq<V>(self, _: V) -> Result<(), V::Error>
where V: SeqVisitor,
where V: SeqVisitor
{
Ok(())
}
@@ -105,7 +85,7 @@ impl Visitor for UnitVisitor {
impl Deserialize for () {
fn deserialize<D>(deserializer: D) -> Result<(), D::Error>
where D: Deserializer,
where D: Deserializer
{
deserializer.deserialize_unit(UnitVisitor)
}
@@ -124,13 +104,13 @@ impl Visitor for BoolVisitor {
}
fn visit_bool<E>(self, v: bool) -> Result<bool, E>
where E: Error,
where E: Error
{
Ok(v)
}
fn visit_str<E>(self, s: &str) -> Result<bool, E>
where E: Error,
where E: Error
{
match s.trim_matches(::utils::Pattern_White_Space) {
"true" => Ok(true),
@@ -142,7 +122,7 @@ impl Visitor for BoolVisitor {
impl Deserialize for bool {
fn deserialize<D>(deserializer: D) -> Result<bool, D::Error>
where D: Deserializer,
where D: Deserializer
{
deserializer.deserialize_bool(BoolVisitor)
}
@@ -233,14 +213,14 @@ impl Visitor for CharVisitor {
#[inline]
fn visit_char<E>(self, v: char) -> Result<char, E>
where E: Error,
where E: Error
{
Ok(v)
}
#[inline]
fn visit_str<E>(self, v: &str) -> Result<char, E>
where E: Error,
where E: Error
{
let mut iter = v.chars();
match (iter.next(), iter.next()) {
@@ -253,7 +233,7 @@ impl Visitor for CharVisitor {
impl Deserialize for char {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<char, D::Error>
where D: Deserializer,
where D: Deserializer
{
deserializer.deserialize_char(CharVisitor)
}
@@ -273,25 +253,25 @@ impl Visitor for StringVisitor {
}
fn visit_str<E>(self, v: &str) -> Result<String, E>
where E: Error,
where E: Error
{
Ok(v.to_owned())
}
fn visit_string<E>(self, v: String) -> Result<String, E>
where E: Error,
where E: Error
{
Ok(v)
}
fn visit_unit<E>(self) -> Result<String, E>
where E: Error,
where E: Error
{
Ok(String::new())
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<String, E>
where E: Error,
where E: Error
{
match str::from_utf8(v) {
Ok(s) => Ok(s.to_owned()),
@@ -300,7 +280,7 @@ impl Visitor for StringVisitor {
}
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<String, E>
where E: Error,
where E: Error
{
match String::from_utf8(v) {
Ok(s) => Ok(s),
@@ -312,7 +292,7 @@ impl Visitor for StringVisitor {
#[cfg(any(feature = "std", feature = "collections"))]
impl Deserialize for String {
fn deserialize<D>(deserializer: D) -> Result<String, D::Error>
where D: Deserializer,
where D: Deserializer
{
deserializer.deserialize_string(StringVisitor)
}
@@ -320,13 +300,23 @@ impl Deserialize for String {
///////////////////////////////////////////////////////////////////////////////
#[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>,
}
impl<
T: Deserialize,
> Visitor for OptionVisitor<T> {
impl<T: Deserialize> Visitor for OptionVisitor<T> {
type Value = Option<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
@@ -335,29 +325,31 @@ impl<
#[inline]
fn visit_unit<E>(self) -> Result<Option<T>, E>
where E: Error,
where E: Error
{
Ok(None)
}
#[inline]
fn visit_none<E>(self) -> Result<Option<T>, E>
where E: Error,
where E: Error
{
Ok(None)
}
#[inline]
fn visit_some<D>(self, deserializer: D) -> Result<Option<T>, D::Error>
where D: Deserializer,
where D: Deserializer
{
Ok(Some(try!(Deserialize::deserialize(deserializer))))
}
}
impl<T> Deserialize for Option<T> where T: Deserialize {
impl<T> Deserialize for Option<T>
where T: Deserialize
{
fn deserialize<D>(deserializer: D) -> Result<Option<T>, D::Error>
where D: Deserializer,
where D: Deserializer
{
deserializer.deserialize_option(OptionVisitor { marker: PhantomData })
}
@@ -379,7 +371,7 @@ impl<T> Visitor for PhantomDataVisitor<T> {
#[inline]
fn visit_unit<E>(self) -> Result<PhantomData<T>, E>
where E: Error,
where E: Error
{
Ok(PhantomData)
}
@@ -387,7 +379,7 @@ impl<T> Visitor for PhantomDataVisitor<T> {
impl<T> Deserialize for PhantomData<T> {
fn deserialize<D>(deserializer: D) -> Result<PhantomData<T>, D::Error>
where D: Deserializer,
where D: Deserializer
{
let visitor = PhantomDataVisitor { marker: PhantomData };
deserializer.deserialize_unit_struct("PhantomData", visitor)
@@ -469,7 +461,7 @@ seq_impl!(
BinaryHeapVisitor<T: Deserialize + Ord>,
visitor,
BinaryHeap::new(),
BinaryHeap::with_capacity(visitor.size_hint().0),
BinaryHeap::with_capacity(cmp::min(visitor.size_hint().0, 4096)),
BinaryHeap::push);
#[cfg(any(feature = "std", feature = "collections"))]
@@ -481,15 +473,6 @@ seq_impl!(
BTreeSet::new(),
BTreeSet::insert);
#[cfg(feature = "collections")]
seq_impl!(
EnumSet<T>,
EnumSetVisitor<T: Deserialize + CLike>,
visitor,
EnumSet::new(),
EnumSet::new(),
EnumSet::insert);
#[cfg(any(feature = "std", feature = "collections"))]
seq_impl!(
LinkedList<T>,
@@ -506,7 +489,7 @@ seq_impl!(
S: BuildHasher + Default>,
visitor,
HashSet::with_hasher(S::default()),
HashSet::with_capacity_and_hasher(visitor.size_hint().0, S::default()),
HashSet::with_capacity_and_hasher(cmp::min(visitor.size_hint().0, 4096), S::default()),
HashSet::insert);
#[cfg(any(feature = "std", feature = "collections"))]
@@ -515,7 +498,7 @@ seq_impl!(
VecVisitor<T: Deserialize>,
visitor,
Vec::new(),
Vec::with_capacity(visitor.size_hint().0),
Vec::with_capacity(cmp::min(visitor.size_hint().0, 4096)),
Vec::push);
#[cfg(any(feature = "std", feature = "collections"))]
@@ -524,7 +507,7 @@ seq_impl!(
VecDequeVisitor<T: Deserialize>,
visitor,
VecDeque::new(),
VecDeque::with_capacity(visitor.size_hint().0),
VecDeque::with_capacity(cmp::min(visitor.size_hint().0, 4096)),
VecDeque::push_back);
///////////////////////////////////////////////////////////////////////////////
@@ -535,13 +518,13 @@ struct ArrayVisitor<A> {
impl<A> ArrayVisitor<A> {
pub fn new() -> Self {
ArrayVisitor {
marker: PhantomData,
}
ArrayVisitor { marker: PhantomData }
}
}
impl<T> Visitor for ArrayVisitor<[T; 0]> where T: Deserialize {
impl<T> Visitor for ArrayVisitor<[T; 0]>
where T: Deserialize
{
type Value = [T; 0];
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
@@ -550,14 +533,14 @@ impl<T> Visitor for ArrayVisitor<[T; 0]> where T: Deserialize {
#[inline]
fn visit_unit<E>(self) -> Result<[T; 0], E>
where E: Error,
where E: Error
{
Ok([])
}
#[inline]
fn visit_seq<V>(self, _: V) -> Result<[T; 0], V::Error>
where V: SeqVisitor,
where V: SeqVisitor
{
Ok([])
}
@@ -567,14 +550,14 @@ impl<T> Deserialize for [T; 0]
where T: Deserialize
{
fn deserialize<D>(deserializer: D) -> Result<[T; 0], D::Error>
where D: Deserializer,
where D: Deserializer
{
deserializer.deserialize_seq_fixed_size(0, ArrayVisitor::<[T; 0]>::new())
}
}
macro_rules! array_impls {
($($len:expr => ($($name:ident)+))+) => {
($($len:expr => ($($n:tt $name:ident)+))+) => {
$(
impl<T> Visitor for ArrayVisitor<[T; $len]> where T: Deserialize {
type Value = [T; $len];
@@ -590,7 +573,7 @@ macro_rules! array_impls {
$(
let $name = match try!(visitor.visit()) {
Some(val) => val,
None => return Err(Error::invalid_length(0, &self)),
None => return Err(Error::invalid_length($n, &self)),
};
)+
@@ -612,44 +595,44 @@ macro_rules! array_impls {
}
array_impls! {
1 => (a)
2 => (a b)
3 => (a b c)
4 => (a b c d)
5 => (a b c d e)
6 => (a b c d e f)
7 => (a b c d e f g)
8 => (a b c d e f g h)
9 => (a b c d e f g h i)
10 => (a b c d e f g h i j)
11 => (a b c d e f g h i j k)
12 => (a b c d e f g h i j k l)
13 => (a b c d e f g h i j k l m)
14 => (a b c d e f g h i j k l m n)
15 => (a b c d e f g h i j k l m n o)
16 => (a b c d e f g h i j k l m n o p)
17 => (a b c d e f g h i j k l m n o p q)
18 => (a b c d e f g h i j k l m n o p q r)
19 => (a b c d e f g h i j k l m n o p q r s)
20 => (a b c d e f g h i j k l m n o p q r s t)
21 => (a b c d e f g h i j k l m n o p q r s t u)
22 => (a b c d e f g h i j k l m n o p q r s t u v)
23 => (a b c d e f g h i j k l m n o p q r s t u v w)
24 => (a b c d e f g h i j k l m n o p q r s t u v w x)
25 => (a b c d e f g h i j k l m n o p q r s t u v w x y)
26 => (a b c d e f g h i j k l m n o p q r s t u v w x y z)
27 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa)
28 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab)
29 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac)
30 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad)
31 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad ae)
32 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad ae af)
1 => (0 a)
2 => (0 a 1 b)
3 => (0 a 1 b 2 c)
4 => (0 a 1 b 2 c 3 d)
5 => (0 a 1 b 2 c 3 d 4 e)
6 => (0 a 1 b 2 c 3 d 4 e 5 f)
7 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g)
8 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h)
9 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i)
10 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j)
11 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k)
12 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l)
13 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m)
14 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n)
15 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o)
16 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p)
17 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q)
18 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r)
19 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s)
20 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t)
21 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u)
22 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v)
23 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w)
24 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x)
25 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y)
26 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z)
27 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa)
28 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab)
29 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab 28 ac)
30 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab 28 ac 29 ad)
31 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab 28 ac 29 ad 30 ae)
32 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab 28 ac 29 ad 30 ae 31 af)
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! tuple_impls {
($($len:expr => $visitor:ident => ($($name:ident)+))+) => {
($($len:expr => $visitor:ident => ($($n:tt $name:ident)+))+) => {
$(
/// Construct a tuple visitor.
pub struct $visitor<$($name,)+> {
@@ -678,7 +661,7 @@ macro_rules! tuple_impls {
$(
let $name = match try!(visitor.visit()) {
Some(value) => value,
None => return Err(Error::invalid_length(0, &self)),
None => return Err(Error::invalid_length($n, &self)),
};
)+
@@ -699,22 +682,22 @@ macro_rules! tuple_impls {
}
tuple_impls! {
1 => TupleVisitor1 => (T0)
2 => TupleVisitor2 => (T0 T1)
3 => TupleVisitor3 => (T0 T1 T2)
4 => TupleVisitor4 => (T0 T1 T2 T3)
5 => TupleVisitor5 => (T0 T1 T2 T3 T4)
6 => TupleVisitor6 => (T0 T1 T2 T3 T4 T5)
7 => TupleVisitor7 => (T0 T1 T2 T3 T4 T5 T6)
8 => TupleVisitor8 => (T0 T1 T2 T3 T4 T5 T6 T7)
9 => TupleVisitor9 => (T0 T1 T2 T3 T4 T5 T6 T7 T8)
10 => TupleVisitor10 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9)
11 => TupleVisitor11 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10)
12 => TupleVisitor12 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11)
13 => TupleVisitor13 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12)
14 => TupleVisitor14 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13)
15 => TupleVisitor15 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14)
16 => TupleVisitor16 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15)
1 => TupleVisitor1 => (0 T0)
2 => TupleVisitor2 => (0 T0 1 T1)
3 => TupleVisitor3 => (0 T0 1 T1 2 T2)
4 => TupleVisitor4 => (0 T0 1 T1 2 T2 3 T3)
5 => TupleVisitor5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
6 => TupleVisitor6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
7 => TupleVisitor7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
8 => TupleVisitor8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
9 => TupleVisitor9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
10 => TupleVisitor10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
11 => TupleVisitor11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
12 => TupleVisitor12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
13 => TupleVisitor13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
14 => TupleVisitor14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
15 => TupleVisitor15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
16 => TupleVisitor16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
}
///////////////////////////////////////////////////////////////////////////////
@@ -802,14 +785,14 @@ map_impl!(
S: BuildHasher + Default>,
visitor,
HashMap::with_hasher(S::default()),
HashMap::with_capacity_and_hasher(visitor.size_hint().0, S::default()));
HashMap::with_capacity_and_hasher(cmp::min(visitor.size_hint().0, 4096), S::default()));
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl Deserialize for net::IpAddr {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer,
where D: Deserializer
{
let s = try!(String::deserialize(deserializer));
match s.parse() {
@@ -822,7 +805,7 @@ impl Deserialize for net::IpAddr {
#[cfg(feature = "std")]
impl Deserialize for net::Ipv4Addr {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer,
where D: Deserializer
{
let s = try!(String::deserialize(deserializer));
match s.parse() {
@@ -835,7 +818,7 @@ impl Deserialize for net::Ipv4Addr {
#[cfg(feature = "std")]
impl Deserialize for net::Ipv6Addr {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer,
where D: Deserializer
{
let s = try!(String::deserialize(deserializer));
match s.parse() {
@@ -850,7 +833,7 @@ impl Deserialize for net::Ipv6Addr {
#[cfg(feature = "std")]
impl Deserialize for net::SocketAddr {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer,
where D: Deserializer
{
let s = try!(String::deserialize(deserializer));
match s.parse() {
@@ -863,7 +846,7 @@ impl Deserialize for net::SocketAddr {
#[cfg(feature = "std")]
impl Deserialize for net::SocketAddrV4 {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer,
where D: Deserializer
{
let s = try!(String::deserialize(deserializer));
match s.parse() {
@@ -876,7 +859,7 @@ impl Deserialize for net::SocketAddrV4 {
#[cfg(feature = "std")]
impl Deserialize for net::SocketAddrV6 {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer,
where D: Deserializer
{
let s = try!(String::deserialize(deserializer));
match s.parse() {
@@ -900,13 +883,13 @@ impl Visitor for PathBufVisitor {
}
fn visit_str<E>(self, v: &str) -> Result<path::PathBuf, E>
where E: Error,
where E: Error
{
Ok(From::from(v))
}
fn visit_string<E>(self, v: String) -> Result<path::PathBuf, E>
where E: Error,
where E: Error
{
Ok(From::from(v))
}
@@ -915,7 +898,7 @@ impl Visitor for PathBufVisitor {
#[cfg(feature = "std")]
impl Deserialize for path::PathBuf {
fn deserialize<D>(deserializer: D) -> Result<path::PathBuf, D::Error>
where D: Deserializer,
where D: Deserializer
{
deserializer.deserialize_string(PathBufVisitor)
}
@@ -926,7 +909,7 @@ impl Deserialize for path::PathBuf {
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Deserialize> Deserialize for Box<T> {
fn deserialize<D>(deserializer: D) -> Result<Box<T>, D::Error>
where D: Deserializer,
where D: Deserializer
{
let val = try!(Deserialize::deserialize(deserializer));
Ok(Box::new(val))
@@ -936,7 +919,7 @@ impl<T: Deserialize> Deserialize for Box<T> {
#[cfg(any(feature = "std", feature = "collections"))]
impl<T: Deserialize> Deserialize for Box<[T]> {
fn deserialize<D>(deserializer: D) -> Result<Box<[T]>, D::Error>
where D: Deserializer,
where D: Deserializer
{
let v: Vec<T> = try!(Deserialize::deserialize(deserializer));
Ok(v.into_boxed_slice())
@@ -956,7 +939,7 @@ impl Deserialize for Box<str> {
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Deserialize> Deserialize for Arc<T> {
fn deserialize<D>(deserializer: D) -> Result<Arc<T>, D::Error>
where D: Deserializer,
where D: Deserializer
{
let val = try!(Deserialize::deserialize(deserializer));
Ok(Arc::new(val))
@@ -966,7 +949,7 @@ impl<T: Deserialize> Deserialize for Arc<T> {
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Deserialize> Deserialize for Rc<T> {
fn deserialize<D>(deserializer: D) -> Result<Rc<T>, D::Error>
where D: Deserializer,
where D: Deserializer
{
let val = try!(Deserialize::deserialize(deserializer));
Ok(Rc::new(val))
@@ -974,10 +957,13 @@ impl<T: Deserialize> Deserialize for Rc<T> {
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a, T: ?Sized> Deserialize for Cow<'a, T> where T: ToOwned, T::Owned: Deserialize, {
impl<'a, T: ?Sized> Deserialize for Cow<'a, T>
where T: ToOwned,
T::Owned: Deserialize
{
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Cow<'a, T>, D::Error>
where D: Deserializer,
where D: Deserializer
{
let val = try!(Deserialize::deserialize(deserializer));
Ok(Cow::Owned(val))
@@ -997,13 +983,16 @@ impl<'a, T: ?Sized> Deserialize for Cow<'a, T> where T: ToOwned, T::Owned: Deser
#[cfg(feature = "std")]
impl Deserialize for Duration {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer,
where D: Deserializer
{
enum Field { Secs, Nanos };
enum Field {
Secs,
Nanos,
};
impl Deserialize for Field {
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
where D: Deserializer,
where D: Deserializer
{
struct FieldVisitor;
@@ -1015,7 +1004,7 @@ impl Deserialize for Duration {
}
fn visit_str<E>(self, value: &str) -> Result<Field, E>
where E: Error,
where E: Error
{
match value {
"secs" => Ok(Field::Secs),
@@ -1025,7 +1014,7 @@ impl Deserialize for Duration {
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E>
where E: Error,
where E: Error
{
match value {
b"secs" => Ok(Field::Secs),
@@ -1052,7 +1041,7 @@ impl Deserialize for Duration {
}
fn visit_seq<V>(self, mut visitor: V) -> Result<Duration, V::Error>
where V: SeqVisitor,
where V: SeqVisitor
{
let secs: u64 = match try!(visitor.visit()) {
Some(value) => value,
@@ -1070,7 +1059,7 @@ impl Deserialize for Duration {
}
fn visit_map<V>(self, mut visitor: V) -> Result<Duration, V::Error>
where V: MapVisitor,
where V: MapVisitor
{
let mut secs: Option<u64> = None;
let mut nanos: Option<u32> = None;
@@ -1111,24 +1100,30 @@ impl Deserialize for Duration {
#[cfg(feature = "unstable")]
#[allow(deprecated)] // num::Zero is deprecated but there is no replacement
impl<T> Deserialize for NonZero<T> where T: Deserialize + PartialEq + Zeroable + Zero {
fn deserialize<D>(deserializer: D) -> Result<NonZero<T>, D::Error> where D: Deserializer {
impl<T> Deserialize for NonZero<T>
where T: Deserialize + PartialEq + Zeroable + Zero
{
fn deserialize<D>(deserializer: D) -> Result<NonZero<T>, D::Error>
where D: Deserializer
{
let value = try!(Deserialize::deserialize(deserializer));
if value == Zero::zero() {
return Err(Error::custom("expected a non-zero value"))
}
unsafe {
Ok(NonZero::new(value))
return Err(Error::custom("expected a non-zero value"));
}
unsafe { Ok(NonZero::new(value)) }
}
}
///////////////////////////////////////////////////////////////////////////////
impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
impl<T, E> Deserialize for Result<T, E>
where T: Deserialize,
E: Deserialize
{
fn deserialize<D>(deserializer: D) -> Result<Result<T, E>, D::Error>
where D: Deserializer {
where D: Deserializer
{
enum Field {
Ok,
Err,
@@ -1148,15 +1143,21 @@ impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
formatter.write_str("`Ok` or `Err`")
}
fn visit_u32<E>(self, value: u32) -> Result<Field, E> where E: Error {
fn visit_u32<E>(self, value: u32) -> Result<Field, E>
where E: Error
{
match value {
0 => Ok(Field::Ok),
1 => Ok(Field::Err),
_ => Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self)),
_ => {
Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self))
}
}
}
fn visit_str<E>(self, value: &str) -> Result<Field, E> where E: Error {
fn visit_str<E>(self, value: &str) -> Result<Field, E>
where E: Error
{
match value {
"Ok" => Ok(Field::Ok),
"Err" => Ok(Field::Err),
@@ -1164,14 +1165,18 @@ impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
}
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E> where E: Error {
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E>
where E: Error
{
match value {
b"Ok" => Ok(Field::Ok),
b"Err" => Ok(Field::Err),
_ => {
match str::from_utf8(value) {
Ok(value) => Err(Error::unknown_variant(value, VARIANTS)),
Err(_) => Err(Error::invalid_value(Unexpected::Bytes(value), &self)),
Err(_) => {
Err(Error::invalid_value(Unexpected::Bytes(value), &self))
}
}
}
}
@@ -1219,7 +1224,7 @@ pub struct IgnoredAny;
impl Deserialize for IgnoredAny {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<IgnoredAny, D::Error>
where D: Deserializer,
where D: Deserializer
{
struct IgnoredAnyVisitor;
@@ -1252,7 +1257,7 @@ impl Deserialize for IgnoredAny {
#[inline]
fn visit_str<E>(self, _: &str) -> Result<IgnoredAny, E>
where E: Error,
where E: Error
{
Ok(IgnoredAny)
}
@@ -1264,14 +1269,14 @@ impl Deserialize for IgnoredAny {
#[inline]
fn visit_some<D>(self, _: D) -> Result<IgnoredAny, D::Error>
where D: Deserializer,
where D: Deserializer
{
Ok(IgnoredAny)
}
#[inline]
fn visit_newtype_struct<D>(self, _: D) -> Result<IgnoredAny, D::Error>
where D: Deserializer,
where D: Deserializer
{
Ok(IgnoredAny)
}
@@ -1283,7 +1288,7 @@ impl Deserialize for IgnoredAny {
#[inline]
fn visit_seq<V>(self, mut visitor: V) -> Result<IgnoredAny, V::Error>
where V: SeqVisitor,
where V: SeqVisitor
{
while let Some(_) = try!(visitor.visit::<IgnoredAny>()) {
// Gobble
@@ -1293,7 +1298,7 @@ impl Deserialize for IgnoredAny {
#[inline]
fn visit_map<V>(self, mut visitor: V) -> Result<IgnoredAny, V::Error>
where V: MapVisitor,
where V: MapVisitor
{
while let Some((_, _)) = try!(visitor.visit::<IgnoredAny, IgnoredAny>()) {
// Gobble
@@ -1303,7 +1308,7 @@ impl Deserialize for IgnoredAny {
#[inline]
fn visit_bytes<E>(self, _: &[u8]) -> Result<IgnoredAny, E>
where E: Error,
where E: Error
{
Ok(IgnoredAny)
}
+110 -102
View File
@@ -115,6 +115,8 @@ mod from_primitive;
// Helpers used by generated code. Not public API.
#[doc(hidden)]
pub mod private;
#[cfg(any(feature = "std", feature = "collections"))]
mod content;
///////////////////////////////////////////////////////////////////////////////
@@ -150,10 +152,7 @@ pub trait Error: Sized + error::Error {
/// where D: Deserializer
/// {
/// let s = try!(String::deserialize(deserializer));
/// match s.parse() {
/// Ok(s) => Ok(s),
/// Err(err) => Err(Error::custom(err)),
/// }
/// s.parse().map_err(Error::custom)
/// }
/// }
/// ```
@@ -182,7 +181,10 @@ pub trait Error: Sized + error::Error {
write!(formatter, "invalid type: {}, expected {}", self.unexp, self.exp)
}
}
Error::custom(InvalidType { unexp: unexp, exp: exp })
Error::custom(InvalidType {
unexp: unexp,
exp: exp,
})
}
/// Raised when a `Deserialize` receives a value of the right type but that
@@ -208,7 +210,10 @@ pub trait Error: Sized + error::Error {
write!(formatter, "invalid value: {}, expected {}", self.unexp, self.exp)
}
}
Error::custom(InvalidValue { unexp: unexp, exp: exp })
Error::custom(InvalidValue {
unexp: unexp,
exp: exp,
})
}
/// Raised when deserializing a sequence or map and the input data contains
@@ -230,7 +235,10 @@ pub trait Error: Sized + error::Error {
write!(formatter, "invalid length {}, expected {}", self.len, self.exp)
}
}
Error::custom(InvalidLength { len: len, exp: exp })
Error::custom(InvalidLength {
len: len,
exp: exp,
})
}
/// Raised when a `Deserialize` enum type received a variant with an
@@ -254,7 +262,10 @@ pub trait Error: Sized + error::Error {
}
}
}
Error::custom(UnknownVariant { variant: variant, expected: expected })
Error::custom(UnknownVariant {
variant: variant,
expected: expected,
})
}
/// Raised when a `Deserialize` struct type received a field with an
@@ -278,7 +289,10 @@ pub trait Error: Sized + error::Error {
}
}
}
Error::custom(UnknownField { field: field, expected: expected })
Error::custom(UnknownField {
field: field,
expected: expected,
})
}
/// Raised when a `Deserialize` struct type expected to receive a required
@@ -471,7 +485,9 @@ pub trait Expected {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result;
}
impl<T> Expected for T where T: Visitor {
impl<T> Expected for T
where T: Visitor
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
self.expecting(formatter)
}
@@ -491,8 +507,8 @@ impl<'a> Display for Expected + 'a {
///////////////////////////////////////////////////////////////////////////////
/// An implementation of this trait is a **data structure** that can be
/// deserialized from any data format supported by Serde.
/// A **data structure** that can be deserialized from any data format supported
/// by Serde.
///
/// Serde provides `Deserialize` implementations for many Rust primitive and
/// standard library types. The complete list is [here][de]. All of these can
@@ -522,8 +538,7 @@ pub trait Deserialize: Sized {
/// manual for more information about how to implement this method.
///
/// [impl-deserialize]: https://serde.rs/impl-deserialize.html
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer;
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer;
}
/// `DeserializeSeed` is the stateful form of the `Deserialize` trait. If you
@@ -671,8 +686,7 @@ pub trait DeserializeSeed: Sized {
/// Equivalent to the more common `Deserialize::deserialize` method, except
/// with some initial piece of data (the seed) passed in.
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where D: Deserializer;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error> where D: Deserializer;
}
impl<T> DeserializeSeed for PhantomData<T>
@@ -690,8 +704,8 @@ impl<T> DeserializeSeed for PhantomData<T>
///////////////////////////////////////////////////////////////////////////////
/// An implementation of this trait is a **data format** that can deserialize
/// any data structure supported by Serde.
/// A **data format** that can deserialize any data structure supported by
/// Serde.
///
/// The role of this trait is to define the deserialization half of the Serde
/// data model, which is a way to categorize every Rust data type into one of 28
@@ -785,56 +799,43 @@ pub trait Deserializer: Sized {
/// `Deserializer::deserialize` means your data type will be able to
/// deserialize from self-describing formats only, ruling out Bincode and
/// many others.
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting a `bool` value.
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting a `u8` value.
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting a `u16` value.
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting a `u32` value.
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting a `u64` value.
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting an `i8` value.
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting an `i16` value.
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting an `i32` value.
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting an `i64` value.
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting a `f32` value.
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting a `f64` value.
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting a `char` value.
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting a string value and does
/// not benefit from taking ownership of buffered data owned by the
@@ -843,8 +844,7 @@ pub trait Deserializer: Sized {
/// If the `Visitor` would benefit from taking ownership of `String` data,
/// indiciate this to the `Deserializer` by using `deserialize_string`
/// instead.
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting a string value and would
/// benefit from taking ownership of buffered data owned by the
@@ -853,18 +853,16 @@ pub trait Deserializer: Sized {
/// If the `Visitor` would not benefit from taking ownership of `String`
/// data, indicate that to the `Deserializer` by using `deserialize_str`
/// instead.
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting a byte array and does not
/// benefit from taking ownership of buffered data owned by the
/// `Deserializer`.
///
/// If the `Visitor would benefit from taking ownership of `Vec<u8>` data,
/// If the `Visitor` would benefit from taking ownership of `Vec<u8>` data,
/// indicate this to the `Deserializer` by using `deserialize_byte_buf`
/// instead.
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting a byte array and would
/// benefit from taking ownership of buffered data owned by the
@@ -873,44 +871,43 @@ pub trait Deserializer: Sized {
/// If the `Visitor` would not benefit from taking ownership of `Vec<u8>`
/// data, indicate that to the `Deserializer` by using `deserialize_bytes`
/// instead.
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting an optional value.
///
/// This allows deserializers that encode an optional value as a nullable
/// value to convert the null value into `None` and a regular value into
/// `Some(value)`.
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting a unit value.
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting a unit struct with a
/// particular name.
fn deserialize_unit_struct<V>(self,
name: &'static str,
visitor: V) -> Result<V::Value, Self::Error>
visitor: V)
-> Result<V::Value, Self::Error>
where V: Visitor;
/// Hint that the `Deserialize` type is expecting a newtype struct with a
/// particular name.
fn deserialize_newtype_struct<V>(self,
name: &'static str,
visitor: V) -> Result<V::Value, Self::Error>
visitor: V)
-> Result<V::Value, Self::Error>
where V: Visitor;
/// Hint that the `Deserialize` type is expecting a sequence of values.
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting a sequence of values and
/// knows how many values there are without looking at the serialized data.
fn deserialize_seq_fixed_size<V>(self,
len: usize,
visitor: V) -> Result<V::Value, Self::Error>
visitor: V)
-> Result<V::Value, Self::Error>
where V: Visitor;
/// Hint that the `Deserialize` type is expecting a tuple value with a
@@ -923,19 +920,20 @@ pub trait Deserializer: Sized {
fn deserialize_tuple_struct<V>(self,
name: &'static str,
len: usize,
visitor: V) -> Result<V::Value, Self::Error>
visitor: V)
-> Result<V::Value, Self::Error>
where V: Visitor;
/// Hint that the `Deserialize` type is expecting a map of key-value pairs.
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
/// Hint that the `Deserialize` type is expecting a struct with a particular
/// name and fields.
fn deserialize_struct<V>(self,
name: &'static str,
fields: &'static [&'static str],
visitor: V) -> Result<V::Value, Self::Error>
visitor: V)
-> Result<V::Value, Self::Error>
where V: Visitor;
/// Hint that the `Deserialize` type is expecting the name of a struct
@@ -948,7 +946,8 @@ pub trait Deserializer: Sized {
fn deserialize_enum<V>(self,
name: &'static str,
variants: &'static [&'static str],
visitor: V) -> Result<V::Value, Self::Error>
visitor: V)
-> Result<V::Value, Self::Error>
where V: Visitor;
/// Hint that the `Deserialize` type needs to deserialize a value whose type
@@ -1017,77 +1016,77 @@ pub trait Visitor: Sized {
/// Deserialize a `bool` into a `Value`.
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
Err(Error::invalid_type(Unexpected::Bool(v), &self))
}
/// Deserialize an `i8` into a `Value`.
fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
self.visit_i64(v as i64)
}
/// Deserialize an `i16` into a `Value`.
fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
self.visit_i64(v as i64)
}
/// Deserialize an `i32` into a `Value`.
fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
self.visit_i64(v as i64)
}
/// Deserialize an `i64` into a `Value`.
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
Err(Error::invalid_type(Unexpected::Signed(v), &self))
}
/// Deserialize a `u8` into a `Value`.
fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
self.visit_u64(v as u64)
}
/// Deserialize a `u16` into a `Value`.
fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
self.visit_u64(v as u64)
}
/// Deserialize a `u32` into a `Value`.
fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
self.visit_u64(v as u64)
}
/// Deserialize a `u64` into a `Value`.
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
Err(Error::invalid_type(Unexpected::Unsigned(v), &self))
}
/// Deserialize a `f32` into a `Value`.
fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
self.visit_f64(v as f64)
}
/// Deserialize a `f64` into a `Value`.
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
Err(Error::invalid_type(Unexpected::Float(v), &self))
}
@@ -1095,7 +1094,7 @@ pub trait Visitor: Sized {
/// Deserialize a `char` into a `Value`.
#[inline]
fn visit_char<E>(self, v: char) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
self.visit_str(::utils::encode_utf8(v).as_str())
}
@@ -1111,7 +1110,7 @@ pub trait Visitor: Sized {
/// It is never correct to implement `visit_string` without implementing
/// `visit_str`. Implement neither, both, or just `visit_str`.
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
Err(Error::invalid_type(Unexpected::Str(v), &self))
}
@@ -1133,28 +1132,28 @@ pub trait Visitor: Sized {
#[inline]
#[cfg(any(feature = "std", feature = "collections"))]
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
self.visit_str(&v)
}
/// Deserialize a `()` into a `Value`.
fn visit_unit<E>(self) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
Err(Error::invalid_type(Unexpected::Unit, &self))
}
/// Deserialize an absent optional `Value`.
fn visit_none<E>(self) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
Err(Error::invalid_type(Unexpected::Option, &self))
}
/// Deserialize a present optional `Value`.
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where D: Deserializer,
where D: Deserializer
{
let _ = deserializer;
Err(Error::invalid_type(Unexpected::Option, &self))
@@ -1162,7 +1161,7 @@ pub trait Visitor: Sized {
/// Deserialize `Value` as a newtype struct.
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where D: Deserializer,
where D: Deserializer
{
let _ = deserializer;
Err(Error::invalid_type(Unexpected::NewtypeStruct, &self))
@@ -1170,7 +1169,7 @@ pub trait Visitor: Sized {
/// Deserialize `Value` as a sequence of elements.
fn visit_seq<V>(self, visitor: V) -> Result<Self::Value, V::Error>
where V: SeqVisitor,
where V: SeqVisitor
{
let _ = visitor;
Err(Error::invalid_type(Unexpected::Seq, &self))
@@ -1178,7 +1177,7 @@ pub trait Visitor: Sized {
/// Deserialize `Value` as a key-value map.
fn visit_map<V>(self, visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor,
where V: MapVisitor
{
let _ = visitor;
Err(Error::invalid_type(Unexpected::Map, &self))
@@ -1186,7 +1185,7 @@ pub trait Visitor: Sized {
/// Deserialize `Value` as an enum.
fn visit_enum<V>(self, visitor: V) -> Result<Self::Value, V::Error>
where V: EnumVisitor,
where V: EnumVisitor
{
let _ = visitor;
Err(Error::invalid_type(Unexpected::Enum, &self))
@@ -1203,7 +1202,7 @@ pub trait Visitor: Sized {
/// It is never correct to implement `visit_byte_buf` without implementing
/// `visit_bytes`. Implement neither, both, or just `visit_bytes`.
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
let _ = v;
Err(Error::invalid_type(Unexpected::Bytes(v), &self))
@@ -1226,7 +1225,7 @@ pub trait Visitor: Sized {
/// `Vec<u8>`.
#[cfg(any(feature = "std", feature = "collections"))]
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where E: Error,
where E: Error
{
self.visit_bytes(&v)
}
@@ -1270,7 +1269,9 @@ pub trait SeqVisitor {
}
}
impl<'a, V> SeqVisitor for &'a mut V where V: SeqVisitor {
impl<'a, V> SeqVisitor for &'a mut V
where V: SeqVisitor
{
type Error = V::Error;
#[inline]
@@ -1327,7 +1328,10 @@ pub trait MapVisitor {
/// `Deserialize` implementations should typically use `MapVisitor::visit`
/// instead.
#[inline]
fn visit_seed<K, V>(&mut self, kseed: K, vseed: V) -> Result<Option<(K::Value, V::Value)>, Self::Error>
fn visit_seed<K, V>(&mut self,
kseed: K,
vseed: V)
-> Result<Option<(K::Value, V::Value)>, Self::Error>
where K: DeserializeSeed,
V: DeserializeSeed
{
@@ -1336,7 +1340,7 @@ pub trait MapVisitor {
let value = try!(self.visit_value_seed(vseed));
Ok(Some((key, value)))
}
None => Ok(None)
None => Ok(None),
}
}
@@ -1371,7 +1375,7 @@ pub trait MapVisitor {
#[inline]
fn visit<K, V>(&mut self) -> Result<Option<(K, V)>, Self::Error>
where K: Deserialize,
V: Deserialize,
V: Deserialize
{
self.visit_seed(PhantomData, PhantomData)
}
@@ -1383,7 +1387,9 @@ pub trait MapVisitor {
}
}
impl<'a, V_> MapVisitor for &'a mut V_ where V_: MapVisitor {
impl<'a, V_> MapVisitor for &'a mut V_
where V_: MapVisitor
{
type Error = V_::Error;
#[inline]
@@ -1401,7 +1407,10 @@ impl<'a, V_> MapVisitor for &'a mut V_ where V_: MapVisitor {
}
#[inline]
fn visit_seed<K, V>(&mut self, kseed: K, vseed: V) -> Result<Option<(K::Value, V::Value)>, Self::Error>
fn visit_seed<K, V>(&mut self,
kseed: K,
vseed: V)
-> Result<Option<(K::Value, V::Value)>, Self::Error>
where K: DeserializeSeed,
V: DeserializeSeed
{
@@ -1411,7 +1420,7 @@ impl<'a, V_> MapVisitor for &'a mut V_ where V_: MapVisitor {
#[inline]
fn visit<K, V>(&mut self) -> Result<Option<(K, V)>, V_::Error>
where K: Deserialize,
V: Deserialize,
V: Deserialize
{
(**self).visit()
}
@@ -1447,7 +1456,7 @@ pub trait EnumVisitor: Sized {
type Error: Error;
/// The `Visitor` that will be used to deserialize the content of the enum
/// variant.
type Variant: VariantVisitor<Error=Self::Error>;
type Variant: VariantVisitor<Error = Self::Error>;
/// `visit_variant` is called to identify which variant to deserialize.
///
@@ -1540,9 +1549,7 @@ pub trait VariantVisitor: Sized {
/// Err(Error::invalid_type(unexp, &"tuple variant"))
/// }
/// ```
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: Visitor;
/// Called when deserializing a struct-like variant.
@@ -1565,7 +1572,8 @@ pub trait VariantVisitor: Sized {
/// ```
fn visit_struct<V>(self,
fields: &'static [&'static str],
visitor: V) -> Result<V::Value, Self::Error>
visitor: V)
-> Result<V::Value, Self::Error>
where V: Visitor;
}
+5
View File
@@ -2,6 +2,11 @@ use core::marker::PhantomData;
use de::{Deserialize, Deserializer, Error, Visitor};
#[cfg(any(feature = "std", feature = "collections"))]
pub use de::content::{Content, ContentRefDeserializer, ContentDeserializer, TaggedContentVisitor,
TagOrContentField, TagOrContentFieldVisitor, InternallyTaggedUnitVisitor,
UntaggedUnitVisitor};
/// If the missing field is of type `Option<T>` then treat is as `None`,
/// otherwise it is an error.
pub fn missing_field<V, E>(field: &'static str) -> Result<V, E>
+181 -139
View File
@@ -1,31 +1,15 @@
//! This module supports deserializing from primitives with the `ValueDeserializer` trait.
#[cfg(feature = "std")]
use std::collections::{
BTreeMap,
BTreeSet,
HashMap,
HashSet,
btree_map,
btree_set,
hash_map,
hash_set,
};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, btree_map, btree_set, hash_map,
hash_set};
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(feature = "std")]
use std::vec;
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::{
BTreeMap,
BTreeSet,
Vec,
String,
btree_map,
btree_set,
vec,
};
use collections::{BTreeMap, BTreeSet, Vec, String, btree_map, btree_set, vec};
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::borrow::Cow;
#[cfg(all(feature = "collections", not(feature = "std")))]
@@ -41,7 +25,7 @@ use std::error;
use error;
use core::fmt::{self, Display};
use core::iter::{self, Iterator};
use core::iter::{self, Iterator};
use core::marker::PhantomData;
use de::{self, Expected, SeqVisitor};
@@ -51,7 +35,9 @@ use bytes;
/// This represents all the possible errors that can occur using the `ValueDeserializer`.
#[derive(Clone, Debug, PartialEq)]
pub struct Error(ErrorImpl);
pub struct Error {
err: ErrorImpl,
}
#[cfg(any(feature = "std", feature = "collections"))]
type ErrorImpl = Box<str>;
@@ -61,19 +47,19 @@ type ErrorImpl = ();
impl de::Error for Error {
#[cfg(any(feature = "std", feature = "collections"))]
fn custom<T: Display>(msg: T) -> Self {
Error(msg.to_string().into_boxed_str())
Error { err: msg.to_string().into_boxed_str() }
}
#[cfg(not(any(feature = "std", feature = "collections")))]
fn custom<T: Display>(_msg: T) -> Self {
Error(())
Error { err: () }
}
}
impl Display for Error {
#[cfg(any(feature = "std", feature = "collections"))]
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(&self.0)
formatter.write_str(&self.err)
}
#[cfg(not(any(feature = "std", feature = "collections")))]
@@ -85,7 +71,7 @@ impl Display for Error {
impl error::Error for Error {
#[cfg(any(feature = "std", feature = "collections"))]
fn description(&self) -> &str {
&self.0
&self.err
}
#[cfg(not(any(feature = "std", feature = "collections")))]
@@ -99,7 +85,7 @@ impl error::Error for Error {
/// This trait converts primitive types into a deserializer.
pub trait ValueDeserializer<E: de::Error = Error> {
/// The actual deserializer type.
type Deserializer: de::Deserializer<Error=E>;
type Deserializer: de::Deserializer<Error = E>;
/// Convert this value into a deserializer.
fn into_deserializer(self) -> Self::Deserializer;
@@ -108,17 +94,19 @@ pub trait ValueDeserializer<E: de::Error = Error> {
///////////////////////////////////////////////////////////////////////////////
impl<E> ValueDeserializer<E> for ()
where E: de::Error,
where E: de::Error
{
type Deserializer = UnitDeserializer<E>;
fn into_deserializer(self) -> UnitDeserializer<E> {
UnitDeserializer(PhantomData)
UnitDeserializer { marker: PhantomData }
}
}
/// A helper deserializer that deserializes a `()`.
pub struct UnitDeserializer<E>(PhantomData<E>);
pub struct UnitDeserializer<E> {
marker: PhantomData<E>,
}
impl<E> de::Deserializer for UnitDeserializer<E>
where E: de::Error
@@ -132,13 +120,13 @@ impl<E> de::Deserializer for UnitDeserializer<E>
}
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
where V: de::Visitor
{
visitor.visit_unit()
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
where V: de::Visitor
{
visitor.visit_none()
}
@@ -149,7 +137,10 @@ impl<E> de::Deserializer for UnitDeserializer<E>
macro_rules! primitive_deserializer {
($ty:ty, $name:ident, $method:ident $($cast:tt)*) => {
/// A helper deserializer that deserializes a number.
pub struct $name<E>($ty, PhantomData<E>);
pub struct $name<E> {
value: $ty,
marker: PhantomData<E>
}
impl<E> ValueDeserializer<E> for $ty
where E: de::Error,
@@ -157,7 +148,10 @@ macro_rules! primitive_deserializer {
type Deserializer = $name<E>;
fn into_deserializer(self) -> $name<E> {
$name(self, PhantomData)
$name {
value: self,
marker: PhantomData,
}
}
}
@@ -175,7 +169,7 @@ macro_rules! primitive_deserializer {
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
visitor.$method(self.0 $($cast)*)
visitor.$method(self.value $($cast)*)
}
}
}
@@ -199,34 +193,41 @@ primitive_deserializer!(char, CharDeserializer, visit_char);
///////////////////////////////////////////////////////////////////////////////
/// A helper deserializer that deserializes a `&str`.
pub struct StrDeserializer<'a, E>(&'a str, PhantomData<E>);
pub struct StrDeserializer<'a, E> {
value: &'a str,
marker: PhantomData<E>,
}
impl<'a, E> ValueDeserializer<E> for &'a str
where E: de::Error,
where E: de::Error
{
type Deserializer = StrDeserializer<'a, E>;
fn into_deserializer(self) -> StrDeserializer<'a, E> {
StrDeserializer(self, PhantomData)
StrDeserializer {
value: self,
marker: PhantomData,
}
}
}
impl<'a, E> de::Deserializer for StrDeserializer<'a, E>
where E: de::Error,
where E: de::Error
{
type Error = E;
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
where V: de::Visitor
{
visitor.visit_str(self.0)
visitor.visit_str(self.value)
}
fn deserialize_enum<V>(self,
_name: &str,
_variants: &'static [&'static str],
visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
_name: &str,
_variants: &'static [&'static str],
visitor: V)
-> Result<V::Value, Self::Error>
where V: de::Visitor
{
visitor.visit_enum(self)
}
@@ -239,13 +240,13 @@ impl<'a, E> de::Deserializer for StrDeserializer<'a, E>
}
impl<'a, E> de::EnumVisitor for StrDeserializer<'a, E>
where E: de::Error,
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,
where T: de::DeserializeSeed
{
seed.deserialize(self).map(private::unit_only)
}
@@ -255,36 +256,43 @@ impl<'a, E> de::EnumVisitor for StrDeserializer<'a, E>
/// A helper deserializer that deserializes a `String`.
#[cfg(any(feature = "std", feature = "collections"))]
pub struct StringDeserializer<E>(String, PhantomData<E>);
pub struct StringDeserializer<E> {
value: String,
marker: PhantomData<E>,
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<E> ValueDeserializer<E> for String
where E: de::Error,
where E: de::Error
{
type Deserializer = StringDeserializer<E>;
fn into_deserializer(self) -> StringDeserializer<E> {
StringDeserializer(self, PhantomData)
StringDeserializer {
value: self,
marker: PhantomData,
}
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<E> de::Deserializer for StringDeserializer<E>
where E: de::Error,
where E: de::Error
{
type Error = E;
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
where V: de::Visitor
{
visitor.visit_string(self.0)
visitor.visit_string(self.value)
}
fn deserialize_enum<V>(self,
_name: &str,
_variants: &'static [&'static str],
visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
_name: &str,
_variants: &'static [&'static str],
visitor: V)
-> Result<V::Value, Self::Error>
where V: de::Visitor
{
visitor.visit_enum(self)
}
@@ -298,13 +306,13 @@ impl<E> de::Deserializer for StringDeserializer<E>
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a, E> de::EnumVisitor for StringDeserializer<E>
where E: de::Error,
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,
where T: de::DeserializeSeed
{
seed.deserialize(self).map(private::unit_only)
}
@@ -314,39 +322,46 @@ impl<'a, E> de::EnumVisitor for StringDeserializer<E>
/// A helper deserializer that deserializes a `String`.
#[cfg(any(feature = "std", feature = "collections"))]
pub struct CowStrDeserializer<'a, E>(Cow<'a, str>, PhantomData<E>);
pub struct CowStrDeserializer<'a, E> {
value: Cow<'a, str>,
marker: PhantomData<E>,
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a, E> ValueDeserializer<E> for Cow<'a, str>
where E: de::Error,
where E: de::Error
{
type Deserializer = CowStrDeserializer<'a, E>;
fn into_deserializer(self) -> CowStrDeserializer<'a, E> {
CowStrDeserializer(self, PhantomData)
CowStrDeserializer {
value: self,
marker: PhantomData,
}
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a, E> de::Deserializer for CowStrDeserializer<'a, E>
where E: de::Error,
where E: de::Error
{
type Error = E;
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
where V: de::Visitor
{
match self.0 {
match self.value {
Cow::Borrowed(string) => visitor.visit_str(string),
Cow::Owned(string) => visitor.visit_string(string),
}
}
fn deserialize_enum<V>(self,
_name: &str,
_variants: &'static [&'static str],
visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
_name: &str,
_variants: &'static [&'static str],
visitor: V)
-> Result<V::Value, Self::Error>
where V: de::Visitor
{
visitor.visit_enum(self)
}
@@ -360,13 +375,13 @@ impl<'a, E> de::Deserializer for CowStrDeserializer<'a, E>
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a, E> de::EnumVisitor for CowStrDeserializer<'a, E>
where E: de::Error,
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,
where T: de::DeserializeSeed
{
seed.deserialize(self).map(private::unit_only)
}
@@ -383,7 +398,7 @@ pub struct SeqDeserializer<I, E> {
impl<I, E> SeqDeserializer<I, E>
where I: Iterator,
E: de::Error,
E: de::Error
{
/// Construct a new `SeqDeserializer<I>`.
pub fn new(iter: I) -> Self {
@@ -394,7 +409,9 @@ impl<I, E> SeqDeserializer<I, E>
}
}
fn end(&mut self) -> Result<(), E> {
/// Check for remaining elements after passing a `SeqDeserializer` to
/// `Visitor::visit_seq`.
pub fn end(mut self) -> Result<(), E> {
let mut remaining = 0;
while self.iter.next().is_some() {
remaining += 1;
@@ -410,14 +427,14 @@ impl<I, E> SeqDeserializer<I, E>
}
impl<I, T, E> de::Deserializer for SeqDeserializer<I, E>
where I: Iterator<Item=T>,
where I: Iterator<Item = T>,
T: ValueDeserializer<E>,
E: de::Error,
E: de::Error
{
type Error = E;
fn deserialize<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
where V: de::Visitor
{
let v = try!(visitor.visit_seq(&mut self));
try!(self.end());
@@ -432,9 +449,9 @@ impl<I, T, E> de::Deserializer for SeqDeserializer<I, E>
}
impl<I, T, E> de::SeqVisitor for SeqDeserializer<I, E>
where I: Iterator<Item=T>,
where I: Iterator<Item = T>,
T: ValueDeserializer<E>,
E: de::Error,
E: de::Error
{
type Error = E;
@@ -472,7 +489,7 @@ impl Expected for ExpectedInSeq {
#[cfg(any(feature = "std", feature = "collections"))]
impl<T, E> ValueDeserializer<E> for Vec<T>
where T: ValueDeserializer<E>,
E: de::Error,
E: de::Error
{
type Deserializer = SeqDeserializer<vec::IntoIter<T>, E>;
@@ -484,7 +501,7 @@ impl<T, E> ValueDeserializer<E> for Vec<T>
#[cfg(any(feature = "std", feature = "collections"))]
impl<T, E> ValueDeserializer<E> for BTreeSet<T>
where T: ValueDeserializer<E> + Eq + Ord,
E: de::Error,
E: de::Error
{
type Deserializer = SeqDeserializer<btree_set::IntoIter<T>, E>;
@@ -496,7 +513,7 @@ impl<T, E> ValueDeserializer<E> for BTreeSet<T>
#[cfg(feature = "std")]
impl<T, E> ValueDeserializer<E> for HashSet<T>
where T: ValueDeserializer<E> + Eq + Hash,
E: de::Error,
E: de::Error
{
type Deserializer = SeqDeserializer<hash_set::IntoIter<T>, E>;
@@ -515,20 +532,20 @@ pub struct SeqVisitorDeserializer<V_, E> {
impl<V_, E> SeqVisitorDeserializer<V_, E>
where V_: de::SeqVisitor<Error = E>,
E: de::Error,
E: de::Error
{
/// Construct a new `SeqVisitorDeserializer<V_, E>`.
pub fn new(visitor: V_) -> Self {
SeqVisitorDeserializer{
SeqVisitorDeserializer {
visitor: visitor,
marker: PhantomData
marker: PhantomData,
}
}
}
impl<V_, E> de::Deserializer for SeqVisitorDeserializer<V_, E>
where V_: de::SeqVisitor<Error = E>,
E: de::Error,
E: de::Error
{
type Error = E;
@@ -551,7 +568,7 @@ pub struct MapDeserializer<I, E>
I::Item: private::Pair,
<I::Item as private::Pair>::First: ValueDeserializer<E>,
<I::Item as private::Pair>::Second: ValueDeserializer<E>,
E: de::Error,
E: de::Error
{
iter: iter::Fuse<I>,
value: Option<<I::Item as private::Pair>::Second>,
@@ -564,7 +581,7 @@ impl<I, E> MapDeserializer<I, E>
I::Item: private::Pair,
<I::Item as private::Pair>::First: ValueDeserializer<E>,
<I::Item as private::Pair>::Second: ValueDeserializer<E>,
E: de::Error,
E: de::Error
{
/// Construct a new `MapDeserializer<I, K, V, E>`.
pub fn new(iter: I) -> Self {
@@ -576,17 +593,9 @@ impl<I, E> MapDeserializer<I, E>
}
}
fn next_pair(&mut self) -> Option<(<I::Item as private::Pair>::First, <I::Item as private::Pair>::Second)> {
match self.iter.next() {
Some(kv) => {
self.count += 1;
Some(private::Pair::split(kv))
}
None => None,
}
}
fn end(&mut self) -> Result<(), E> {
/// Check for remaining elements after passing a `MapDeserializer` to
/// `Visitor::visit_map`.
pub fn end(mut self) -> Result<(), E> {
let mut remaining = 0;
while self.iter.next().is_some() {
remaining += 1;
@@ -599,6 +608,18 @@ impl<I, E> MapDeserializer<I, E>
Err(de::Error::invalid_length(self.count + remaining, &ExpectedInMap(self.count)))
}
}
fn next_pair
(&mut self)
-> Option<(<I::Item as private::Pair>::First, <I::Item as private::Pair>::Second)> {
match self.iter.next() {
Some(kv) => {
self.count += 1;
Some(private::Pair::split(kv))
}
None => None,
}
}
}
impl<I, E> de::Deserializer for MapDeserializer<I, E>
@@ -606,12 +627,12 @@ impl<I, E> de::Deserializer for MapDeserializer<I, E>
I::Item: private::Pair,
<I::Item as private::Pair>::First: ValueDeserializer<E>,
<I::Item as private::Pair>::Second: ValueDeserializer<E>,
E: de::Error,
E: de::Error
{
type Error = E;
fn deserialize<V_>(mut self, visitor: V_) -> Result<V_::Value, Self::Error>
where V_: de::Visitor,
where V_: de::Visitor
{
let value = try!(visitor.visit_map(&mut self));
try!(self.end());
@@ -619,15 +640,18 @@ impl<I, E> de::Deserializer for MapDeserializer<I, E>
}
fn deserialize_seq<V_>(mut self, visitor: V_) -> Result<V_::Value, Self::Error>
where V_: de::Visitor,
where V_: de::Visitor
{
let value = try!(visitor.visit_seq(&mut self));
try!(self.end());
Ok(value)
}
fn deserialize_seq_fixed_size<V_>(self, _len: usize, visitor: V_) -> Result<V_::Value, Self::Error>
where V_: de::Visitor,
fn deserialize_seq_fixed_size<V_>(self,
_len: usize,
visitor: V_)
-> Result<V_::Value, Self::Error>
where V_: de::Visitor
{
self.deserialize_seq(visitor)
}
@@ -644,12 +668,12 @@ impl<I, E> de::MapVisitor for MapDeserializer<I, E>
I::Item: private::Pair,
<I::Item as private::Pair>::First: ValueDeserializer<E>,
<I::Item as private::Pair>::Second: ValueDeserializer<E>,
E: de::Error,
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.next_pair() {
Some((key, value)) => {
@@ -661,7 +685,7 @@ impl<I, E> de::MapVisitor for MapDeserializer<I, E>
}
fn visit_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
where T: de::DeserializeSeed,
where T: de::DeserializeSeed
{
let value = self.value.take();
// Panic because this indicates a bug in the program rather than an
@@ -670,7 +694,10 @@ impl<I, E> de::MapVisitor for MapDeserializer<I, E>
seed.deserialize(value.into_deserializer())
}
fn visit_seed<TK, TV>(&mut self, kseed: TK, vseed: TV) -> Result<Option<(TK::Value, TV::Value)>, Self::Error>
fn visit_seed<TK, TV>(&mut self,
kseed: TK,
vseed: TV)
-> Result<Option<(TK::Value, TV::Value)>, Self::Error>
where TK: de::DeserializeSeed,
TV: de::DeserializeSeed
{
@@ -680,7 +707,7 @@ impl<I, E> de::MapVisitor for MapDeserializer<I, E>
let value = try!(vseed.deserialize(value.into_deserializer()));
Ok(Some((key, value)))
}
None => Ok(None)
None => Ok(None),
}
}
@@ -694,12 +721,12 @@ impl<I, E> de::SeqVisitor for MapDeserializer<I, E>
I::Item: private::Pair,
<I::Item as private::Pair>::First: ValueDeserializer<E>,
<I::Item as private::Pair>::Second: ValueDeserializer<E>,
E: de::Error,
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.next_pair() {
Some((k, v)) => {
@@ -733,13 +760,13 @@ impl<A, B, E> de::Deserializer for PairDeserializer<A, B, E>
}
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
where V: de::Visitor
{
self.deserialize_seq(visitor)
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
where V: de::Visitor
{
let mut pair_visitor = PairVisitor(Some(self.0), Some(self.1), PhantomData);
let pair = try!(visitor.visit_seq(&mut pair_visitor));
@@ -754,7 +781,7 @@ impl<A, B, E> de::Deserializer for PairDeserializer<A, B, E>
}
fn deserialize_seq_fixed_size<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
where V: de::Visitor
{
if len == 2 {
self.deserialize_seq(visitor)
@@ -771,12 +798,12 @@ struct PairVisitor<A, B, E>(Option<A>, Option<B>, PhantomData<E>);
impl<A, B, E> de::SeqVisitor for PairVisitor<A, B, E>
where A: ValueDeserializer<E>,
B: ValueDeserializer<E>,
E: de::Error,
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
{
if let Some(k) = self.0.take() {
seed.deserialize(k.into_deserializer()).map(Some)
@@ -817,7 +844,7 @@ impl Expected for ExpectedInMap {
impl<K, V, E> ValueDeserializer<E> for BTreeMap<K, V>
where K: ValueDeserializer<E> + Eq + Ord,
V: ValueDeserializer<E>,
E: de::Error,
E: de::Error
{
type Deserializer = MapDeserializer<btree_map::IntoIter<K, V>, E>;
@@ -830,7 +857,7 @@ impl<K, V, E> ValueDeserializer<E> for BTreeMap<K, V>
impl<K, V, E> ValueDeserializer<E> for HashMap<K, V>
where K: ValueDeserializer<E> + Eq + Hash,
V: ValueDeserializer<E>,
E: de::Error,
E: de::Error
{
type Deserializer = MapDeserializer<hash_map::IntoIter<K, V>, E>;
@@ -849,20 +876,20 @@ pub struct MapVisitorDeserializer<V_, E> {
impl<V_, E> MapVisitorDeserializer<V_, E>
where V_: de::MapVisitor<Error = E>,
E: de::Error,
E: de::Error
{
/// Construct a new `MapVisitorDeserializer<V_, E>`.
pub fn new(visitor: V_) -> Self {
MapVisitorDeserializer{
MapVisitorDeserializer {
visitor: visitor,
marker: PhantomData
marker: PhantomData,
}
}
}
impl<V_, E> de::Deserializer for MapVisitorDeserializer<V_, E>
where V_: de::MapVisitor<Error = E>,
E: de::Error,
E: de::Error
{
type Error = E;
@@ -880,17 +907,23 @@ impl<V_, E> de::Deserializer for MapVisitorDeserializer<V_, E>
///////////////////////////////////////////////////////////////////////////////
impl<'a, E> ValueDeserializer<E> for bytes::Bytes<'a>
where E: de::Error,
where E: de::Error
{
type Deserializer = BytesDeserializer<'a, E>;
fn into_deserializer(self) -> BytesDeserializer<'a, E> {
BytesDeserializer(self.into(), PhantomData)
BytesDeserializer {
value: self.into(),
marker: PhantomData,
}
}
}
/// A helper deserializer that deserializes a `&[u8]`.
pub struct BytesDeserializer<'a, E>(&'a [u8], PhantomData<E>);
pub struct BytesDeserializer<'a, E> {
value: &'a [u8],
marker: PhantomData<E>,
}
impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
where E: de::Error
@@ -898,9 +931,9 @@ impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
type Error = E;
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
where V: de::Visitor
{
visitor.visit_bytes(self.0)
visitor.visit_bytes(self.value)
}
forward_to_deserialize! {
@@ -914,29 +947,35 @@ impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
#[cfg(any(feature = "std", feature = "collections"))]
impl<E> ValueDeserializer<E> for bytes::ByteBuf
where E: de::Error,
where E: de::Error
{
type Deserializer = ByteBufDeserializer<E>;
fn into_deserializer(self) -> Self::Deserializer {
ByteBufDeserializer(self.into(), PhantomData)
ByteBufDeserializer {
value: self.into(),
marker: PhantomData,
}
}
}
/// A helper deserializer that deserializes a `Vec<u8>`.
#[cfg(any(feature = "std", feature = "collections"))]
pub struct ByteBufDeserializer<E>(Vec<u8>, PhantomData<E>);
pub struct ByteBufDeserializer<E> {
value: Vec<u8>,
marker: PhantomData<E>,
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<E> de::Deserializer for ByteBufDeserializer<E>
where E: de::Error,
where E: de::Error
{
type Error = E;
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
where V: de::Visitor
{
visitor.visit_byte_buf(self.0)
visitor.visit_byte_buf(self.value)
}
forward_to_deserialize! {
@@ -952,10 +991,12 @@ mod private {
use de::{self, Unexpected};
use core::marker::PhantomData;
pub struct UnitOnly<E>(PhantomData<E>);
pub struct UnitOnly<E> {
marker: PhantomData<E>,
}
pub fn unit_only<T, E>(t: T) -> (T, UnitOnly<E>) {
(t, UnitOnly(PhantomData))
(t, UnitOnly { marker: PhantomData })
}
impl<E> de::VariantVisitor for UnitOnly<E>
@@ -968,14 +1009,12 @@ mod private {
}
fn visit_newtype_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error>
where T: de::DeserializeSeed,
where T: de::DeserializeSeed
{
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"newtype variant"))
}
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
{
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"tuple variant"))
@@ -983,7 +1022,8 @@ mod private {
fn visit_struct<V>(self,
_fields: &'static [&'static str],
_visitor: V) -> Result<V::Value, Self::Error>
_visitor: V)
-> Result<V::Value, Self::Error>
where V: de::Visitor
{
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"struct variant"))
@@ -1001,6 +1041,8 @@ mod private {
impl<A, B> Pair for (A, B) {
type First = A;
type Second = B;
fn split(self) -> (A, B) { self }
fn split(self) -> (A, B) {
self
}
}
}
+3 -1
View File
@@ -11,5 +11,7 @@ pub trait Error: Debug + Display {
fn description(&self) -> &str;
/// The lower-level cause of this error, if any.
fn cause(&self) -> Option<&Error> { None }
fn cause(&self) -> Option<&Error> {
None
}
}
+2 -1
View File
@@ -9,7 +9,8 @@ use collections::borrow::Cow;
pub use core::default::Default;
pub use core::fmt;
pub use core::marker::PhantomData;
pub use core::result::Result;
pub use core::option::Option::{self, None, Some};
pub use core::result::Result::{self, Ok, Err};
#[cfg(any(feature = "collections", feature = "std"))]
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
+24 -12
View File
@@ -4,13 +4,13 @@ use std::io;
use std::iter::Peekable;
/// Iterator over a byte stream that tracks the current position's line and column.
pub struct LineColIterator<Iter: Iterator<Item=io::Result<u8>>> {
pub struct LineColIterator<Iter: Iterator<Item = io::Result<u8>>> {
iter: Iter,
line: usize,
col: usize,
}
impl<Iter: Iterator<Item=io::Result<u8>>> LineColIterator<Iter> {
impl<Iter: Iterator<Item = io::Result<u8>>> LineColIterator<Iter> {
/// Construct a new `LineColIterator<Iter>`.
pub fn new(iter: Iter) -> LineColIterator<Iter> {
LineColIterator {
@@ -21,27 +21,39 @@ impl<Iter: Iterator<Item=io::Result<u8>>> LineColIterator<Iter> {
}
/// Report the current line inside the iterator.
pub fn line(&self) -> usize { self.line }
pub fn line(&self) -> usize {
self.line
}
/// Report the current column inside the iterator.
pub fn col(&self) -> usize { self.col }
pub fn col(&self) -> usize {
self.col
}
/// Gets a reference to the underlying iterator.
pub fn get_ref(&self) -> &Iter { &self.iter }
pub fn get_ref(&self) -> &Iter {
&self.iter
}
/// Gets a mutable reference to the underlying iterator.
pub fn get_mut(&mut self) -> &mut Iter { &mut self.iter }
pub fn get_mut(&mut self) -> &mut Iter {
&mut self.iter
}
/// Unwraps this `LineColIterator`, returning the underlying iterator.
pub fn into_inner(self) -> Iter { self.iter }
pub fn into_inner(self) -> Iter {
self.iter
}
}
impl<Iter: Iterator<Item=io::Result<u8>>> LineColIterator<Peekable<Iter>> {
impl<Iter: Iterator<Item = io::Result<u8>>> LineColIterator<Peekable<Iter>> {
/// peeks at the next value
pub fn peek(&mut self) -> Option<&io::Result<u8>> { self.iter.peek() }
pub fn peek(&mut self) -> Option<&io::Result<u8>> {
self.iter.peek()
}
}
impl<Iter: Iterator<Item=io::Result<u8>>> Iterator for LineColIterator<Iter> {
impl<Iter: Iterator<Item = io::Result<u8>>> Iterator for LineColIterator<Iter> {
type Item = io::Result<u8>;
fn next(&mut self) -> Option<io::Result<u8>> {
match self.iter.next() {
@@ -50,11 +62,11 @@ impl<Iter: Iterator<Item=io::Result<u8>>> Iterator for LineColIterator<Iter> {
self.line += 1;
self.col = 0;
Some(Ok(b'\n'))
},
}
Some(Ok(c)) => {
self.col += 1;
Some(Ok(c))
},
}
Some(Err(e)) => Some(Err(e)),
}
}
+6 -6
View File
@@ -61,12 +61,10 @@
#![doc(html_root_url="https://docs.serde.rs")]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "unstable", feature(nonzero, inclusive_range, zero_one))]
#![cfg_attr(feature = "unstable", feature(inclusive_range, nonzero, specialization, zero_one))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "collections", feature(collections, enumset))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", allow(linkedlist, type_complexity))]
#![cfg_attr(feature = "collections", feature(collections))]
#![cfg_attr(feature = "cargo-clippy", allow(linkedlist, type_complexity, doc_markdown))]
#![deny(missing_docs)]
#[cfg(feature = "collections")]
@@ -81,12 +79,14 @@ 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};
usize, f32, f64, char, str, num, slice, iter, cell, default, result, option};
#[cfg(feature = "unstable")]
pub use actual_core::nonzero;
}
#[doc(inline)]
pub use ser::{Serialize, Serializer};
#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[macro_use]
+32
View File
@@ -188,3 +188,35 @@ macro_rules! forward_to_deserialize {
$(forward_to_deserialize_helper!{$func})*
};
}
/// Seralize the `$value` that implements Display as a string,
/// when that string is statically known to never have more than
/// a constant `$MAX_LEN` bytes.
///
/// Panics if the Display impl tries to write more than `$MAX_LEN` bytes.
#[cfg(feature = "std")]
// Not exported
macro_rules! serialize_display_bounded_length {
($value: expr, $MAX_LEN: expr, $serializer: expr) => {
{
use std::io::Write;
let mut buffer: [u8; $MAX_LEN] = unsafe { ::std::mem::uninitialized() };
let remaining_len;
{
let mut remaining = &mut buffer[..];
write!(remaining, "{}", $value).unwrap();
remaining_len = remaining.len()
}
let written_len = buffer.len() - remaining_len;
let written = &buffer[..written_len];
// write! only provides std::fmt::Formatter to Display implementations,
// which has methods write_str and write_char but no method to write arbitrary bytes.
// Therefore, `written` is well-formed in UTF-8.
let written_str = unsafe {
::std::str::from_utf8_unchecked(written)
};
$serializer.serialize_str(written_str)
}
}
}
+635
View File
@@ -0,0 +1,635 @@
use core::marker::PhantomData;
#[cfg(all(not(feature = "std"), feature = "collections"))]
use collections::{String, Vec};
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::boxed::Box;
#[cfg(feature = "collections")]
use collections::borrow::ToOwned;
use ser::{self, Serialize, Serializer};
pub struct SerializeTupleVariantAsMapValue<M> {
map: M,
name: &'static str,
fields: Vec<Content>,
}
impl<M> SerializeTupleVariantAsMapValue<M> {
pub fn new(map: M, name: &'static str, len: usize) -> Self {
SerializeTupleVariantAsMapValue {
map: map,
name: name,
fields: Vec::with_capacity(len),
}
}
}
impl<M> ser::SerializeTupleVariant for SerializeTupleVariantAsMapValue<M>
where M: ser::SerializeMap
{
type Ok = M::Ok;
type Error = 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(())
}
fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self.map.serialize_value(&Content::TupleStruct(self.name, self.fields)));
self.map.end()
}
}
pub struct SerializeStructVariantAsMapValue<M> {
map: M,
name: &'static str,
fields: Vec<(&'static str, Content)>,
}
impl<M> SerializeStructVariantAsMapValue<M> {
pub fn new(map: M, name: &'static str, len: usize) -> Self {
SerializeStructVariantAsMapValue {
map: map,
name: name,
fields: Vec::with_capacity(len),
}
}
}
impl<M> ser::SerializeStructVariant for SerializeStructVariantAsMapValue<M>
where M: ser::SerializeMap
{
type Ok = M::Ok;
type Error = M::Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
key: &'static str,
value: &T)
-> Result<(), M::Error>
{
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push((key, value));
Ok(())
}
fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self.map.serialize_value(&Content::Struct(self.name, self.fields)));
self.map.end()
}
}
#[derive(Debug)]
enum Content {
Bool(bool),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
F32(f32),
F64(f64),
Char(char),
String(String),
Bytes(Vec<u8>),
None,
Some(Box<Content>),
Unit,
UnitStruct(&'static str),
UnitVariant(&'static str, usize, &'static str),
NewtypeStruct(&'static str, Box<Content>),
NewtypeVariant(&'static str, usize, &'static str, Box<Content>),
Seq(Vec<Content>),
SeqFixedSize(Vec<Content>),
Tuple(Vec<Content>),
TupleStruct(&'static str, Vec<Content>),
TupleVariant(&'static str, usize, &'static str, Vec<Content>),
Map(Vec<(Content, Content)>),
Struct(&'static str, Vec<(&'static str, Content)>),
StructVariant(&'static str, usize, &'static str, Vec<(&'static str, Content)>),
}
impl Serialize for Content {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
match *self {
Content::Bool(b) => serializer.serialize_bool(b),
Content::U8(u) => serializer.serialize_u8(u),
Content::U16(u) => serializer.serialize_u16(u),
Content::U32(u) => serializer.serialize_u32(u),
Content::U64(u) => serializer.serialize_u64(u),
Content::I8(i) => serializer.serialize_i8(i),
Content::I16(i) => serializer.serialize_i16(i),
Content::I32(i) => serializer.serialize_i32(i),
Content::I64(i) => serializer.serialize_i64(i),
Content::F32(f) => serializer.serialize_f32(f),
Content::F64(f) => serializer.serialize_f64(f),
Content::Char(c) => serializer.serialize_char(c),
Content::String(ref s) => serializer.serialize_str(s),
Content::Bytes(ref b) => serializer.serialize_bytes(b),
Content::None => serializer.serialize_none(),
Content::Some(ref c) => serializer.serialize_some(&**c),
Content::Unit => serializer.serialize_unit(),
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::Seq(ref elements) => elements.serialize(serializer),
Content::SeqFixedSize(ref elements) => {
use ser::SerializeSeq;
let mut seq = try!(serializer.serialize_seq_fixed_size(elements.len()));
for e in elements {
try!(seq.serialize_element(e));
}
seq.end()
}
Content::Tuple(ref elements) => {
use ser::SerializeTuple;
let mut tuple = try!(serializer.serialize_tuple(elements.len()));
for e in elements {
try!(tuple.serialize_element(e));
}
tuple.end()
}
Content::TupleStruct(n, ref fields) => {
use ser::SerializeTupleStruct;
let mut ts = try!(serializer.serialize_tuple_struct(n, fields.len()));
for f in fields {
try!(ts.serialize_field(f));
}
ts.end()
}
Content::TupleVariant(n, i, v, ref fields) => {
use ser::SerializeTupleVariant;
let mut tv = try!(serializer.serialize_tuple_variant(n, i, v, fields.len()));
for f in fields {
try!(tv.serialize_field(f));
}
tv.end()
}
Content::Map(ref entries) => {
use ser::SerializeMap;
let mut map = try!(serializer.serialize_map(Some(entries.len())));
for &(ref k, ref v) in entries {
try!(map.serialize_entry(k, v));
}
map.end()
}
Content::Struct(n, ref fields) => {
use ser::SerializeStruct;
let mut s = try!(serializer.serialize_struct(n, fields.len()));
for &(k, ref v) in fields {
try!(s.serialize_field(k, v));
}
s.end()
}
Content::StructVariant(n, i, v, ref fields) => {
use ser::SerializeStructVariant;
let mut sv = try!(serializer.serialize_struct_variant(n, i, v, fields.len()));
for &(k, ref v) in fields {
try!(sv.serialize_field(k, v));
}
sv.end()
}
}
}
}
struct ContentSerializer<E> {
error: PhantomData<E>,
}
impl<E> ContentSerializer<E> {
fn new() -> Self {
ContentSerializer {
error: PhantomData,
}
}
}
impl<E> Serializer for ContentSerializer<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
type SerializeSeq = SerializeSeq<E>;
type SerializeTuple = SerializeTuple<E>;
type SerializeTupleStruct = SerializeTupleStruct<E>;
type SerializeTupleVariant = SerializeTupleVariant<E>;
type SerializeMap = SerializeMap<E>;
type SerializeStruct = SerializeStruct<E>;
type SerializeStructVariant = SerializeStructVariant<E>;
fn serialize_bool(self, v: bool) -> Result<Content, E> {
Ok(Content::Bool(v))
}
fn serialize_i8(self, v: i8) -> Result<Content, E> {
Ok(Content::I8(v))
}
fn serialize_i16(self, v: i16) -> Result<Content, E> {
Ok(Content::I16(v))
}
fn serialize_i32(self, v: i32) -> Result<Content, E> {
Ok(Content::I32(v))
}
fn serialize_i64(self, v: i64) -> Result<Content, E> {
Ok(Content::I64(v))
}
fn serialize_u8(self, v: u8) -> Result<Content, E> {
Ok(Content::U8(v))
}
fn serialize_u16(self, v: u16) -> Result<Content, E> {
Ok(Content::U16(v))
}
fn serialize_u32(self, v: u32) -> Result<Content, E> {
Ok(Content::U32(v))
}
fn serialize_u64(self, v: u64) -> Result<Content, E> {
Ok(Content::U64(v))
}
fn serialize_f32(self, v: f32) -> Result<Content, E> {
Ok(Content::F32(v))
}
fn serialize_f64(self, v: f64) -> Result<Content, E> {
Ok(Content::F64(v))
}
fn serialize_char(self, v: char) -> Result<Content, E> {
Ok(Content::Char(v))
}
fn serialize_str(self, value: &str) -> Result<Content, E> {
Ok(Content::String(value.to_owned()))
}
fn serialize_bytes(self, value: &[u8]) -> Result<Content, E> {
Ok(Content::Bytes(value.to_owned()))
}
fn serialize_none(self) -> Result<Content, E> {
Ok(Content::None)
}
fn serialize_some<T: ?Sized + Serialize>(self,
value: &T)
-> Result<Content, E> {
Ok(Content::Some(Box::new(try!(value.serialize(self)))))
}
fn serialize_unit(self) -> Result<Content, E> {
Ok(Content::Unit)
}
fn serialize_unit_struct(self,
name: &'static str)
-> Result<Content, E> {
Ok(Content::UnitStruct(name))
}
fn serialize_unit_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str)
-> Result<Content, E> {
Ok(Content::UnitVariant(name, variant_index, variant))
}
fn serialize_newtype_struct<T: ?Sized + Serialize>(self,
name: &'static str,
value: &T)
-> Result<Content, E> {
Ok(Content::NewtypeStruct(name, Box::new(try!(value.serialize(self)))))
}
fn serialize_newtype_variant<T: ?Sized + Serialize>(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
value: &T)
-> Result<Content, E> {
Ok(Content::NewtypeVariant(name, variant_index, variant, Box::new(try!(value.serialize(self)))))
}
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,
})
}
fn serialize_seq_fixed_size(self,
size: usize)
-> Result<Self::SerializeSeq, E> {
Ok(SerializeSeq {
fixed_size: true,
elements: Vec::with_capacity(size),
error: PhantomData,
})
}
fn serialize_tuple(self,
len: usize)
-> Result<Self::SerializeTuple, E> {
Ok(SerializeTuple {
elements: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_tuple_struct(self,
name: &'static str,
len: usize)
-> Result<Self::SerializeTupleStruct, E> {
Ok(SerializeTupleStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_tuple_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize)
-> Result<Self::SerializeTupleVariant, E> {
Ok(SerializeTupleVariant {
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> {
Ok(SerializeMap {
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> {
Ok(SerializeStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_struct_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize)
-> Result<Self::SerializeStructVariant, E> {
Ok(SerializeStructVariant {
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
}
struct SerializeSeq<E> {
fixed_size: bool,
elements: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeSeq for SerializeSeq<E>
where E: ser::Error
{
type Ok = Content;
type Error = 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(())
}
fn end(self) -> Result<Content, E> {
Ok(if self.fixed_size {
Content::SeqFixedSize(self.elements)
} else {
Content::Seq(self.elements)
})
}
}
struct SerializeTuple<E> {
elements: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeTuple for SerializeTuple<E>
where E: ser::Error
{
type Ok = Content;
type Error = 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(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::Tuple(self.elements))
}
}
struct SerializeTupleStruct<E> {
name: &'static str,
fields: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeTupleStruct for SerializeTupleStruct<E>
where E: ser::Error
{
type Ok = Content;
type Error = 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(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::TupleStruct(self.name, self.fields))
}
}
struct SerializeTupleVariant<E> {
name: &'static str,
variant_index: usize,
variant: &'static str,
fields: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeTupleVariant for SerializeTupleVariant<E>
where E: ser::Error
{
type Ok = Content;
type Error = 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(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::TupleVariant(self.name, self.variant_index, self.variant, self.fields))
}
}
struct SerializeMap<E> {
entries: Vec<(Content, Content)>,
key: Option<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeMap for SerializeMap<E>
where E: ser::Error
{
type Ok = Content;
type Error = 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> {
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));
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::Map(self.entries))
}
fn serialize_entry<K: ?Sized + Serialize, V: ?Sized + Serialize>(&mut self,
key: &K,
value: &V)
-> Result<(), E> {
let key = try!(key.serialize(ContentSerializer::<E>::new()));
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.entries.push((key, value));
Ok(())
}
}
struct SerializeStruct<E> {
name: &'static str,
fields: Vec<(&'static str, Content)>,
error: PhantomData<E>,
}
impl<E> ser::SerializeStruct for SerializeStruct<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
key: &'static str,
value: &T)
-> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push((key, value));
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::Struct(self.name, self.fields))
}
}
struct SerializeStructVariant<E> {
name: &'static str,
variant_index: usize,
variant: &'static str,
fields: Vec<(&'static str, Content)>,
error: PhantomData<E>,
}
impl<E> ser::SerializeStructVariant for SerializeStructVariant<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
key: &'static str,
value: &T)
-> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push((key, value));
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::StructVariant(self.name, self.variant_index, self.variant, self.fields))
}
}
+88 -133
View File
@@ -4,28 +4,10 @@ use std::borrow::Cow;
use collections::borrow::Cow;
#[cfg(feature = "std")]
use std::collections::{
BinaryHeap,
BTreeMap,
BTreeSet,
LinkedList,
HashMap,
HashSet,
VecDeque,
};
use std::collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, HashMap, HashSet, VecDeque};
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::{
BinaryHeap,
BTreeMap,
BTreeSet,
LinkedList,
VecDeque,
String,
Vec,
};
use collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque, String, Vec};
#[cfg(feature = "collections")]
use collections::enum_set::{CLike, EnumSet};
#[cfg(feature = "collections")]
use collections::borrow::ToOwned;
@@ -40,6 +22,8 @@ use core::ops;
#[cfg(feature = "std")]
use std::path;
#[cfg(feature = "std")]
use std::ffi::{CString, CStr};
#[cfg(feature = "std")]
use std::rc::Rc;
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::rc::Rc;
@@ -59,18 +43,10 @@ use core::marker::PhantomData;
#[cfg(feature = "unstable")]
use core::nonzero::{NonZero, Zeroable};
use super::{
Serialize,
SerializeSeq,
SerializeTuple,
Serializer,
};
#[cfg(any(feature = "std", feature = "unstable"))]
use super::{Serialize, SerializeSeq, SerializeTuple, Serializer};
#[cfg(feature = "std")]
use super::Error;
#[cfg(feature = "unstable")]
use super::Iterator;
///////////////////////////////////////////////////////////////////////////////
macro_rules! impl_visit {
@@ -106,7 +82,7 @@ impl_visit!(char, serialize_char);
impl Serialize for str {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
serializer.serialize_str(self)
}
@@ -116,7 +92,7 @@ impl Serialize for str {
impl Serialize for String {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
(&self[..]).serialize(serializer)
}
@@ -124,12 +100,34 @@ 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
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
match *self {
Some(ref value) => serializer.serialize_some(value),
@@ -143,30 +141,12 @@ impl<T> Serialize for Option<T>
impl<T> Serialize for PhantomData<T> {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
serializer.serialize_unit_struct("PhantomData")
}
}
///////////////////////////////////////////////////////////////////////////////
impl<T> Serialize for [T]
where T: 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 {
try!(seq.serialize_element(e));
}
seq.end()
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! array_impls {
@@ -222,48 +202,23 @@ array_impls!(32);
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")]
impl<'a, I> Serialize for Iterator<I>
where I: IntoIterator, <I as IntoIterator>::Item: Serialize
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
// FIXME: use specialization to prevent invalidating the object in case of clonable iterators?
let iter = match self.0.borrow_mut().take() {
Some(iter) => iter.into_iter(),
None => return Err(Error::custom("Iterator used twice")),
};
let size = match iter.size_hint() {
(lo, Some(hi)) if lo == hi => Some(lo),
_ => None,
};
let mut seq = try!(serializer.serialize_seq(size));
for e in iter {
try!(seq.serialize_element(&e));
}
seq.end()
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! serialize_seq {
() => {
#[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 {
try!(seq.serialize_element(&e));
}
seq.end()
serializer.collect_seq(self)
}
}
}
impl<T> Serialize for [T]
where T: Serialize
{
serialize_seq!();
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for BinaryHeap<T>
where T: Serialize + Ord
@@ -273,14 +228,7 @@ impl<T> Serialize for BinaryHeap<T>
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for BTreeSet<T>
where T: Serialize + Ord,
{
serialize_seq!();
}
#[cfg(feature = "collections")]
impl<T> Serialize for EnumSet<T>
where T: Serialize + CLike
where T: Serialize + Ord
{
serialize_seq!();
}
@@ -288,14 +236,14 @@ impl<T> Serialize for EnumSet<T>
#[cfg(feature = "std")]
impl<T, H> Serialize for HashSet<T, H>
where T: Serialize + Eq + Hash,
H: BuildHasher,
H: BuildHasher
{
serialize_seq!();
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for LinkedList<T>
where T: Serialize,
where T: Serialize
{
serialize_seq!();
}
@@ -317,11 +265,11 @@ impl<T> Serialize for VecDeque<T>
#[cfg(feature = "unstable")]
impl<A> Serialize for ops::Range<A>
where ops::Range<A>: ExactSizeIterator + iter::Iterator<Item = A> + Clone,
A: Serialize,
A: Serialize
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
let mut seq = try!(serializer.serialize_seq(Some(self.len())));
for e in self.clone() {
@@ -334,11 +282,11 @@ impl<A> Serialize for ops::Range<A>
#[cfg(feature = "unstable")]
impl<A> Serialize for ops::RangeInclusive<A>
where ops::RangeInclusive<A>: ExactSizeIterator + iter::Iterator<Item = A> + Clone,
A: Serialize,
A: Serialize
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
let mut seq = try!(serializer.serialize_seq(Some(self.len())));
for e in self.clone() {
@@ -353,7 +301,7 @@ impl<A> Serialize for ops::RangeInclusive<A>
impl Serialize for () {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
serializer.serialize_unit()
}
@@ -565,13 +513,7 @@ macro_rules! serialize_map {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
use super::SerializeMap;
let mut map = try!(serializer.serialize_map(Some(self.len())));
for (k, v) in self {
try!(map.serialize_key(k));
try!(map.serialize_value(v));
}
map.end()
serializer.collect_map(self)
}
}
}
@@ -579,7 +521,7 @@ macro_rules! serialize_map {
#[cfg(any(feature = "std", feature = "collections"))]
impl<K, V> Serialize for BTreeMap<K, V>
where K: Serialize + Ord,
V: Serialize,
V: Serialize
{
serialize_map!();
}
@@ -588,26 +530,30 @@ impl<K, V> Serialize for BTreeMap<K, V>
impl<K, V, H> Serialize for HashMap<K, V, H>
where K: Serialize + Eq + Hash,
V: Serialize,
H: BuildHasher,
H: BuildHasher
{
serialize_map!();
}
///////////////////////////////////////////////////////////////////////////////
impl<'a, T: ?Sized> Serialize for &'a T where T: Serialize {
impl<'a, T: ?Sized> Serialize for &'a T
where T: Serialize
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
(**self).serialize(serializer)
}
}
impl<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize {
impl<'a, T: ?Sized> Serialize for &'a mut T
where T: Serialize
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
(**self).serialize(serializer)
}
@@ -619,7 +565,7 @@ impl<T: ?Sized> Serialize for Box<T>
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
(**self).serialize(serializer)
}
@@ -631,7 +577,7 @@ impl<T> Serialize for Rc<T>
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
(**self).serialize(serializer)
}
@@ -643,7 +589,7 @@ impl<T> Serialize for Arc<T>
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
(**self).serialize(serializer)
}
@@ -655,7 +601,7 @@ impl<'a, T: ?Sized> Serialize for Cow<'a, T>
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
(**self).serialize(serializer)
}
@@ -671,9 +617,7 @@ impl<T, E> Serialize for Result<T, E>
where S: Serializer
{
match *self {
Result::Ok(ref value) => {
serializer.serialize_newtype_variant("Result", 0, "Ok", value)
}
Result::Ok(ref value) => serializer.serialize_newtype_variant("Result", 0, "Ok", value),
Result::Err(ref value) => {
serializer.serialize_newtype_variant("Result", 1, "Err", value)
}
@@ -686,7 +630,7 @@ impl<T, E> Serialize for Result<T, E>
#[cfg(feature = "std")]
impl Serialize for Duration {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("Duration", 2));
@@ -701,27 +645,34 @@ impl Serialize for Duration {
#[cfg(feature = "std")]
impl Serialize for net::IpAddr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
self.to_string().serialize(serializer)
match *self {
net::IpAddr::V4(ref a) => a.serialize(serializer),
net::IpAddr::V6(ref a) => a.serialize(serializer),
}
}
}
#[cfg(feature = "std")]
impl Serialize for net::Ipv4Addr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
self.to_string().serialize(serializer)
/// "101.102.103.104".len()
const MAX_LEN: usize = 15;
serialize_display_bounded_length!(self, MAX_LEN, serializer)
}
}
#[cfg(feature = "std")]
impl Serialize for net::Ipv6Addr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
self.to_string().serialize(serializer)
/// "1000:1002:1003:1004:1005:1006:1007:1008".len()
const MAX_LEN: usize = 39;
serialize_display_bounded_length!(self, MAX_LEN, serializer)
}
}
@@ -730,7 +681,7 @@ impl Serialize for net::Ipv6Addr {
#[cfg(feature = "std")]
impl Serialize for net::SocketAddr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
match *self {
net::SocketAddr::V4(ref addr) => addr.serialize(serializer),
@@ -742,18 +693,22 @@ impl Serialize for net::SocketAddr {
#[cfg(feature = "std")]
impl Serialize for net::SocketAddrV4 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
self.to_string().serialize(serializer)
/// "101.102.103.104:65000".len()
const MAX_LEN: usize = 21;
serialize_display_bounded_length!(self, MAX_LEN, serializer)
}
}
#[cfg(feature = "std")]
impl Serialize for net::SocketAddrV6 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
self.to_string().serialize(serializer)
/// "[1000:1002:1003:1004:1005:1006:1007:1008]:65000".len()
const MAX_LEN: usize = 47;
serialize_display_bounded_length!(self, MAX_LEN, serializer)
}
}
@@ -762,7 +717,7 @@ impl Serialize for net::SocketAddrV6 {
#[cfg(feature = "std")]
impl Serialize for path::Path {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
match self.to_str() {
Some(s) => s.serialize(serializer),
@@ -774,7 +729,7 @@ impl Serialize for path::Path {
#[cfg(feature = "std")]
impl Serialize for path::PathBuf {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
where S: Serializer
{
self.as_path().serialize(serializer)
}
+156
View File
@@ -0,0 +1,156 @@
//! This module contains `Impossible` serializer and its implementations.
use core::marker::PhantomData;
use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
SerializeTupleVariant, SerializeMap, SerializeStruct, SerializeStructVariant};
/// Helper type for implementing a `Serializer` that does not support
/// serializing one of the compound types.
///
/// This type cannot be instantiated, but implements every one of the traits
/// corresponding to the `Serializer` compound types: `SerializeSeq`,
/// `SerializeTuple`, `SerializeTupleStruct`, `SerializeTupleVariant`,
/// `SerializeMap`, `SerializeStruct`, and `SerializeStructVariant`.
///
/// ```rust,ignore
/// impl Serializer for MySerializer {
/// type Ok = ();
/// type Error = Error;
///
/// type SerializeSeq = Impossible<(), Error>;
/// /* other associated types */
///
/// /// This data format does not support serializing sequences.
/// fn serialize_seq(self,
/// len: Option<usize>)
/// -> Result<Self::SerializeSeq, Error> {
/// // Given Impossible cannot be instantiated, the only
/// // thing we can do here is to return an error.
/// Err(...)
/// }
///
/// /* other Serializer methods */
/// }
/// ```
pub struct Impossible<Ok, E> {
void: Void,
_marker: PhantomData<(Ok, E)>,
}
enum Void {}
impl<Ok, E> SerializeSeq for Impossible<Ok, E>
where E: ser::Error
{
type Ok = Ok;
type Error = E;
fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeTuple for Impossible<Ok, E>
where E: ser::Error
{
type Ok = Ok;
type Error = E;
fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeTupleStruct for Impossible<Ok, E>
where E: ser::Error
{
type Ok = Ok;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeTupleVariant for Impossible<Ok, E>
where E: ser::Error
{
type Ok = Ok;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeMap for Impossible<Ok, E>
where E: ser::Error
{
type Ok = Ok;
type Error = E;
fn serialize_key<T: ?Sized + Serialize>(&mut self, _key: &T) -> Result<(), E> {
match self.void {}
}
fn serialize_value<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeStruct for Impossible<Ok, E>
where E: ser::Error
{
type Ok = Ok;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
_key: &'static str,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeStructVariant for Impossible<Ok, E>
where E: ser::Error
{
type Ok = Ok;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
_key: &'static str,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
+232 -113
View File
@@ -98,12 +98,23 @@ use std::error;
#[cfg(not(feature = "std"))]
use error;
#[cfg(feature = "unstable")]
use core::cell::RefCell;
#[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;
mod impossible;
// Helpers used by generated code. Not public API.
#[doc(hidden)]
pub mod private;
#[cfg(any(feature = "std", feature = "collections"))]
mod content;
pub use self::impossible::Impossible;
///////////////////////////////////////////////////////////////////////////////
@@ -138,8 +149,8 @@ pub trait Error: Sized + error::Error {
///////////////////////////////////////////////////////////////////////////////
/// An implementation of this trait is a **data structure** that can be
/// serialized into any data format supported by Serde.
/// A **data structure** that can be serialized into any data format supported
/// by Serde.
///
/// Serde provides `Serialize` implementations for many Rust primitive and
/// standard library types. The complete list is [here][ser]. All of these can
@@ -169,14 +180,12 @@ pub trait Serialize {
/// for more information about how to implement this method.
///
/// [impl-serialize]: https://serde.rs/impl-serialize.html
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer;
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer;
}
///////////////////////////////////////////////////////////////////////////////
/// An implementation of this trait is a **data format** that can serialize any
/// data structure supported by Serde.
/// A **data format** that can serialize any data structure supported by Serde.
///
/// The role of this trait is to define the serialization half of the Serde data
/// model, which is a way to categorize every Rust data structure into one of 28
@@ -236,7 +245,7 @@ pub trait Serialize {
/// is the `serde_json::value::Serializer` (distinct from the main `serde_json`
/// serializer) that produces a `serde_json::Value` data structure in memory as
/// output.
pub trait Serializer {
pub trait Serializer: Sized {
/// The output type produced by this `Serializer` during successful
/// serialization. Most serializers that produce text or binary output
/// should set `Ok = ()` and serialize into an `io::Write` or buffer
@@ -250,31 +259,31 @@ pub trait Serializer {
/// Type returned from `serialize_seq` and `serialize_seq_fixed_size` for
/// serializing the content of the sequence.
type SerializeSeq: SerializeSeq<Ok=Self::Ok, Error=Self::Error>;
type SerializeSeq: SerializeSeq<Ok = Self::Ok, Error = Self::Error>;
/// Type returned from `serialize_tuple` for serializing the content of the
/// tuple.
type SerializeTuple: SerializeTuple<Ok=Self::Ok, Error=Self::Error>;
type SerializeTuple: SerializeTuple<Ok = Self::Ok, Error = Self::Error>;
/// Type returned from `serialize_tuple_struct` for serializing the content
/// of the tuple struct.
type SerializeTupleStruct: SerializeTupleStruct<Ok=Self::Ok, Error=Self::Error>;
type SerializeTupleStruct: SerializeTupleStruct<Ok = Self::Ok, Error = Self::Error>;
/// Type returned from `serialize_tuple_variant` for serializing the content
/// of the tuple variant.
type SerializeTupleVariant: SerializeTupleVariant<Ok=Self::Ok, Error=Self::Error>;
type SerializeTupleVariant: SerializeTupleVariant<Ok = Self::Ok, Error = Self::Error>;
/// Type returned from `serialize_map` for serializing the content of the
/// map.
type SerializeMap: SerializeMap<Ok=Self::Ok, Error=Self::Error>;
type SerializeMap: SerializeMap<Ok = Self::Ok, Error = Self::Error>;
/// Type returned from `serialize_struct` for serializing the content of the
/// struct.
type SerializeStruct: SerializeStruct<Ok=Self::Ok, Error=Self::Error>;
type SerializeStruct: SerializeStruct<Ok = Self::Ok, Error = Self::Error>;
/// Type returned from `serialize_struct_variant` for serializing the
/// content of the struct variant.
type SerializeStructVariant: SerializeStructVariant<Ok=Self::Ok, Error=Self::Error>;
type SerializeStructVariant: SerializeStructVariant<Ok = Self::Ok, Error = Self::Error>;
/// Serialize a `bool` value.
fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error>;
@@ -367,10 +376,7 @@ pub trait Serializer {
fn serialize_none(self) -> Result<Self::Ok, Self::Error>;
/// Serialize a `Some(T)` value.
fn serialize_some<T: ?Sized + Serialize>(
self,
value: &T,
) -> Result<Self::Ok, Self::Error>;
fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok, Self::Error>;
/// Serialize a `()` value.
fn serialize_unit(self) -> Result<Self::Ok, Self::Error>;
@@ -378,10 +384,7 @@ pub trait Serializer {
/// Serialize a unit struct like `struct Unit` or `PhantomData<T>`.
///
/// A reasonable implementation would be to forward to `serialize_unit`.
fn serialize_unit_struct(
self,
name: &'static str,
) -> Result<Self::Ok, Self::Error>;
fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error>;
/// Serialize a unit variant like `E::A` in `enum E { A, B }`.
///
@@ -397,12 +400,11 @@ pub trait Serializer {
/// E::B => serializer.serialize_unit_variant("E", 1, "B"),
/// }
/// ```
fn serialize_unit_variant(
self,
name: &'static str,
variant_index: usize,
variant: &'static str,
) -> Result<Self::Ok, Self::Error>;
fn serialize_unit_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str)
-> Result<Self::Ok, Self::Error>;
/// Serialize a newtype struct like `struct Millimeters(u8)`.
///
@@ -413,11 +415,10 @@ pub trait Serializer {
/// ```rust,ignore
/// serializer.serialize_newtype_struct("Millimeters", &self.0)
/// ```
fn serialize_newtype_struct<T: ?Sized + Serialize>(
self,
name: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>;
fn serialize_newtype_struct<T: ?Sized + Serialize>(self,
name: &'static str,
value: &T)
-> Result<Self::Ok, Self::Error>;
/// Serialize a newtype variant like `E::N` in `enum E { N(u8) }`.
///
@@ -430,13 +431,12 @@ pub trait Serializer {
/// E::N(ref n) => serializer.serialize_newtype_variant("E", 0, "N", n),
/// }
/// ```
fn serialize_newtype_variant<T: ?Sized + Serialize>(
self,
name: &'static str,
variant_index: usize,
variant: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>;
fn serialize_newtype_variant<T: ?Sized + Serialize>(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
value: &T)
-> Result<Self::Ok, Self::Error>;
/// Begin to serialize a dynamically sized sequence. This call must be
/// followed by zero or more calls to `serialize_element`, then a call to
@@ -453,10 +453,7 @@ pub trait Serializer {
/// }
/// seq.end()
/// ```
fn serialize_seq(
self,
len: Option<usize>,
) -> Result<Self::SerializeSeq, Self::Error>;
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error>;
/// Begin to serialize a statically sized sequence whose length will be
/// known at deserialization time without looking at the serialized data.
@@ -470,25 +467,19 @@ pub trait Serializer {
/// }
/// seq.end()
/// ```
fn serialize_seq_fixed_size(
self,
size: usize,
) -> Result<Self::SerializeSeq, Self::Error>;
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>;
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error>;
/// Begin to serialize a tuple struct like `struct Rgb(u8, u8, u8)`. This
/// call must be followed by zero or more calls to `serialize_field`, then a
@@ -504,11 +495,10 @@ pub trait Serializer {
/// ts.serialize_field(&self.2)?;
/// ts.end()
/// ```
fn serialize_tuple_struct(
self,
name: &'static str,
len: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error>;
fn serialize_tuple_struct(self,
name: &'static str,
len: usize)
-> Result<Self::SerializeTupleStruct, Self::Error>;
/// Begin to serialize a tuple variant like `E::T` in `enum E { T(u8, u8)
/// }`. This call must be followed by zero or more calls to
@@ -528,13 +518,12 @@ pub trait Serializer {
/// }
/// }
/// ```
fn serialize_tuple_variant(
self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error>;
fn serialize_tuple_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize)
-> Result<Self::SerializeTupleVariant, Self::Error>;
/// Begin to serialize a map. This call must be followed by zero or more
/// calls to `serialize_key` and `serialize_value`, then a call to `end`.
@@ -546,15 +535,11 @@ pub trait Serializer {
/// ```rust,ignore
/// let mut map = serializer.serialize_map(Some(self.len()))?;
/// for (k, v) in self {
/// map.serialize_key(k)?;
/// map.serialize_value(v)?;
/// map.serialize_entry(k, v)?;
/// }
/// map.end()
/// ```
fn serialize_map(
self,
len: Option<usize>,
) -> Result<Self::SerializeMap, Self::Error>;
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error>;
/// Begin to serialize a struct like `struct Rgb { r: u8, g: u8, b: u8 }`.
/// This call must be followed by zero or more calls to `serialize_field`,
@@ -570,11 +555,10 @@ pub trait Serializer {
/// struc.serialize_field("b", &self.b)?;
/// struc.end()
/// ```
fn serialize_struct(
self,
name: &'static str,
len: usize,
) -> Result<Self::SerializeStruct, Self::Error>;
fn serialize_struct(self,
name: &'static str,
len: usize)
-> Result<Self::SerializeStruct, Self::Error>;
/// Begin to serialize a struct variant like `E::S` in `enum E { S { r: u8,
/// g: u8, b: u8 } }`. This call must be followed by zero or more calls to
@@ -595,13 +579,111 @@ pub trait Serializer {
/// }
/// }
/// ```
fn serialize_struct_variant(
self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error>;
fn serialize_struct_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize)
-> Result<Self::SerializeStructVariant, Self::Error>;
/// Collect an iterator as a sequence.
///
/// The default implementation serializes each item yielded by the iterator
/// using `Self::SerializeSeq`. Implementors should not need to override
/// this method.
fn collect_seq<I>(self, iter: I) -> Result<Self::Ok, Self::Error>
where I: IntoIterator,
<I as IntoIterator>::Item: Serialize
{
let iter = iter.into_iter();
let mut serializer = try!(self.serialize_seq(iter.len_hint()));
for item in iter {
try!(serializer.serialize_element(&item));
}
serializer.end()
}
/// Collect an iterator as a map.
///
/// The default implementation serializes each pair yielded by the iterator
/// using `Self::SerializeMap`. Implementors should not need to override
/// this method.
fn collect_map<K, V, I>(self, iter: I) -> Result<Self::Ok, Self::Error>
where K: Serialize,
V: Serialize,
I: IntoIterator<Item = (K, V)>
{
let iter = iter.into_iter();
let mut serializer = try!(self.serialize_map(iter.len_hint()));
for (key, value) in iter {
try!(serializer.serialize_entry(&key, &value));
}
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
@@ -632,9 +714,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 {
@@ -705,8 +787,7 @@ pub trait SerializeTupleVariant {
/// ```rust,ignore
/// let mut map = serializer.serialize_map(Some(self.len()))?;
/// for (k, v) in self {
/// map.serialize_key(k)?;
/// map.serialize_value(v)?;
/// map.serialize_entry(k, v)?;
/// }
/// map.end()
/// ```
@@ -723,6 +804,27 @@ pub trait SerializeMap {
/// Serialize a map value.
fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error>;
/// Serialize a map entry consisting of a key and a value.
///
/// Some `Serialize` types are not able to hold a key and value in memory at
/// the same time so `SerializeMap` implementations are required to support
/// `serialize_key` and `serialize_value` individually. The
/// `serialize_entry` method allows serializers to optimize for the case
/// where key and value are both available. `Serialize` implementations are
/// encouraged to use `serialize_entry` if possible.
///
/// The default implementation delegates to `serialize_key` and
/// `serialize_value`. This is appropriate for serializers that do not care
/// about performance or are not able to optimize `serialize_entry` any
/// better than this.
fn serialize_entry<K: ?Sized + Serialize, V: ?Sized + Serialize>(&mut self,
key: &K,
value: &V)
-> Result<(), Self::Error> {
try!(self.serialize_key(key));
self.serialize_value(value)
}
/// Finish serializing a map.
fn end(self) -> Result<Self::Ok, Self::Error>;
}
@@ -744,7 +846,10 @@ pub trait SerializeStruct {
type Error: Error;
/// Serialize a struct field.
fn serialize_field<T: ?Sized + Serialize>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
key: &'static str,
value: &T)
-> Result<(), Self::Error>;
/// Finish serializing a struct.
fn end(self) -> Result<Self::Ok, Self::Error>;
@@ -771,27 +876,41 @@ pub trait SerializeStructVariant {
type Error: Error;
/// Serialize a struct variant field.
fn serialize_field<T: ?Sized + Serialize>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
key: &'static str,
value: &T)
-> Result<(), Self::Error>;
/// Finish serializing a struct variant.
fn end(self) -> Result<Self::Ok, Self::Error>;
}
/// A wrapper type for iterators that implements `Serialize` for iterators whose
/// items implement `Serialize`. Don't use multiple times. Create new versions
/// of this with the `serde::ser::iterator` function every time you want to
/// serialize an iterator.
#[cfg(feature = "unstable")]
pub struct Iterator<I>(RefCell<Option<I>>)
where <I as IntoIterator>::Item: Serialize,
I: IntoIterator;
/// Create a wrapper type that can be passed to any function expecting a
/// `Serialize` and will serialize the given iterator as a sequence.
#[cfg(feature = "unstable")]
pub fn iterator<I>(iter: I) -> Iterator<I>
where <I as IntoIterator>::Item: Serialize,
I: IntoIterator
{
Iterator(RefCell::new(Some(iter)))
trait LenHint: Iterator {
fn len_hint(&self) -> Option<usize>;
}
impl<I: Iterator> LenHint for I {
#[cfg(not(feature = "unstable"))]
fn len_hint(&self) -> Option<usize> {
iterator_len_hint(self)
}
#[cfg(feature = "unstable")]
default fn len_hint(&self) -> Option<usize> {
iterator_len_hint(self)
}
}
#[cfg(feature = "unstable")]
impl<I: ExactSizeIterator> LenHint for I {
fn len_hint(&self) -> Option<usize> {
Some(self.len())
}
}
fn iterator_len_hint<I: Iterator>(iter: &I) -> Option<usize> {
match iter.size_hint() {
(lo, Some(hi)) if lo == hi => Some(lo),
_ => None,
}
}
+313
View File
@@ -0,0 +1,313 @@
use core::fmt::{self, Display};
use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct, Impossible};
#[cfg(any(feature = "std", feature = "collections"))]
use ser::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMapValue};
/// Not public API.
pub fn serialize_tagged_newtype<S, T>(serializer: S,
type_ident: &'static str,
variant_ident: &'static str,
tag: &'static str,
variant_name: &'static str,
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,
})
}
struct TaggedSerializer<S> {
type_ident: &'static str,
variant_ident: &'static str,
tag: &'static str,
variant_name: &'static str,
delegate: S,
}
enum Unsupported {
Boolean,
Integer,
Float,
Char,
String,
ByteArray,
Optional,
Unit,
UnitStruct,
Sequence,
Tuple,
TupleStruct,
#[cfg(not(any(feature = "std", feature = "collections")))]
Enum,
}
impl Display for Unsupported {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match *self {
Unsupported::Boolean => formatter.write_str("a boolean"),
Unsupported::Integer => formatter.write_str("an integer"),
Unsupported::Float => formatter.write_str("a float"),
Unsupported::Char => formatter.write_str("a char"),
Unsupported::String => formatter.write_str("a string"),
Unsupported::ByteArray => formatter.write_str("a byte array"),
Unsupported::Optional => formatter.write_str("an optional"),
Unsupported::Unit => formatter.write_str("unit"),
Unsupported::UnitStruct => formatter.write_str("a unit struct"),
Unsupported::Sequence => formatter.write_str("a sequence"),
Unsupported::Tuple => formatter.write_str("a tuple"),
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
#[cfg(not(any(feature = "std", feature = "collections")))]
Unsupported::Enum => formatter.write_str("an enum"),
}
}
}
struct Error {
type_ident: &'static str,
variant_ident: &'static str,
ty: Unsupported,
}
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)
}
}
impl<S> TaggedSerializer<S>
where S: Serializer
{
fn bad_type(self, what: Unsupported) -> S::Error {
ser::Error::custom(Error {
type_ident: self.type_ident,
variant_ident: self.variant_ident,
ty: what,
})
}
}
impl<S> Serializer for TaggedSerializer<S>
where S: Serializer
{
type Ok = S::Ok;
type Error = S::Error;
type SerializeSeq = Impossible<S::Ok, S::Error>;
type SerializeTuple = Impossible<S::Ok, S::Error>;
type SerializeTupleStruct = Impossible<S::Ok, S::Error>;
type SerializeMap = S::SerializeMap;
type SerializeStruct = S::SerializeStruct;
#[cfg(not(any(feature = "std", feature = "collections")))]
type SerializeTupleVariant = Impossible<S::Ok, S::Error>;
#[cfg(any(feature = "std", feature = "collections"))]
type SerializeTupleVariant = SerializeTupleVariantAsMapValue<S::SerializeMap>;
#[cfg(not(any(feature = "std", feature = "collections")))]
type SerializeStructVariant = Impossible<S::Ok, S::Error>;
#[cfg(any(feature = "std", feature = "collections"))]
type SerializeStructVariant = SerializeStructVariantAsMapValue<S::SerializeMap>;
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Boolean))
}
fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
}
fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
}
fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Char))
}
fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::String))
}
fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::ByteArray))
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Optional))
}
fn serialize_some<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
where T: Serialize
{
Err(self.bad_type(Unsupported::Optional))
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Unit))
}
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::UnitStruct))
}
fn serialize_unit_variant(self,
_: &'static str,
_: usize,
inner_variant: &'static str)
-> Result<Self::Ok, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_entry(inner_variant, &()));
map.end()
}
fn serialize_newtype_struct<T: ?Sized>(self,
_: &'static str,
value: &T)
-> Result<Self::Ok, Self::Error>
where T: Serialize
{
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(self,
_: &'static str,
_: usize,
inner_variant: &'static str,
inner_value: &T)
-> Result<Self::Ok, Self::Error>
where T: Serialize
{
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_entry(inner_variant, inner_value));
map.end()
}
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Err(self.bad_type(Unsupported::Sequence))
}
fn serialize_seq_fixed_size(self, _: usize) -> Result<Self::SerializeSeq, Self::Error> {
Err(self.bad_type(Unsupported::Sequence))
}
fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
Err(self.bad_type(Unsupported::Tuple))
}
fn serialize_tuple_struct(self,
_: &'static str,
_: usize)
-> Result<Self::SerializeTupleStruct, Self::Error> {
Err(self.bad_type(Unsupported::TupleStruct))
}
#[cfg(not(any(feature = "std", feature = "collections")))]
fn serialize_tuple_variant(self,
_: &'static str,
_: usize,
_: &'static str,
_: usize)
-> Result<Self::SerializeTupleVariant, Self::Error> {
// Lack of push-based serialization means we need to buffer the content
// of the tuple variant, so it requires std.
Err(self.bad_type(Unsupported::Enum))
}
#[cfg(any(feature = "std", feature = "collections"))]
fn serialize_tuple_variant(self,
_: &'static str,
_: usize,
inner_variant: &'static str,
len: usize)
-> Result<Self::SerializeTupleVariant, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_key(inner_variant));
Ok(SerializeTupleVariantAsMapValue::new(map, inner_variant, len))
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
let mut map = try!(self.delegate.serialize_map(len.map(|len| len + 1)));
try!(map.serialize_entry(self.tag, self.variant_name));
Ok(map)
}
fn serialize_struct(self,
name: &'static str,
len: usize)
-> Result<Self::SerializeStruct, Self::Error> {
let mut state = try!(self.delegate.serialize_struct(name, len + 1));
try!(state.serialize_field(self.tag, self.variant_name));
Ok(state)
}
#[cfg(not(any(feature = "std", feature = "collections")))]
fn serialize_struct_variant(self,
_: &'static str,
_: usize,
_: &'static str,
_: usize)
-> Result<Self::SerializeStructVariant, Self::Error> {
// Lack of push-based serialization means we need to buffer the content
// of the struct variant, so it requires std.
Err(self.bad_type(Unsupported::Enum))
}
#[cfg(any(feature = "std", feature = "collections"))]
fn serialize_struct_variant(self,
_: &'static str,
_: usize,
inner_variant: &'static str,
len: usize)
-> Result<Self::SerializeStructVariant, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_key(inner_variant));
Ok(SerializeStructVariantAsMapValue::new(map, inner_variant, len))
}
}
+20 -18
View File
@@ -1,12 +1,12 @@
//! Private utility functions
const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
const TAG_THREE_B: u8 = 0b1110_0000;
const TAG_FOUR_B: u8 = 0b1111_0000;
const MAX_ONE_B: u32 = 0x80;
const MAX_TWO_B: u32 = 0x800;
const MAX_THREE_B: u32 = 0x10000;
const TAG_FOUR_B: u8 = 0b1111_0000;
const MAX_ONE_B: u32 = 0x80;
const MAX_TWO_B: u32 = 0x800;
const MAX_THREE_B: u32 = 0x10000;
#[inline]
pub fn encode_utf8(c: char) -> EncodeUtf8 {
@@ -21,17 +21,20 @@ pub fn encode_utf8(c: char) -> EncodeUtf8 {
2
} else if code < MAX_THREE_B {
buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
1
} else {
buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
0
};
EncodeUtf8 { buf: buf, pos: pos }
EncodeUtf8 {
buf: buf,
pos: pos,
}
}
pub struct EncodeUtf8 {
@@ -47,23 +50,22 @@ impl EncodeUtf8 {
}
#[allow(non_upper_case_globals)]
const Pattern_White_Space_table: &'static [(char, char)] = &[
('\u{9}', '\u{d}'), ('\u{20}', '\u{20}'), ('\u{85}', '\u{85}'), ('\u{200e}', '\u{200f}'),
('\u{2028}', '\u{2029}')
];
const Pattern_White_Space_table: &'static [(char, char)] = &[('\u{9}', '\u{d}'),
('\u{20}', '\u{20}'),
('\u{85}', '\u{85}'),
('\u{200e}', '\u{200f}'),
('\u{2028}', '\u{2029}')];
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 {
r.binary_search_by(|&(lo, hi)| if c < lo {
Greater
} else if hi < c {
Less
} else {
Equal
}
})
.is_ok()
})
.is_ok()
}
#[allow(non_snake_case)]
-32
View File
@@ -1,32 +0,0 @@
[package]
name = "serde_codegen"
version = "0.9.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde.rs/codegen.html"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[features]
default = ["with-syntex"]
unstable = []
unstable-testing = ["clippy"]
with-syntex = [
"syntex",
"syntex_syntax",
]
with-syn = []
[dependencies]
clippy = { version = "0.*", optional = true }
quote = "0.3.8"
serde_codegen_internals = { version = "=0.11.3", default-features = false, path = "../serde_codegen_internals" }
syn = { version = "0.10", features = ["aster", "visit"] }
syntex = { version = "0.54", optional = true }
syntex_syntax = { version = "0.54", optional = true }
[badges]
travis-ci = { repository = "serde-rs/serde" }
-121
View File
@@ -1,121 +0,0 @@
use std::collections::HashSet;
use syn::{self, aster, visit};
use internals::ast::Item;
use internals::attr;
// Remove the default from every type parameter because in the generated impls
// they look like associated types: "error: associated type bindings are not
// allowed here".
pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
syn::Generics {
ty_params: generics.ty_params.iter().map(|ty_param| {
syn::TyParam {
default: None,
.. ty_param.clone()
}}).collect(),
.. generics.clone()
}
}
pub fn with_where_predicates(
generics: &syn::Generics,
predicates: &[syn::WherePredicate],
) -> syn::Generics {
aster::from_generics(generics.clone())
.with_predicates(predicates.to_vec())
.build()
}
pub fn with_where_predicates_from_fields<F>(
item: &Item,
generics: &syn::Generics,
from_field: F,
) -> syn::Generics
where F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
{
aster::from_generics(generics.clone())
.with_predicates(
item.body.all_fields()
.flat_map(|field| from_field(&field.attrs))
.flat_map(|predicates| predicates.to_vec()))
.build()
}
// Puts the given bound on any generic type parameters that are used in fields
// for which filter returns true.
//
// For example, the following struct needs the bound `A: Serialize, B: Serialize`.
//
// struct S<'b, A, B: 'b, C> {
// a: A,
// b: Option<&'b B>
// #[serde(skip_serializing)]
// c: C,
// }
pub fn with_bound<F>(
item: &Item,
generics: &syn::Generics,
filter: F,
bound: &syn::Path,
) -> syn::Generics
where F: Fn(&attr::Field) -> bool,
{
struct FindTyParams {
// Set of all generic type parameters on the current struct (A, B, C in
// the example). Initialized up front.
all_ty_params: HashSet<syn::Ident>,
// Set of generic type parameters used in fields for which filter
// returns true (A and B in the example). Filled in as the visitor sees
// them.
relevant_ty_params: HashSet<syn::Ident>,
}
impl visit::Visitor for FindTyParams {
fn visit_path(&mut self, path: &syn::Path) {
if let Some(seg) = path.segments.last() {
if seg.ident == "PhantomData" {
// Hardcoded exception, because PhantomData<T> implements
// Serialize and Deserialize whether or not T implements it.
return;
}
}
if !path.global && path.segments.len() == 1 {
let id = path.segments[0].ident.clone();
if self.all_ty_params.contains(&id) {
self.relevant_ty_params.insert(id);
}
}
visit::walk_path(self, path);
}
}
let all_ty_params: HashSet<_> = generics.ty_params.iter()
.map(|ty_param| ty_param.ident.clone())
.collect();
let relevant_tys = item.body.all_fields()
.filter(|&field| filter(&field.attrs))
.map(|field| &field.ty);
let mut visitor = FindTyParams {
all_ty_params: all_ty_params,
relevant_ty_params: HashSet::new(),
};
for ty in relevant_tys {
visit::walk_ty(&mut visitor, ty);
}
aster::from_generics(generics.clone())
.with_predicates(
generics.ty_params.iter()
.map(|ty_param| ty_param.ident.clone())
.filter(|id| visitor.relevant_ty_params.contains(id))
.map(|id| aster::where_predicate()
// the type parameter that is being bounded e.g. T
.bound().build(aster::ty().id(id))
// the bound e.g. Serialize
.bound().trait_(bound.clone()).build()
.build()))
.build()
}
File diff suppressed because it is too large Load Diff
-171
View File
@@ -1,171 +0,0 @@
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "clippy", allow(used_underscore_binding))]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "192"]
extern crate serde_codegen_internals as internals;
#[cfg(feature = "with-syntex")]
extern crate syntex;
#[cfg(feature = "with-syntex")]
extern crate syntex_syntax as syntax;
extern crate syn;
#[macro_use]
extern crate quote;
#[cfg(feature = "with-syntex")]
use std::path::Path;
mod bound;
mod de;
mod ser;
#[cfg(feature = "with-syntex")]
fn syntex_registry() -> syntex::Registry {
use syntax::{ast, fold};
/// Strip the serde attributes from the crate.
#[cfg(feature = "with-syntex")]
fn strip_attributes(krate: ast::Crate) -> ast::Crate {
/// Helper folder that strips the serde attributes after the extensions have been expanded.
struct StripAttributeFolder;
impl fold::Folder for StripAttributeFolder {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
if attr.value.name == "serde" {
if let ast::MetaItemKind::List(..) = attr.value.node {
return None;
}
}
Some(attr)
}
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
fold::noop_fold_mac(mac, self)
}
}
fold::Folder::fold_crate(&mut StripAttributeFolder, krate)
}
let mut reg = syntex::Registry::new();
reg.add_attr("feature(custom_derive)");
reg.add_attr("feature(custom_attribute)");
reg.add_decorator("derive_Serialize", shim::expand_derive_serialize);
reg.add_decorator("derive_Deserialize", shim::expand_derive_deserialize);
reg.add_post_expansion_pass(strip_attributes);
reg
}
#[cfg(feature = "with-syntex")]
pub fn expand_str(src: &str) -> Result<String, syntex::Error> {
let src = src.to_owned();
let expand_thread = move || {
syntex_registry().expand_str("", "", &src)
};
syntex::with_extra_stack(expand_thread)
}
#[cfg(feature = "with-syntex")]
pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
where S: AsRef<Path>,
D: AsRef<Path>,
{
let src = src.as_ref().to_owned();
let dst = dst.as_ref().to_owned();
let expand_thread = move || {
syntex_registry().expand("", src, dst)
};
syntex::with_extra_stack(expand_thread)
}
macro_rules! shim {
($name:ident $pkg:ident :: $func:ident) => {
pub fn $func(
cx: &mut ::syntax::ext::base::ExtCtxt,
span: ::syntax::codemap::Span,
meta_item: &::syntax::ast::MetaItem,
annotatable: &::syntax::ext::base::Annotatable,
push: &mut FnMut(::syntax::ext::base::Annotatable)
) {
let item = match *annotatable {
::syntax::ext::base::Annotatable::Item(ref item) => item,
_ => {
cx.span_err(
meta_item.span,
concat!("`#[derive(",
stringify!($name),
")]` may only be applied to structs and enums"));
return;
}
};
use syntax::{attr, ast, visit};
struct MarkSerdeAttributesUsed;
impl<'a> visit::Visitor<'a> for MarkSerdeAttributesUsed {
fn visit_attribute(&mut self, attr: &ast::Attribute) {
if attr.value.name == "serde" {
if let ast::MetaItemKind::List(..) = attr.value.node {
attr::mark_used(attr);
}
}
}
}
visit::walk_item(&mut MarkSerdeAttributesUsed, item);
use syntax::print::pprust;
let s = pprust::item_to_string(item);
use {syn, $pkg};
let syn_item = syn::parse_macro_input(&s).unwrap();
let expanded = match $pkg::$func(&syn_item) {
Ok(expanded) => expanded.to_string(),
Err(msg) => {
cx.span_err(span, &msg);
return;
}
};
use syntax::parse;
let name = stringify!($name).to_string();
let sess = cx.parse_sess;
let impl_item = parse::parse_item_from_source_str(name, expanded, sess);
push(::syntax::ext::base::Annotatable::Item(impl_item.unwrap().unwrap()));
}
};
}
#[cfg(feature = "with-syntex")]
mod shim {
shim!(Serialize ser::expand_derive_serialize);
shim!(Deserialize de::expand_derive_deserialize);
}
#[cfg(feature = "with-syn")]
#[doc(hidden)]
/// Not public API. Use the serde_derive crate.
pub fn expand_derive_serialize(item: &str) -> Result<quote::Tokens, String> {
let syn_item = syn::parse_macro_input(item).unwrap();
ser::expand_derive_serialize(&syn_item)
}
#[cfg(feature = "with-syn")]
#[doc(hidden)]
/// Not public API. Use the serde_derive crate.
pub fn expand_derive_deserialize(item: &str) -> Result<quote::Tokens, String> {
let syn_item = syn::parse_macro_input(item).unwrap();
de::expand_derive_deserialize(&syn_item)
}
-570
View File
@@ -1,570 +0,0 @@
use syn::{self, aster, Ident};
use quote::Tokens;
use bound;
use internals::ast::{Body, Field, Item, Style, Variant};
use internals::{self, attr};
pub fn expand_derive_serialize(item: &syn::MacroInput) -> Result<Tokens, String> {
let ctxt = internals::Ctxt::new();
let item = Item::from_ast(&ctxt, item);
try!(ctxt.check());
let impl_generics = build_impl_generics(&item);
let ty = aster::ty().path()
.segment(item.ident.clone()).with_generics(impl_generics.clone()).build()
.build();
let body = serialize_body(&item,
&impl_generics,
ty.clone());
let where_clause = &impl_generics.where_clause;
let dummy_const = Ident::new(format!("_IMPL_SERIALIZE_FOR_{}", item.ident));
Ok(quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
extern crate serde as _serde;
#[automatically_derived]
impl #impl_generics _serde::Serialize for #ty #where_clause {
fn serialize<__S>(&self, _serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
{
#body
}
}
};
})
}
// All the generics in the input, plus a bound `T: Serialize` for each generic
// field type that will be serialized by us.
fn build_impl_generics(item: &Item) -> syn::Generics {
let generics = bound::without_defaults(item.generics);
let generics = bound::with_where_predicates_from_fields(
item, &generics,
|attrs| attrs.ser_bound());
match item.attrs.ser_bound() {
Some(predicates) => {
bound::with_where_predicates(&generics, predicates)
}
None => {
bound::with_bound(item, &generics,
needs_serialize_bound,
&aster::path().ids(&["_serde", "Serialize"]).build())
}
}
}
// Fields with a `skip_serializing` or `serialize_with` attribute are not
// serialized by us so we do not generate a bound. Fields with a `bound`
// attribute specify their own bound so we do not generate one. All other fields
// may need a `T: Serialize` bound where T is the type of the field.
fn needs_serialize_bound(attrs: &attr::Field) -> bool {
!attrs.skip_serializing()
&& attrs.serialize_with().is_none()
&& attrs.ser_bound().is_none()
}
fn serialize_body(
item: &Item,
impl_generics: &syn::Generics,
ty: syn::Ty,
) -> Tokens {
match item.body {
Body::Enum(ref variants) => {
serialize_item_enum(
&item.ident,
impl_generics,
ty,
variants,
&item.attrs)
}
Body::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) {
panic!("struct has unnamed fields");
}
serialize_struct(
impl_generics,
ty,
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(
impl_generics,
ty,
fields,
&item.attrs)
}
Body::Struct(Style::Newtype, ref fields) => {
serialize_newtype_struct(
impl_generics,
ty,
&fields[0],
&item.attrs)
}
Body::Struct(Style::Unit, _) => {
serialize_unit_struct(
&item.attrs)
}
}
}
fn serialize_unit_struct(item_attrs: &attr::Item) -> Tokens {
let type_name = item_attrs.name().serialize_name();
quote! {
_serializer.serialize_unit_struct(#type_name)
}
}
fn serialize_newtype_struct(
impl_generics: &syn::Generics,
item_ty: syn::Ty,
field: &Field,
item_attrs: &attr::Item,
) -> Tokens {
let type_name = item_attrs.name().serialize_name();
let mut field_expr = quote!(&self.0);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(
&item_ty, impl_generics, field.ty, path, field_expr);
}
quote! {
_serializer.serialize_newtype_struct(#type_name, #field_expr)
}
}
fn serialize_tuple_struct(
impl_generics: &syn::Generics,
ty: syn::Ty,
fields: &[Field],
item_attrs: &attr::Item,
) -> Tokens {
let serialize_stmts = serialize_tuple_struct_visitor(
ty.clone(),
fields,
impl_generics,
false,
quote!(_serde::ser::SerializeTupleStruct::serialize_field),
);
let type_name = item_attrs.name().serialize_name();
let len = serialize_stmts.len();
let let_mut = mut_if(len > 0);
quote! {
let #let_mut __serde_state = try!(_serializer.serialize_tuple_struct(#type_name, #len));
#(#serialize_stmts)*
_serde::ser::SerializeTupleStruct::end(__serde_state)
}
}
fn serialize_struct(
impl_generics: &syn::Generics,
ty: syn::Ty,
fields: &[Field],
item_attrs: &attr::Item,
) -> Tokens {
let serialize_fields = serialize_struct_visitor(
ty.clone(),
fields,
impl_generics,
false,
quote!(_serde::ser::SerializeStruct::serialize_field),
);
let type_name = item_attrs.name().serialize_name();
let mut serialized_fields = fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields
.map(|field| {
let ident = field.ident.clone().expect("struct has unnamed fields");
let field_expr = quote!(&self.#ident);
match field.attrs.skip_serializing_if() {
Some(path) => quote!(if #path(#field_expr) { 0 } else { 1 }),
None => quote!(1),
}
})
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote! {
let #let_mut __serde_state = try!(_serializer.serialize_struct(#type_name, #len));
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
}
fn serialize_item_enum(
type_ident: &syn::Ident,
impl_generics: &syn::Generics,
ty: syn::Ty,
variants: &[Variant],
item_attrs: &attr::Item,
) -> Tokens {
let arms: Vec<_> =
variants.iter()
.enumerate()
.map(|(variant_index, variant)| {
serialize_variant(
type_ident,
impl_generics,
ty.clone(),
variant,
variant_index,
item_attrs,
)
})
.collect();
quote! {
match *self {
#(#arms)*
}
}
}
fn serialize_variant(
type_ident: &syn::Ident,
generics: &syn::Generics,
ty: syn::Ty,
variant: &Variant,
variant_index: usize,
item_attrs: &attr::Item,
) -> Tokens {
let type_name = item_attrs.name().serialize_name();
let variant_ident = variant.ident.clone();
let variant_name = variant.attrs.name().serialize_name();
if variant.attrs.skip_serializing() {
let skipped_msg = format!("the enum variant {}::{} cannot be serialized",
type_ident, variant_ident);
let skipped_err = quote! {
Err(_serde::ser::Error::custom(#skipped_msg))
};
let fields_pat = match variant.style {
Style::Unit => quote!(),
Style::Newtype | Style::Tuple => quote!( (..) ),
Style::Struct => quote!( {..} ),
};
quote! {
#type_ident::#variant_ident #fields_pat => #skipped_err,
}
} else { // variant wasn't skipped
match variant.style {
Style::Unit => {
quote! {
#type_ident::#variant_ident =>
_serde::Serializer::serialize_unit_variant(
_serializer,
#type_name,
#variant_index,
#variant_name,
),
}
},
Style::Newtype => {
let block = serialize_newtype_variant(
type_name,
variant_index,
variant_name,
ty,
generics,
&variant.fields[0],
);
quote! {
#type_ident::#variant_ident(ref __simple_value) => #block,
}
},
Style::Tuple => {
let field_names = (0 .. variant.fields.len())
.map(|i| Ident::new(format!("__field{}", i)));
let block = serialize_tuple_variant(
type_name,
variant_index,
variant_name,
generics,
ty,
&variant.fields,
);
quote! {
#type_ident::#variant_ident(#(ref #field_names),*) => { #block }
}
}
Style::Struct => {
let fields = variant.fields.iter()
.map(|f| f.ident.clone().expect("struct variant has unnamed fields"));
let block = serialize_struct_variant(
variant_index,
variant_name,
generics,
ty,
&variant.fields,
item_attrs,
);
quote! {
#type_ident::#variant_ident { #(ref #fields),* } => { #block }
}
}
}
}
}
fn serialize_newtype_variant(
type_name: String,
variant_index: usize,
variant_name: String,
item_ty: syn::Ty,
generics: &syn::Generics,
field: &Field,
) -> Tokens {
let mut field_expr = quote!(__simple_value);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(
&item_ty, generics, field.ty, path, field_expr);
}
quote! {
_serde::Serializer::serialize_newtype_variant(
_serializer,
#type_name,
#variant_index,
#variant_name,
#field_expr,
)
}
}
fn serialize_tuple_variant(
type_name: String,
variant_index: usize,
variant_name: String,
generics: &syn::Generics,
structure_ty: syn::Ty,
fields: &[Field],
) -> Tokens {
let serialize_stmts = serialize_tuple_struct_visitor(
structure_ty,
fields,
generics,
true,
quote!(_serde::ser::SerializeTupleVariant::serialize_field),
);
let len = serialize_stmts.len();
let let_mut = mut_if(len > 0);
quote! {
let #let_mut __serde_state = try!(_serializer.serialize_tuple_variant(
#type_name,
#variant_index,
#variant_name,
#len));
#(#serialize_stmts)*
_serde::ser::SerializeTupleVariant::end(__serde_state)
}
}
fn serialize_struct_variant(
variant_index: usize,
variant_name: String,
generics: &syn::Generics,
ty: syn::Ty,
fields: &[Field],
item_attrs: &attr::Item,
) -> Tokens {
let serialize_fields = serialize_struct_visitor(
ty.clone(),
fields,
generics,
true,
quote!(_serde::ser::SerializeStructVariant::serialize_field),
);
let item_name = item_attrs.name().serialize_name();
let mut serialized_fields = fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields
.map(|field| {
let ident = field.ident.clone().expect("struct has unnamed fields");
match field.attrs.skip_serializing_if() {
Some(path) => quote!(if #path(#ident) { 0 } else { 1 }),
None => quote!(1),
}
})
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote! {
let #let_mut __serde_state = try!(_serializer.serialize_struct_variant(
#item_name,
#variant_index,
#variant_name,
#len,
));
#(#serialize_fields)*
_serde::ser::SerializeStructVariant::end(__serde_state)
}
}
fn serialize_tuple_struct_visitor(
structure_ty: syn::Ty,
fields: &[Field],
generics: &syn::Generics,
is_enum: bool,
func: Tokens,
) -> Vec<Tokens> {
fields.iter()
.enumerate()
.map(|(i, field)| {
let mut field_expr = if is_enum {
let id = Ident::new(format!("__field{}", i));
quote!(#id)
} else {
let i = Ident::new(i);
quote!(&self.#i)
};
let skip = field.attrs.skip_serializing_if()
.map(|path| quote!(#path(#field_expr)));
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(
&structure_ty, generics, field.ty, path, field_expr);
}
let ser = quote! {
try!(#func(&mut __serde_state, #field_expr));
};
match skip {
None => ser,
Some(skip) => quote!(if !#skip { #ser }),
}
})
.collect()
}
fn serialize_struct_visitor(
structure_ty: syn::Ty,
fields: &[Field],
generics: &syn::Generics,
is_enum: bool,
func: Tokens,
) -> Vec<Tokens> {
fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.map(|field| {
let ident = field.ident.clone().expect("struct has unnamed field");
let mut field_expr = if is_enum {
quote!(#ident)
} else {
quote!(&self.#ident)
};
let key_expr = field.attrs.name().serialize_name();
let skip = field.attrs.skip_serializing_if()
.map(|path| quote!(#path(#field_expr)));
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(
&structure_ty, generics, field.ty, path, field_expr)
}
let ser = quote! {
try!(#func(&mut __serde_state, #key_expr, #field_expr));
};
match skip {
None => ser,
Some(skip) => quote!(if !#skip { #ser }),
}
})
.collect()
}
fn wrap_serialize_with(
item_ty: &syn::Ty,
generics: &syn::Generics,
field_ty: &syn::Ty,
path: &syn::Path,
value: Tokens,
) -> Tokens {
let where_clause = &generics.where_clause;
let wrapper_generics = aster::from_generics(generics.clone())
.add_lifetime_bound("'__a")
.lifetime_name("'__a")
.build();
let wrapper_ty = aster::path()
.segment("__SerializeWith")
.with_generics(wrapper_generics.clone())
.build()
.build();
quote!({
struct __SerializeWith #wrapper_generics #where_clause {
value: &'__a #field_ty,
phantom: ::std::marker::PhantomData<#item_ty>,
}
impl #wrapper_generics _serde::Serialize for #wrapper_ty #where_clause {
fn serialize<__S>(&self, __s: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
{
#path(self.value, __s)
}
}
&__SerializeWith {
value: #value,
phantom: ::std::marker::PhantomData::<#item_ty>,
}
})
}
// Serialization of an empty struct results in code like:
//
// let mut __serde_state = try!(serializer.serialize_struct("S", 0));
// _serde::ser::SerializeStruct::end(__serde_state)
//
// where we want to omit the `mut` to avoid a warning.
fn mut_if(is_mut: bool) -> Option<Tokens> {
if is_mut {
Some(quote!(mut))
} else {
None
}
}
+4 -7
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_codegen_internals"
version = "0.11.3"
version = "0.14.1"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "AST representation used by Serde codegen. Unstable."
@@ -8,14 +8,11 @@ homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_codegen_internals/"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[features]
unstable-testing = ["clippy"]
readme = "../README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[dependencies]
clippy = { version = "0.*", optional = true }
syn = "0.10"
syn = { version = "0.11", default-features = false, features = ["parsing"] }
[badges]
travis-ci = { repository = "serde-rs/serde" }
+1
View File
@@ -0,0 +1 @@
../LICENSE-APACHE
+1
View File
@@ -0,0 +1 @@
../LICENSE-MIT
+1
View File
@@ -0,0 +1 @@
../README.md
+24 -18
View File
@@ -38,16 +38,30 @@ 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 {
syn::Body::Enum(ref variants) => {
Body::Enum(enum_from_ast(cx, variants))
}
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);
Body::Struct(style, fields)
}
};
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,
@@ -58,15 +72,13 @@ impl<'a> Item<'a> {
}
impl<'a> Body<'a> {
pub fn all_fields(&'a self) -> Box<Iterator<Item=&'a Field<'a>> + 'a> {
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
match *self {
Body::Enum(ref variants) => {
Box::new(variants.iter()
.flat_map(|variant| variant.fields.iter()))
}
Body::Struct(_, ref fields) => {
Box::new(fields.iter())
.flat_map(|variant| variant.fields.iter()))
}
Body::Struct(_, ref fields) => Box::new(fields.iter()),
}
}
}
@@ -87,18 +99,12 @@ fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>
fn struct_from_ast<'a>(cx: &Ctxt, data: &'a syn::VariantData) -> (Style, Vec<Field<'a>>) {
match *data {
syn::VariantData::Struct(ref fields) => {
(Style::Struct, fields_from_ast(cx, fields))
}
syn::VariantData::Struct(ref fields) => (Style::Struct, fields_from_ast(cx, fields)),
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
(Style::Newtype, fields_from_ast(cx, fields))
}
syn::VariantData::Tuple(ref fields) => {
(Style::Tuple, fields_from_ast(cx, fields))
}
syn::VariantData::Unit => {
(Style::Unit, Vec::new())
}
syn::VariantData::Tuple(ref fields) => (Style::Tuple, fields_from_ast(cx, fields)),
syn::VariantData::Unit => (Style::Unit, Vec::new()),
}
}
+302 -46
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,
@@ -90,8 +93,43 @@ impl Name {
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,
}
/// Styles of representing an enum.
#[derive(Debug)]
pub enum EnumTag {
/// The default.
///
/// ```json
/// {"variant1": {"key1": "value1", "key2": "value2"}}
/// ```
External,
/// `#[serde(tag = "type")]`
///
/// ```json
/// {"type": "variant1", "key1": "value1", "key2": "value2"}
/// ```
Internal { tag: String },
/// `#[serde(tag = "t", content = "c")]`
///
/// ```json
/// {"t": "variant1", "c": {"key1": "value1", "key2": "value2"}}
/// ```
Adjacent { tag: String, content: String },
/// `#[serde(untagged)]`
///
/// ```json
/// {"key1": "value1", "key2": "value2"}
/// ```
None,
}
impl Item {
@@ -100,8 +138,13 @@ impl Item {
let mut ser_name = Attr::none(cx, "rename");
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");
for meta_items in item.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
@@ -122,14 +165,57 @@ 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();
}
// Parse `#[serde(default)]`
MetaItem(Word(ref name)) if name == "default" => {
match item.body {
syn::Body::Struct(syn::VariantData::Struct(_)) => {
default.set(Default::Default);
}
_ => {
cx.error("#[serde(default)] can only be used on structs \
with named fields")
}
}
}
// Parse `#[serde(default="...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "default" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
match item.body {
syn::Body::Struct(syn::VariantData::Struct(_)) => {
default.set(Default::Path(path));
}
_ => {
cx.error("#[serde(default = \"...\")] can only be used \
on structs with named fields")
}
}
}
}
// Parse `#[serde(bound="D: Serialize")]`
MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
if let Ok(where_predicates) =
parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
}
@@ -143,26 +229,116 @@ impl Item {
}
}
// Parse `#[serde(untagged)]`
MetaItem(Word(ref name)) if name == "untagged" => {
match item.body {
syn::Body::Enum(_) => {
untagged.set_true();
}
syn::Body::Struct(_) => {
cx.error("#[serde(untagged)] can only be used on enums")
}
}
}
// Parse `#[serde(tag = "type")]`
MetaItem(NameValue(ref name, ref lit)) if name == "tag" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match item.body {
syn::Body::Enum(_) => {
internal_tag.set(s);
}
syn::Body::Struct(_) => {
cx.error("#[serde(tag = \"...\")] can only be used on enums")
}
}
}
}
// Parse `#[serde(content = "c")]`
MetaItem(NameValue(ref name, ref lit)) if name == "content" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match item.body {
syn::Body::Enum(_) => {
content.set(s);
}
syn::Body::Struct(_) => {
cx.error("#[serde(content = \"...\")] can only be used on \
enums")
}
}
}
}
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde container attribute `{}`",
meta_item.name()));
}
Literal(_) => {
cx.error(format!("unexpected literal in serde container attribute"));
cx.error("unexpected literal in serde container attribute");
}
}
}
}
let tag = match (untagged.get(), internal_tag.get(), content.get()) {
(false, None, None) => EnumTag::External,
(true, None, None) => EnumTag::None,
(false, Some(tag), None) => {
// Check that there are no tuple variants.
if let syn::Body::Enum(ref variants) = item.body {
for variant in variants {
match variant.data {
syn::VariantData::Struct(_) |
syn::VariantData::Unit => {}
syn::VariantData::Tuple(ref fields) => {
if fields.len() != 1 {
cx.error("#[serde(tag = \"...\")] cannot be used with tuple \
variants");
break;
}
}
}
}
}
EnumTag::Internal { tag: tag }
}
(true, Some(_), None) => {
cx.error("enum cannot be both untagged and internally tagged");
EnumTag::External // doesn't matter, will error
}
(false, None, Some(_)) => {
cx.error("#[serde(tag = \"...\", content = \"...\")] must be used together");
EnumTag::External
}
(true, None, Some(_)) => {
cx.error("untagged enum cannot have #[serde(content = \"...\")]");
EnumTag::External
}
(false, Some(tag), Some(content)) => {
EnumTag::Adjacent {
tag: tag,
content: content,
}
}
(true, Some(_), Some(_)) => {
cx.error("untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]");
EnumTag::External
}
};
Item {
name: Name {
serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()),
deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()),
},
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,
}
}
@@ -170,10 +346,18 @@ impl Item {
&self.name
}
pub fn rename_all(&self) -> &RenameRule {
&self.rename_all
}
pub fn deny_unknown_fields(&self) -> bool {
self.deny_unknown_fields
}
pub fn default(&self) -> &Default {
&self.default
}
pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
self.ser_bound.as_ref().map(|vec| &vec[..])
}
@@ -181,12 +365,19 @@ impl Item {
pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
pub fn tag(&self) -> &EnumTag {
&self.tag
}
}
/// 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,
}
@@ -197,6 +388,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 {
@@ -216,6 +408,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();
@@ -226,22 +433,28 @@ impl Variant {
}
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde variant attribute `{}`",
meta_item.name()));
cx.error(format!("unknown serde variant attribute `{}`", meta_item.name()));
}
Literal(_) => {
cx.error(format!("unexpected literal in serde variant attribute"));
cx.error("unexpected literal in serde variant attribute");
}
}
}
}
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(),
}
@@ -251,6 +464,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
}
@@ -264,10 +490,12 @@ 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>,
default: FieldDefault,
default: Default,
serialize_with: Option<syn::Path>,
deserialize_with: Option<syn::Path>,
ser_bound: Option<Vec<syn::WherePredicate>>,
@@ -276,7 +504,7 @@ pub struct Field {
/// Represents the default to use for a field when deserializing.
#[derive(Debug, PartialEq)]
pub enum FieldDefault {
pub enum Default {
/// Field must always be specified because it does not have a default.
None,
/// The default is given by `std::default::Default::default()`.
@@ -287,9 +515,7 @@ pub enum FieldDefault {
impl Field {
/// Extract out the `#[serde(...)]` attributes from a struct field.
pub fn from_ast(cx: &Ctxt,
index: usize,
field: &syn::Field) -> Self {
pub fn from_ast(cx: &Ctxt, index: usize, field: &syn::Field) -> Self {
let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename");
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
@@ -327,13 +553,13 @@ impl Field {
// Parse `#[serde(default)]`
MetaItem(Word(ref name)) if name == "default" => {
default.set(FieldDefault::Default);
default.set(Default::Default);
}
// Parse `#[serde(default="...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "default" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
default.set(FieldDefault::Path(path));
default.set(Default::Path(path));
}
}
@@ -368,9 +594,22 @@ impl Field {
}
}
// Parse `#[serde(with="...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "with" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
let mut ser_path = path.clone();
ser_path.segments.push("serialize".into());
serialize_with.set(ser_path);
let mut de_path = path;
de_path.segments.push("deserialize".into());
deserialize_with.set(de_path);
}
}
// Parse `#[serde(bound="D: Serialize")]`
MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
if let Ok(where_predicates) =
parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
}
@@ -385,12 +624,11 @@ impl Field {
}
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde field attribute `{}`",
meta_item.name()));
cx.error(format!("unknown serde field attribute `{}`", meta_item.name()));
}
Literal(_) => {
cx.error(format!("unexpected literal in serde field attribute"));
cx.error("unexpected literal in serde field attribute");
}
}
}
@@ -399,18 +637,24 @@ impl Field {
// Is skip_deserializing, initialize the field to Default::default()
// unless a different default is specified by `#[serde(default="...")]`
if skip_deserializing.0.value.is_some() {
default.set_if_none(FieldDefault::Default);
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(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(),
default: default.get().unwrap_or(FieldDefault::None),
default: default.get().unwrap_or(Default::None),
serialize_with: serialize_with.get(),
deserialize_with: deserialize_with.get(),
ser_bound: ser_bound.get(),
@@ -422,6 +666,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
}
@@ -434,7 +687,7 @@ impl Field {
self.skip_serializing_if.as_ref()
}
pub fn default(&self) -> &FieldDefault {
pub fn default(&self) -> &Default {
&self.default
}
@@ -457,13 +710,12 @@ impl Field {
type SerAndDe<T> = (Option<T>, Option<T>);
fn get_ser_and_de<T, F>(
cx: &Ctxt,
attr_name: &'static str,
items: &[syn::NestedMetaItem],
f: F
) -> Result<SerAndDe<T>, ()>
where F: Fn(&Ctxt, &str, &str, &syn::Lit) -> Result<T, ()>,
fn get_ser_and_de<T, F>(cx: &Ctxt,
attr_name: &'static str,
items: &[syn::NestedMetaItem],
f: F)
-> Result<SerAndDe<T>, ()>
where F: Fn(&Ctxt, &str, &str, &syn::Lit) -> Result<T, ()>
{
let mut ser_item = Attr::none(cx, attr_name);
let mut de_item = Attr::none(cx, attr_name);
@@ -483,7 +735,8 @@ fn get_ser_and_de<T, F>(
}
_ => {
cx.error(format!("malformed {0} attribute, expected `{0}(serialize = ..., deserialize = ...)`",
cx.error(format!("malformed {0} attribute, expected `{0}(serialize = ..., \
deserialize = ...)`",
attr_name));
return Err(());
}
@@ -493,35 +746,34 @@ fn get_ser_and_de<T, F>(
Ok((ser_item.get(), de_item.get()))
}
fn get_renames(
cx: &Ctxt,
items: &[syn::NestedMetaItem],
) -> Result<SerAndDe<String>, ()> {
fn get_renames(cx: &Ctxt, items: &[syn::NestedMetaItem]) -> Result<SerAndDe<String>, ()> {
get_ser_and_de(cx, "rename", items, get_string_from_lit)
}
fn get_where_predicates(
cx: &Ctxt,
items: &[syn::NestedMetaItem],
) -> Result<SerAndDe<Vec<syn::WherePredicate>>, ()> {
fn get_where_predicates(cx: &Ctxt,
items: &[syn::NestedMetaItem])
-> Result<SerAndDe<Vec<syn::WherePredicate>>, ()> {
get_ser_and_de(cx, "bound", items, parse_lit_into_where)
}
pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option<Vec<syn::NestedMetaItem>> {
match attr.value {
List(ref name, ref items) if name == "serde" => {
Some(items.iter().cloned().collect())
}
_ => None
List(ref name, ref items) if name == "serde" => Some(items.iter().cloned().collect()),
_ => None,
}
}
fn get_string_from_lit(cx: &Ctxt, attr_name: &str, meta_item_name: &str, lit: &syn::Lit) -> Result<String, ()> {
fn get_string_from_lit(cx: &Ctxt,
attr_name: &str,
meta_item_name: &str,
lit: &syn::Lit)
-> Result<String, ()> {
if let syn::Lit::Str(ref s, _) = *lit {
Ok(s.clone())
} else {
cx.error(format!("expected serde {} attribute to be a string: `{} = \"...\"`",
attr_name, meta_item_name));
attr_name,
meta_item_name));
Err(())
}
}
@@ -531,7 +783,11 @@ fn parse_lit_into_path(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn
syn::parse_path(&string).map_err(|err| cx.error(err))
}
fn parse_lit_into_where(cx: &Ctxt, attr_name: &str, meta_item_name: &str, lit: &syn::Lit) -> Result<Vec<syn::WherePredicate>, ()> {
fn parse_lit_into_where(cx: &Ctxt,
attr_name: &str,
meta_item_name: &str,
lit: &syn::Lit)
-> Result<Vec<syn::WherePredicate>, ()> {
let string = try!(get_string_from_lit(cx, attr_name, meta_item_name, lit));
if string.is_empty() {
return Ok(Vec::new());
+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);
}
}
+1 -3
View File
@@ -8,9 +8,7 @@ pub struct Ctxt {
impl Ctxt {
pub fn new() -> Self {
Ctxt {
errors: RefCell::new(Some(Vec::new())),
}
Ctxt { errors: RefCell::new(Some(Vec::new())) }
}
pub fn error<T: Display>(&self, msg: T) {
+2 -3
View File
@@ -1,6 +1,3 @@
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]
extern crate syn;
pub mod ast;
@@ -8,3 +5,5 @@ pub mod attr;
mod ctxt;
pub use ctxt::Ctxt;
mod case;
+11 -14
View File
@@ -1,14 +1,18 @@
[package]
name = "serde_derive"
version = "0.9.1"
version = "0.9.11"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde.rs/codegen.html"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
keywords = ["serde", "serialization", "no_std"]
readme = "../README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[features]
unstable = []
[badges]
travis-ci = { repository = "serde-rs/serde" }
@@ -17,14 +21,7 @@ travis-ci = { repository = "serde-rs/serde" }
name = "serde_derive"
proc-macro = true
[dependencies.serde_codegen]
version = "=0.9.0"
path = "../serde_codegen"
default-features = false
features = ["with-syn"]
[dev-dependencies]
compiletest_rs = "0.2"
fnv = "1.0"
serde = { version = "0.9", path = "../serde" }
serde_test = { version = "0.9", path = "../serde_test" }
[dependencies]
quote = "0.3.8"
serde_codegen_internals = { version = "=0.14.1", default-features = false, path = "../serde_codegen_internals" }
syn = { version = "0.11", features = ["visit"] }
+1
View File
@@ -0,0 +1 @@
../LICENSE-APACHE
+1
View File
@@ -0,0 +1 @@
../LICENSE-MIT
+1
View File
@@ -0,0 +1 @@
../README.md
+228
View File
@@ -0,0 +1,228 @@
use std::collections::HashSet;
use syn::{self, visit};
use internals::ast::Item;
use internals::attr;
macro_rules! path {
($first:ident $(:: $rest:ident)*) => {
syn::Path {
global: false,
segments: vec![
stringify!($first).into(),
$(
stringify!($rest).into(),
)*
],
}
};
(::$first:ident $(:: $rest:ident)*) => {
syn::Path {
global: true,
segments: vec![
stringify!($first).into(),
$(
stringify!($rest).into(),
)*
],
}
};
}
// Remove the default from every type parameter because in the generated impls
// they look like associated types: "error: associated type bindings are not
// allowed here".
pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
syn::Generics {
ty_params: generics.ty_params
.iter()
.map(|ty_param| syn::TyParam { default: None, ..ty_param.clone() })
.collect(),
..generics.clone()
}
}
pub fn with_where_predicates(generics: &syn::Generics,
predicates: &[syn::WherePredicate])
-> syn::Generics {
let mut generics = generics.clone();
generics.where_clause.predicates.extend_from_slice(predicates);
generics
}
pub fn with_where_predicates_from_fields<F>(item: &Item,
generics: &syn::Generics,
from_field: F)
-> syn::Generics
where F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>
{
let predicates = item.body
.all_fields()
.flat_map(|field| from_field(&field.attrs))
.flat_map(|predicates| predicates.to_vec());
let mut generics = generics.clone();
generics.where_clause.predicates.extend(predicates);
generics
}
// Puts the given bound on any generic type parameters that are used in fields
// for which filter returns true.
//
// For example, the following struct needs the bound `A: Serialize, B: Serialize`.
//
// struct S<'b, A, B: 'b, C> {
// a: A,
// b: Option<&'b B>
// #[serde(skip_serializing)]
// c: C,
// }
pub fn with_bound<F>(item: &Item,
generics: &syn::Generics,
filter: F,
bound: &syn::Path)
-> syn::Generics
where F: Fn(&attr::Field) -> bool
{
struct FindTyParams {
// Set of all generic type parameters on the current struct (A, B, C in
// the example). Initialized up front.
all_ty_params: HashSet<syn::Ident>,
// Set of generic type parameters used in fields for which filter
// returns true (A and B in the example). Filled in as the visitor sees
// them.
relevant_ty_params: HashSet<syn::Ident>,
}
impl visit::Visitor for FindTyParams {
fn visit_path(&mut self, path: &syn::Path) {
if let Some(seg) = path.segments.last() {
if seg.ident == "PhantomData" {
// Hardcoded exception, because PhantomData<T> implements
// Serialize and Deserialize whether or not T implements it.
return;
}
}
if !path.global && path.segments.len() == 1 {
let id = path.segments[0].ident.clone();
if self.all_ty_params.contains(&id) {
self.relevant_ty_params.insert(id);
}
}
visit::walk_path(self, path);
}
}
let all_ty_params: HashSet<_> = generics.ty_params
.iter()
.map(|ty_param| ty_param.ident.clone())
.collect();
let relevant_tys = item.body
.all_fields()
.filter(|&field| filter(&field.attrs))
.map(|field| &field.ty);
let mut visitor = FindTyParams {
all_ty_params: all_ty_params,
relevant_ty_params: HashSet::new(),
};
for ty in relevant_tys {
visit::walk_ty(&mut visitor, ty);
}
let new_predicates = generics.ty_params
.iter()
.map(|ty_param| ty_param.ident.clone())
.filter(|id| visitor.relevant_ty_params.contains(id))
.map(|id| {
syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
bound_lifetimes: Vec::new(),
// the type parameter that is being bounded e.g. T
bounded_ty: syn::Ty::Path(None, id.into()),
// the bound e.g. Serialize
bounds: vec![syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None
)],
})
});
let mut generics = generics.clone();
generics.where_clause.predicates.extend(new_predicates);
generics
}
pub fn with_self_bound(item: &Item,
generics: &syn::Generics,
bound: &syn::Path)
-> syn::Generics
{
let mut generics = generics.clone();
generics.where_clause.predicates.push(
syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
bound_lifetimes: Vec::new(),
// the type that is being bounded e.g. MyStruct<'a, T>
bounded_ty: type_of_item(item),
// the bound e.g. Default
bounds: vec![syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None
)],
})
);
generics
}
pub fn with_lifetime_bound(generics: &syn::Generics,
lifetime: &str)
-> syn::Generics {
let mut generics = generics.clone();
for lifetime_def in &mut generics.lifetimes {
lifetime_def.bounds.push(syn::Lifetime::new(lifetime));
}
for ty_param in &mut generics.ty_params {
ty_param.bounds.push(syn::TyParamBound::Region(syn::Lifetime::new(lifetime)));
}
generics.lifetimes.push(syn::LifetimeDef {
attrs: Vec::new(),
lifetime: syn::Lifetime::new(lifetime),
bounds: Vec::new(),
});
generics
}
fn type_of_item(item: &Item) -> syn::Ty {
syn::Ty::Path(None, syn::Path {
global: false,
segments: vec![
syn::PathSegment {
ident: item.ident.clone(),
parameters: syn::PathParameters::AngleBracketed(syn::AngleBracketedParameterData {
lifetimes: item.generics
.lifetimes
.iter()
.map(|def| def.lifetime.clone())
.collect(),
types: item.generics
.ty_params
.iter()
.map(|param| syn::Ty::Path(None, param.ident.clone().into()))
.collect(),
bindings: Vec::new(),
}),
}
]
})
}
File diff suppressed because it is too large Load Diff
+67
View File
@@ -0,0 +1,67 @@
use quote::{Tokens, ToTokens};
pub enum Fragment {
/// Tokens that can be used as an expression.
Expr(Tokens),
/// Tokens that can be used inside a block. The surrounding curly braces are
/// not part of these tokens.
Block(Tokens),
}
macro_rules! quote_expr {
($($tt:tt)*) => {
$crate::fragment::Fragment::Expr(quote!($($tt)*))
}
}
macro_rules! quote_block {
($($tt:tt)*) => {
$crate::fragment::Fragment::Block(quote!($($tt)*))
}
}
/// Interpolate a fragment in place of an expression. This involves surrounding
/// Block fragments in curly braces.
pub struct Expr(pub Fragment);
impl ToTokens for Expr {
fn to_tokens(&self, out: &mut Tokens) {
match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => {
out.append("{");
block.to_tokens(out);
out.append("}");
}
}
}
}
/// Interpolate a fragment as the statements of a block.
pub struct Stmts(pub Fragment);
impl ToTokens for Stmts {
fn to_tokens(&self, out: &mut Tokens) {
match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => block.to_tokens(out),
}
}
}
/// Interpolate a fragment as the value part of a `match` expression. This
/// involves putting a comma after expressions and curly braces around blocks.
pub struct Match(pub Fragment);
impl ToTokens for Match {
fn to_tokens(&self, out: &mut Tokens) {
match self.0 {
Fragment::Expr(ref expr) => {
expr.to_tokens(out);
out.append(",");
}
Fragment::Block(ref block) => {
out.append("{");
block.to_tokens(out);
out.append("}");
}
}
}
}
+24 -4
View File
@@ -1,11 +1,30 @@
extern crate proc_macro;
extern crate serde_codegen;
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "192"]
extern crate syn;
#[macro_use]
extern crate quote;
extern crate serde_codegen_internals as internals;
extern crate proc_macro;
use proc_macro::TokenStream;
#[macro_use]
mod bound;
#[macro_use]
mod fragment;
mod ser;
mod de;
#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
match serde_codegen::expand_derive_serialize(&input.to_string()) {
let input = syn::parse_derive_input(&input.to_string()).unwrap();
match ser::expand_derive_serialize(&input) {
Ok(expanded) => expanded.parse().unwrap(),
Err(msg) => panic!(msg),
}
@@ -13,7 +32,8 @@ pub fn derive_serialize(input: TokenStream) -> TokenStream {
#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
match serde_codegen::expand_derive_deserialize(&input.to_string()) {
let input = syn::parse_derive_input(&input.to_string()).unwrap();
match de::expand_derive_deserialize(&input) {
Ok(expanded) => expanded.parse().unwrap(),
Err(msg) => panic!(msg),
}
+782
View File
@@ -0,0 +1,782 @@
use syn::{self, Ident};
use quote::Tokens;
use bound;
use fragment::{Fragment, Stmts, Match};
use internals::ast::{Body, Field, Item, Style, Variant};
use internals::{self, attr};
pub fn expand_derive_serialize(item: &syn::DeriveInput) -> Result<Tokens, String> {
let ctxt = internals::Ctxt::new();
let item = Item::from_ast(&ctxt, item);
try!(ctxt.check());
let ident = &item.ident;
let generics = build_generics(&item);
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let dummy_const = Ident::new(format!("_IMPL_SERIALIZE_FOR_{}", ident));
let body = Stmts(serialize_body(&item, &generics));
Ok(quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
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>
where __S: _serde::Serializer
{
#body
}
}
};
})
}
// All the generics in the input, plus a bound `T: Serialize` for each generic
// field type that will be serialized by us.
fn build_generics(item: &Item) -> syn::Generics {
let generics = bound::without_defaults(item.generics);
let generics =
bound::with_where_predicates_from_fields(item, &generics, attr::Field::ser_bound);
match item.attrs.ser_bound() {
Some(predicates) => bound::with_where_predicates(&generics, predicates),
None => {
bound::with_bound(item,
&generics,
needs_serialize_bound,
&path!(_serde::Serialize))
}
}
}
// Fields with a `skip_serializing` or `serialize_with` attribute are not
// serialized by us so we do not generate a bound. Fields with a `bound`
// attribute specify their own bound so we do not generate one. All other fields
// may need a `T: Serialize` bound where T is the type of the field.
fn needs_serialize_bound(attrs: &attr::Field) -> bool {
!attrs.skip_serializing() && attrs.serialize_with().is_none() && attrs.ser_bound().is_none()
}
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");
}
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),
}
}
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)
}
}
fn serialize_newtype_struct(ident: &syn::Ident,
generics: &syn::Generics,
field: &Field,
item_attrs: &attr::Item)
-> Fragment {
let type_name = item_attrs.name().serialize_name();
let mut field_expr = quote!(&self.0);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(ident, generics, field.ty, path, field_expr);
}
quote_expr! {
_serde::Serializer::serialize_newtype_struct(_serializer, #type_name, #field_expr)
}
}
fn serialize_tuple_struct(ident: &syn::Ident,
generics: &syn::Generics,
fields: &[Field],
item_attrs: &attr::Item)
-> Fragment {
let serialize_stmts =
serialize_tuple_struct_visitor(ident,
fields,
generics,
false,
quote!(_serde::ser::SerializeTupleStruct::serialize_field));
let type_name = item_attrs.name().serialize_name();
let len = serialize_stmts.len();
let let_mut = mut_if(len > 0);
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(_serializer, #type_name, #len));
#(#serialize_stmts)*
_serde::ser::SerializeTupleStruct::end(__serde_state)
}
}
fn serialize_struct(ident: &syn::Ident,
generics: &syn::Generics,
fields: &[Field],
item_attrs: &attr::Item)
-> Fragment {
let serialize_fields =
serialize_struct_visitor(ident,
fields,
generics,
false,
quote!(_serde::ser::SerializeStruct::serialize_field));
let type_name = item_attrs.name().serialize_name();
let mut serialized_fields = fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields.map(|field| {
let ident = field.ident.clone().expect("struct has unnamed fields");
let field_expr = quote!(&self.#ident);
match field.attrs.skip_serializing_if() {
Some(path) => quote!(if #path(#field_expr) { 0 } else { 1 }),
None => quote!(1),
}
})
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(_serializer, #type_name, #len));
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
}
fn serialize_item_enum(ident: &syn::Ident,
generics: &syn::Generics,
variants: &[Variant],
item_attrs: &attr::Item)
-> Fragment {
let arms: Vec<_> = variants.iter()
.enumerate()
.map(|(variant_index, variant)| {
serialize_variant(ident,
generics,
variant,
variant_index,
item_attrs)
})
.collect();
quote_expr! {
match *self {
#(#arms)*
}
}
}
fn serialize_variant(ident: &syn::Ident,
generics: &syn::Generics,
variant: &Variant,
variant_index: usize,
item_attrs: &attr::Item)
-> Tokens {
let variant_ident = variant.ident.clone();
if variant.attrs.skip_serializing() {
let skipped_msg = format!("the enum variant {}::{} cannot be serialized",
ident, variant_ident);
let skipped_err = quote! {
_serde::export::Err(_serde::ser::Error::custom(#skipped_msg))
};
let fields_pat = match variant.style {
Style::Unit => quote!(),
Style::Newtype | Style::Tuple => quote!( (..) ),
Style::Struct => quote!( {..} ),
};
quote! {
#ident::#variant_ident #fields_pat => #skipped_err,
}
} else {
// variant wasn't skipped
let case = match variant.style {
Style::Unit => {
quote! {
#ident::#variant_ident
}
}
Style::Newtype => {
quote! {
#ident::#variant_ident(ref __field0)
}
}
Style::Tuple => {
let field_names = (0..variant.fields.len())
.map(|i| Ident::new(format!("__field{}", i)));
quote! {
#ident::#variant_ident(#(ref #field_names),*)
}
}
Style::Struct => {
let fields = variant.fields
.iter()
.map(|f| f.ident.clone().expect("struct variant has unnamed fields"));
quote! {
#ident::#variant_ident { #(ref #fields),* }
}
}
};
let body = Match(match *item_attrs.tag() {
attr::EnumTag::External => {
serialize_externally_tagged_variant(ident,
generics,
variant,
variant_index,
item_attrs)
}
attr::EnumTag::Internal { ref tag } => {
serialize_internally_tagged_variant(ident,
generics,
variant,
item_attrs,
tag)
}
attr::EnumTag::Adjacent { ref tag, ref content } => {
serialize_adjacently_tagged_variant(ident,
generics,
variant,
item_attrs,
tag,
content)
}
attr::EnumTag::None => serialize_untagged_variant(ident, generics, variant, item_attrs),
});
quote! {
#case => #body
}
}
}
fn serialize_externally_tagged_variant(ident: &syn::Ident,
generics: &syn::Generics,
variant: &Variant,
variant_index: usize,
item_attrs: &attr::Item)
-> Fragment {
let type_name = item_attrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name();
match variant.style {
Style::Unit => {
quote_expr! {
_serde::Serializer::serialize_unit_variant(
_serializer,
#type_name,
#variant_index,
#variant_name,
)
}
}
Style::Newtype => {
let field = &variant.fields[0];
let mut field_expr = quote!(__field0);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(ident, generics, field.ty, path, field_expr);
}
quote_expr! {
_serde::Serializer::serialize_newtype_variant(
_serializer,
#type_name,
#variant_index,
#variant_name,
#field_expr,
)
}
}
Style::Tuple => {
serialize_tuple_variant(TupleVariant::ExternallyTagged {
type_name: type_name,
variant_index: variant_index,
variant_name: variant_name,
},
ident,
generics,
&variant.fields)
}
Style::Struct => {
serialize_struct_variant(StructVariant::ExternallyTagged {
variant_index: variant_index,
variant_name: variant_name,
},
ident,
generics,
&variant.fields,
&type_name)
}
}
}
fn serialize_internally_tagged_variant(ident: &syn::Ident,
generics: &syn::Generics,
variant: &Variant,
item_attrs: &attr::Item,
tag: &str)
-> Fragment {
let type_name = item_attrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name();
let enum_ident_str = ident.as_ref();
let variant_ident_str = variant.ident.as_ref();
match variant.style {
Style::Unit => {
quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
_serializer, #type_name, 1));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
_serde::ser::SerializeStruct::end(__struct)
}
}
Style::Newtype => {
let field = &variant.fields[0];
let mut field_expr = quote!(__field0);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(ident, generics, field.ty, path, field_expr);
}
quote_expr! {
_serde::ser::private::serialize_tagged_newtype(
_serializer,
#enum_ident_str,
#variant_ident_str,
#tag,
#variant_name,
#field_expr,
)
}
}
Style::Struct => {
serialize_struct_variant(StructVariant::InternallyTagged {
tag: tag,
variant_name: variant_name,
},
ident,
generics,
&variant.fields,
&type_name)
}
Style::Tuple => unreachable!("checked in serde_codegen_internals"),
}
}
fn serialize_adjacently_tagged_variant(ident: &syn::Ident,
generics: &syn::Generics,
variant: &Variant,
item_attrs: &attr::Item,
tag: &str,
content: &str)
-> Fragment {
let type_name = item_attrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name();
let inner = Stmts(match variant.style {
Style::Unit => {
return quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
_serializer, #type_name, 1));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
_serde::ser::SerializeStruct::end(__struct)
};
}
Style::Newtype => {
let field = &variant.fields[0];
let mut field_expr = quote!(__field0);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(ident, generics, field.ty, path, field_expr);
}
quote_expr! {
_serde::Serialize::serialize(#field_expr, _serializer)
}
}
Style::Tuple => {
serialize_tuple_variant(TupleVariant::Untagged,
ident,
generics,
&variant.fields)
}
Style::Struct => {
serialize_struct_variant(StructVariant::Untagged,
ident,
generics,
&variant.fields,
&variant_name)
}
});
let fields_ty = variant.fields.iter().map(|f| &f.ty);
let ref fields_ident: Vec<_> = match variant.style {
Style::Unit => unreachable!(),
Style::Newtype => vec![Ident::new("__field0")],
Style::Tuple => {
(0..variant.fields.len())
.map(|i| Ident::new(format!("__field{}", i)))
.collect()
}
Style::Struct => {
variant.fields
.iter()
.map(|f| f.ident.clone().expect("struct variant has unnamed fields"))
.collect()
}
};
let (_, ty_generics, where_clause) = generics.split_for_impl();
let wrapper_generics = bound::with_lifetime_bound(generics, "'__a");
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
quote_block! {
struct __AdjacentlyTagged #wrapper_generics #where_clause {
data: (#(&'__a #fields_ty,)*),
phantom: _serde::export::PhantomData<#ident #ty_generics>,
}
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>
where __S: _serde::Serializer
{
let (#(#fields_ident,)*) = self.data;
#inner
}
}
let mut __struct = try!(_serde::Serializer::serialize_struct(
_serializer, #type_name, 2));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #content, &__AdjacentlyTagged {
data: (#(#fields_ident,)*),
phantom: _serde::export::PhantomData::<#ident #ty_generics>,
}));
_serde::ser::SerializeStruct::end(__struct)
}
}
fn serialize_untagged_variant(ident: &syn::Ident,
generics: &syn::Generics,
variant: &Variant,
item_attrs: &attr::Item)
-> Fragment {
match variant.style {
Style::Unit => {
quote_expr! {
_serde::Serializer::serialize_unit(_serializer)
}
}
Style::Newtype => {
let field = &variant.fields[0];
let mut field_expr = quote!(__field0);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(ident, generics, field.ty, path, field_expr);
}
quote_expr! {
_serde::Serialize::serialize(#field_expr, _serializer)
}
}
Style::Tuple => {
serialize_tuple_variant(TupleVariant::Untagged, ident, generics, &variant.fields)
}
Style::Struct => {
let type_name = item_attrs.name().serialize_name();
serialize_struct_variant(StructVariant::Untagged,
ident,
generics,
&variant.fields,
&type_name)
}
}
}
enum TupleVariant {
ExternallyTagged {
type_name: String,
variant_index: usize,
variant_name: String,
},
Untagged,
}
fn serialize_tuple_variant(context: TupleVariant,
ident: &syn::Ident,
generics: &syn::Generics,
fields: &[Field])
-> Fragment {
let method = match context {
TupleVariant::ExternallyTagged { .. } => {
quote!(_serde::ser::SerializeTupleVariant::serialize_field)
}
TupleVariant::Untagged => quote!(_serde::ser::SerializeTuple::serialize_element),
};
let serialize_stmts =
serialize_tuple_struct_visitor(ident, fields, generics, true, method);
let len = serialize_stmts.len();
let let_mut = mut_if(len > 0);
match context {
TupleVariant::ExternallyTagged { type_name, variant_index, variant_name } => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_variant(
_serializer,
#type_name,
#variant_index,
#variant_name,
#len));
#(#serialize_stmts)*
_serde::ser::SerializeTupleVariant::end(__serde_state)
}
}
TupleVariant::Untagged => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple(
_serializer,
#len));
#(#serialize_stmts)*
_serde::ser::SerializeTuple::end(__serde_state)
}
}
}
}
enum StructVariant<'a> {
ExternallyTagged {
variant_index: usize,
variant_name: String,
},
InternallyTagged { tag: &'a str, variant_name: String },
Untagged,
}
fn serialize_struct_variant<'a>(context: StructVariant<'a>,
ident: &syn::Ident,
generics: &syn::Generics,
fields: &[Field],
name: &str)
-> Fragment {
let method = match context {
StructVariant::ExternallyTagged { .. } => {
quote!(_serde::ser::SerializeStructVariant::serialize_field)
}
StructVariant::InternallyTagged { .. } |
StructVariant::Untagged => quote!(_serde::ser::SerializeStruct::serialize_field),
};
let serialize_fields = serialize_struct_visitor(ident, fields, generics, true, method);
let mut serialized_fields = fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields.map(|field| {
let ident = field.ident.clone().expect("struct has unnamed fields");
match field.attrs.skip_serializing_if() {
Some(path) => quote!(if #path(#ident) { 0 } else { 1 }),
None => quote!(1),
}
})
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
match context {
StructVariant::ExternallyTagged { variant_index, variant_name } => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct_variant(
_serializer,
#name,
#variant_index,
#variant_name,
#len,
));
#(#serialize_fields)*
_serde::ser::SerializeStructVariant::end(__serde_state)
}
}
StructVariant::InternallyTagged { tag, variant_name } => {
quote_block! {
let mut __serde_state = try!(_serde::Serializer::serialize_struct(
_serializer,
#name,
#len + 1,
));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __serde_state,
#tag,
#variant_name,
));
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
}
StructVariant::Untagged => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(
_serializer,
#name,
#len,
));
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
}
}
}
fn serialize_tuple_struct_visitor(ident: &syn::Ident,
fields: &[Field],
generics: &syn::Generics,
is_enum: bool,
func: Tokens)
-> Vec<Tokens> {
fields.iter()
.enumerate()
.map(|(i, field)| {
let mut field_expr = if is_enum {
let id = Ident::new(format!("__field{}", i));
quote!(#id)
} else {
let i = Ident::new(i);
quote!(&self.#i)
};
let skip = field.attrs
.skip_serializing_if()
.map(|path| quote!(#path(#field_expr)));
if let Some(path) = field.attrs.serialize_with() {
field_expr =
wrap_serialize_with(ident, generics, field.ty, path, field_expr);
}
let ser = quote! {
try!(#func(&mut __serde_state, #field_expr));
};
match skip {
None => ser,
Some(skip) => quote!(if !#skip { #ser }),
}
})
.collect()
}
fn serialize_struct_visitor(ident: &syn::Ident,
fields: &[Field],
generics: &syn::Generics,
is_enum: bool,
func: Tokens)
-> Vec<Tokens> {
fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.map(|field| {
let field_ident = field.ident.clone().expect("struct has unnamed field");
let mut field_expr = if is_enum {
quote!(#field_ident)
} else {
quote!(&self.#field_ident)
};
let key_expr = field.attrs.name().serialize_name();
let skip = field.attrs
.skip_serializing_if()
.map(|path| quote!(#path(#field_expr)));
if let Some(path) = field.attrs.serialize_with() {
field_expr =
wrap_serialize_with(ident, generics, field.ty, path, field_expr)
}
let ser = quote! {
try!(#func(&mut __serde_state, #key_expr, #field_expr));
};
match skip {
None => ser,
Some(skip) => quote!(if !#skip { #ser }),
}
})
.collect()
}
fn wrap_serialize_with(ident: &syn::Ident,
generics: &syn::Generics,
field_ty: &syn::Ty,
serialize_with: &syn::Path,
value: Tokens)
-> Tokens {
let (_, ty_generics, where_clause) = generics.split_for_impl();
let wrapper_generics = bound::with_lifetime_bound(generics, "'__a");
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
quote!({
struct __SerializeWith #wrapper_impl_generics #where_clause {
value: &'__a #field_ty,
phantom: _serde::export::PhantomData<#ident #ty_generics>,
}
impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __s: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
{
#serialize_with(self.value, __s)
}
}
&__SerializeWith {
value: #value,
phantom: _serde::export::PhantomData::<#ident #ty_generics>,
}
})
}
// Serialization of an empty struct results in code like:
//
// let mut __serde_state = try!(serializer.serialize_struct("S", 0));
// _serde::ser::SerializeStruct::end(__serde_state)
//
// where we want to omit the `mut` to avoid a warning.
fn mut_if(is_mut: bool) -> Option<Tokens> {
if is_mut { Some(quote!(mut)) } else { None }
}
-30
View File
@@ -1,30 +0,0 @@
extern crate compiletest_rs as compiletest;
use std::path::PathBuf;
use std::env::var;
fn run_mode(mode: &'static str) {
let mut config = compiletest::default_config();
let cfg_mode = mode.parse().ok().expect("Invalid mode");
config.target_rustcflags = Some("-L target/debug/ -L target/debug/deps/".to_owned());
if let Ok(name) = var::<&str>("TESTNAME") {
let s : String = name.to_owned();
config.filter = Some(s)
}
config.mode = cfg_mode;
config.src_base = PathBuf::from(format!("tests/{}", mode));
compiletest::run_tests(&config);
}
#[test]
fn compile_fail() {
run_mode("compile-fail");
}
#[test]
fn run_pass() {
run_mode("run-pass");
}
-10
View File
@@ -1,10 +0,0 @@
#![feature(test)]
#[macro_use]
extern crate serde_derive;
extern crate test;
include!("../../testing/tests/test.rs.in");
mod compile_tests;
+3 -3
View File
@@ -1,15 +1,15 @@
[package]
name = "serde_test"
version = "0.9.1"
version = "0.9.11"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_test/"
readme = "../README.md"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
readme = "../README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[dependencies]
serde = { version = "0.9", path = "../serde" }
+1
View File
@@ -0,0 +1 @@
../LICENSE-APACHE
+1
View File
@@ -0,0 +1 @@
../LICENSE-MIT
+1
View File
@@ -0,0 +1 @@
../README.md
+10 -7
View File
@@ -7,24 +7,26 @@ 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,
where T: Serialize + Deserialize + PartialEq + Debug
{
assert_ser_tokens(value, tokens);
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,
where T: Serialize
{
let mut ser = Serializer::new(tokens.iter());
assert_eq!(Serialize::serialize(value, &mut ser), Ok(()));
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,
where T: Serialize + PartialEq + Debug
{
let mut ser = Serializer::new(tokens.iter());
let v: Result<(), Error> = Serialize::serialize(value, &mut ser);
@@ -32,8 +34,9 @@ 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,
where T: Deserialize + PartialEq + Debug
{
let mut de = Deserializer::new(tokens.to_vec().into_iter());
let v: Result<T, Error> = Deserialize::deserialize(&mut de);
@@ -41,9 +44,9 @@ 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,
where T: Deserialize + PartialEq + Debug
{
let mut de = Deserializer::new(tokens.to_vec().into_iter());
let v: Result<T, Error> = Deserialize::deserialize(&mut de);
+208 -492
View File
File diff suppressed because it is too large Load Diff
+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 -7
View File
@@ -1,13 +1,9 @@
#[macro_use]
extern crate serde;
mod assert;
pub use assert::{
assert_tokens,
assert_ser_tokens,
assert_ser_tokens_error,
assert_de_tokens,
assert_de_tokens_error,
};
pub use assert::{assert_tokens, assert_ser_tokens, assert_ser_tokens_error, assert_de_tokens,
assert_de_tokens_error};
mod ser;
pub use ser::Serializer;
+49 -29
View File
@@ -5,16 +5,18 @@ 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>>,
where I: Iterator<Item = &'a Token<'a>>
{
tokens: I,
phantom: PhantomData<&'a Token<'a>>,
}
impl<'a, I> Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
where I: Iterator<Item = &'a Token<'a>>
{
/// Creates the serializer.
pub fn new(tokens: I) -> Serializer<'a, I> {
Serializer {
tokens: tokens,
@@ -22,13 +24,14 @@ 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()
}
}
impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = ();
type Error = Error;
@@ -124,15 +127,14 @@ impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I>
fn serialize_unit_variant(self,
name: &str,
_variant_index: usize,
variant: &str) -> Result<(), Error> {
variant: &str)
-> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumUnit(name, variant)));
Ok(())
}
fn serialize_newtype_struct<T: ?Sized>(self,
name: &'static str,
value: &T) -> Result<(), Error>
where T: Serialize,
fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::StructNewType(name)));
value.serialize(self)
@@ -142,8 +144,9 @@ impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I>
name: &str,
_variant_index: usize,
variant: &str,
value: &T) -> Result<(), Error>
where T: Serialize,
value: &T)
-> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::EnumNewType(name, variant)));
value.serialize(self)
@@ -155,7 +158,7 @@ impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I>
}
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error>
where T: Serialize,
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::Option(true)));
value.serialize(self)
@@ -177,7 +180,8 @@ impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I>
}
fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleStructStart(name, len)));
assert_eq!(self.tokens.next(),
Some(&Token::TupleStructStart(name, len)));
Ok(self)
}
@@ -185,9 +189,10 @@ impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I>
name: &str,
_variant_index: usize,
variant: &str,
len: usize) -> Result<Self, Error>
{
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqStart(name, variant, len)));
len: usize)
-> Result<Self, Error> {
assert_eq!(self.tokens.next(),
Some(&Token::EnumSeqStart(name, variant, len)));
Ok(self)
}
@@ -205,15 +210,16 @@ impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I>
name: &str,
_variant_index: usize,
variant: &str,
len: usize) -> Result<Self, Error>
{
assert_eq!(self.tokens.next(), Some(&Token::EnumMapStart(name, variant, len)));
len: usize)
-> Result<Self, Error> {
assert_eq!(self.tokens.next(),
Some(&Token::EnumMapStart(name, variant, len)));
Ok(self)
}
}
impl<'s, 'a, I> ser::SerializeSeq for &'s mut Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = ();
type Error = Error;
@@ -232,7 +238,7 @@ impl<'s, 'a, I> ser::SerializeSeq for &'s mut Serializer<'a, I>
}
impl<'s, 'a, I> ser::SerializeTuple for &'s mut Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = ();
type Error = Error;
@@ -251,7 +257,7 @@ impl<'s, 'a, I> ser::SerializeTuple for &'s mut Serializer<'a, I>
}
impl<'s, 'a, I> ser::SerializeTupleStruct for &'s mut Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = ();
type Error = Error;
@@ -270,7 +276,7 @@ impl<'s, 'a, I> ser::SerializeTupleStruct for &'s mut Serializer<'a, I>
}
impl<'s, 'a, I> ser::SerializeTupleVariant for &'s mut Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = ();
type Error = Error;
@@ -289,17 +295,21 @@ impl<'s, 'a, I> ser::SerializeTupleVariant for &'s mut Serializer<'a, I>
}
impl<'s, 'a, I> ser::SerializeMap for &'s mut Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = ();
type Error = Error;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error> where T: Serialize {
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::MapSep));
key.serialize(&mut **self)
}
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> where T: Serialize {
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where T: Serialize
{
value.serialize(&mut **self)
}
@@ -310,12 +320,17 @@ impl<'s, 'a, I> ser::SerializeMap for &'s mut Serializer<'a, I>
}
impl<'s, 'a, I> ser::SerializeStruct for &'s mut Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where T: Serialize {
fn serialize_field<T: ?Sized>(&mut self,
key: &'static str,
value: &T)
-> Result<(), Self::Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::StructSep));
try!(key.serialize(&mut **self));
value.serialize(&mut **self)
@@ -328,12 +343,17 @@ impl<'s, 'a, I> ser::SerializeStruct for &'s mut Serializer<'a, I>
}
impl<'s, 'a, I> ser::SerializeStructVariant for &'s mut Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where T: Serialize {
fn serialize_field<T: ?Sized>(&mut self,
key: &'static str,
value: &T)
-> Result<(), Self::Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::EnumMapSep));
try!(key.serialize(&mut **self));
value.serialize(&mut **self)
+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,
}
+18
View File
@@ -0,0 +1,18 @@
[package]
name = "serde_test_suite"
version = "0.0.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
publish = false
[features]
unstable-testing = ["compiletest_rs"]
[dev-dependencies]
fnv = "1.0"
rustc-serialize = "0.3.16"
serde = { path = "../serde" }
serde_derive = { path = "../serde_derive" }
serde_test = { path = "../serde_test" }
[dependencies]
compiletest_rs = { version = "0.2", optional = true }
+11
View File
@@ -0,0 +1,11 @@
[package]
name = "serde_test_suite_deps"
version = "0.0.0"
authors = ["David Tolnay <dtolnay@gmail.com>"]
publish = false
[workspace]
[dependencies]
serde = { path = "../../serde" }
serde_derive = { path = "../../serde_derive" }
View File
@@ -5,4 +5,4 @@ publish = false
[dependencies]
serde = { path = "../../serde", default-features = false }
serde_derive = { path = ".." }
serde_derive = { path = "../../serde_derive" }
@@ -21,7 +21,9 @@ pub extern fn rust_eh_unwind_resume() {}
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
_file: &'static str,
_line: u32) -> ! {
loop {}
unsafe {
libc::abort()
}
}
//////////////////////////////////////////////////////////////////////////////
@@ -0,0 +1,8 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(default)] //~^ HELP: #[serde(default)] can only be used on structs
enum E {
S { f: u8 },
}
@@ -0,0 +1,8 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(default)] //~^ HELP: #[serde(default)] can only be used on structs
struct T(u8, u8);
fn main() { }
@@ -1,7 +1,7 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S {
#[serde(rename="x", serialize="y")] //~^^ HELP: unknown serde field attribute `serialize`
x: (),
@@ -1,7 +1,7 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S {
#[serde(rename="x")]
#[serde(rename(deserialize="y"))] //~^^^ HELP: duplicate serde attribute `rename`
@@ -1,7 +1,7 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S {
#[serde(rename(serialize="x"), rename(serialize="y"))] //~^^ HELP: duplicate serde attribute `rename`
x: (),
@@ -1,7 +1,7 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S {
#[serde(rename(serialize="x"))]
#[serde(rename="y")] //~^^^ HELP: duplicate serde attribute `rename`
@@ -1,7 +1,7 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S {
#[serde(rename(serialize="x", serialize="y"))] //~^^ HELP: duplicate serde attribute `rename`
x: (),
@@ -1,7 +1,7 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S {
#[serde(rename(serialize="x"))]
#[serde(rename(serialize="y"))] //~^^^ HELP: duplicate serde attribute `rename`
@@ -0,0 +1,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S {
#[serde(with = "w", serialize_with = "s")] //~^^ HELP: duplicate serde attribute `serialize_with`
x: (),
}
fn main() {}
@@ -0,0 +1,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(tag = "type")] //~^ HELP: #[serde(tag = "...")] cannot be used with tuple variants
enum E {
Tuple(u8, u8),
}
fn main() {}
@@ -0,0 +1,8 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(tag = "type")] //~^ HELP: #[serde(tag = "...")] can only be used on enums
struct S;
fn main() {}
@@ -0,0 +1,12 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(untagged)]
#[serde(tag = "type")] //~^^ HELP: enum cannot be both untagged and internally tagged
enum E {
A(u8),
B(String),
}
fn main() {}
@@ -0,0 +1,8 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(untagged)] //~^ HELP: #[serde(untagged)] can only be used on enums
struct S;
fn main() {}
@@ -1,7 +1,7 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize, Deserialize)] //~ ERROR: custom derive attribute panicked
#[derive(Serialize, Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test<'a> {
s: &'a str, //~^^ HELP: Serde does not support deserializing fields of type &str
}
@@ -1,7 +1,7 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(abc="xyz")] //~^ HELP: unknown serde container attribute `abc`
struct A {
x: u32,
@@ -1,7 +1,7 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct C {
#[serde(abc="xyz")] //~^^ HELP: unknown serde field attribute `abc`
x: u32,
@@ -1,7 +1,7 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
enum E {
#[serde(abc="xyz")] //~^^ HELP: unknown serde variant attribute `abc`
V,
+28
View File
@@ -0,0 +1,28 @@
#![cfg(feature = "unstable-testing")]
extern crate compiletest_rs as compiletest;
use std::env;
fn run_mode(mode: &'static str) {
let mut config = compiletest::default_config();
config.mode = mode.parse().expect("invalid mode");
config.target_rustcflags = Some("-L deps/target/debug/deps".to_owned());
if let Ok(name) = env::var("TESTNAME") {
config.filter = Some(name);
}
config.src_base = format!("tests/{}", mode).into();
compiletest::run_tests(&config);
}
#[test]
fn compile_fail() {
run_mode("compile-fail");
}
#[test]
fn run_pass() {
run_mode("run-pass");
}
@@ -1,31 +1,3 @@
#[macro_export]
macro_rules! declare_ser_tests {
($($name:ident { $($value:expr => $tokens:expr,)+ })+) => {
$(
#[test]
fn $name() {
$(
assert_ser_tokens(&$value, $tokens);
)+
}
)+
}
}
#[macro_export]
macro_rules! btreemap {
() => {
BTreeMap::new()
};
($($key:expr => $value:expr),+) => {
{
let mut map = BTreeMap::new();
$(map.insert($key, $value);)+
map
}
}
}
macro_rules! btreeset {
() => {
BTreeSet::new()
@@ -1,3 +1,6 @@
#[macro_use]
extern crate serde_derive;
extern crate serde;
use self::serde::{Serialize, Serializer, Deserialize, Deserializer};
@@ -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]
@@ -1,8 +1,14 @@
#[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;
extern crate serde;
use serde::Deserialize;
extern crate fnv;
@@ -16,6 +22,9 @@ use self::serde_test::{
assert_de_tokens_error,
};
#[macro_use]
mod macros;
//////////////////////////////////////////////////////////////////////////
#[derive(Copy, Clone, PartialEq, Debug, Deserialize)]
@@ -40,6 +49,22 @@ struct StructDenyUnknown {
b: i32,
}
#[derive(PartialEq, Debug, Deserialize)]
#[serde(default)]
struct StructDefault<T> {
a: i32,
b: T,
}
impl Default for StructDefault<String> {
fn default() -> Self {
StructDefault {
a: 100,
b: "default".to_string(),
}
}
}
#[derive(PartialEq, Debug, Deserialize)]
struct StructSkipAll {
#[serde(skip_deserializing)]
@@ -97,7 +122,7 @@ macro_rules! declare_tests {
}
macro_rules! declare_error_tests {
($($name:ident<$target:ident> { $tokens:expr, $expected:expr, })+) => {
($($name:ident<$target:ty> { $tokens:expr, $expected:expr, })+) => {
$(
#[test]
fn $name() {
@@ -225,7 +250,7 @@ declare_tests! {
],
() => &[
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
Token::TupleStructEnd,
],
}
test_unit_struct {
@@ -330,7 +355,7 @@ declare_tests! {
],
BTreeSet::<isize>::new() => &[
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
Token::TupleStructEnd,
],
}
test_hashset {
@@ -358,7 +383,7 @@ declare_tests! {
],
HashSet::<isize>::new() => &[
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
Token::TupleStructEnd,
],
hashset![FnvHasher @ 1, 2, 3] => &[
Token::SeqStart(Some(3)),
@@ -408,7 +433,7 @@ declare_tests! {
],
Vec::<isize>::new() => &[
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
Token::TupleStructEnd,
],
}
test_array {
@@ -472,7 +497,7 @@ declare_tests! {
],
[0; 0] => &[
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
Token::TupleStructEnd,
],
}
test_tuple {
@@ -564,7 +589,7 @@ declare_tests! {
],
BTreeMap::<isize, isize>::new() => &[
Token::StructStart("Anything", 0),
Token::MapEnd,
Token::StructEnd,
],
}
test_hashmap {
@@ -618,7 +643,7 @@ declare_tests! {
],
HashMap::<isize, isize>::new() => &[
Token::StructStart("Anything", 0),
Token::MapEnd,
Token::StructEnd,
],
hashmap![FnvHasher @ 1 => 2, 3 => 4] => &[
Token::MapStart(Some(2)),
@@ -728,6 +753,23 @@ declare_tests! {
Token::StructEnd,
],
}
test_struct_default {
StructDefault { a: 50, b: "overwritten".to_string() } => &[
Token::StructStart("StructDefault", 1),
Token::StructSep,
Token::Str("a"),
Token::I32(50),
Token::StructSep,
Token::Str("b"),
Token::String("overwritten".to_string()),
Token::StructEnd,
],
StructDefault { a: 100, b: "default".to_string() } => &[
Token::StructStart("StructDefault", 0),
Token::StructEnd,
],
}
test_enum_unit {
Enum::Unit => &[
Token::EnumUnit("Enum", "Unit"),
@@ -837,6 +879,11 @@ declare_tests! {
Token::String("/usr/local/lib".to_owned()),
],
}
test_cstring {
CString::new("abc").unwrap() => &[
Token::Bytes(b"abc"),
],
}
}
#[cfg(feature = "unstable")]
@@ -936,4 +983,34 @@ declare_error_tests! {
],
Error::Message("invalid value: integer `4`, expected variant index 0 <= i < 4".into()),
}
test_short_tuple<(u8, u8, u8)> {
&[
Token::TupleStart(1),
Token::TupleSep,
Token::U8(1),
Token::TupleEnd,
],
Error::Message("invalid length 1, expected a tuple of size 3".into()),
}
test_short_array<[u8; 3]> {
&[
Token::SeqStart(Some(1)),
Token::SeqSep,
Token::U8(1),
Token::SeqEnd,
],
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()),
}
}
@@ -2,17 +2,26 @@
// successfully when there are a variety of generics and non-(de)serializable
// types involved.
#![cfg_attr(feature = "unstable-testing", 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};
use std::borrow::Cow;
use std::marker::PhantomData;
use std::result::Result as StdResult;
// Try to trip up the generated code if it fails to use fully qualified paths.
#[allow(dead_code)]
struct Result;
use std::result::Result as StdResult;
#[allow(dead_code)]
struct Ok;
#[allow(dead_code)]
struct Err;
//////////////////////////////////////////////////////////////////////////
@@ -26,6 +35,14 @@ fn test_gen() {
}
assert::<With<i32>>();
#[derive(Serialize, Deserialize)]
struct WithTogether<T> {
t: T,
#[serde(with="both_x")]
x: X,
}
assert::<WithTogether<i32>>();
#[derive(Serialize, Deserialize)]
struct WithRef<'a, T: 'a> {
#[serde(skip_deserializing)]
@@ -303,16 +320,20 @@ trait DeserializeWith: Sized {
}
// Implements neither Serialize nor Deserialize
struct X;
pub struct X;
fn ser_x<S: Serializer>(_: &X, _: S) -> StdResult<S::Ok, S::Error> {
pub fn ser_x<S: Serializer>(_: &X, _: S) -> StdResult<S::Ok, S::Error> {
unimplemented!()
}
fn de_x<D: Deserializer>(_: D) -> StdResult<X, D::Error> {
pub fn de_x<D: Deserializer>(_: D) -> StdResult<X, D::Error> {
unimplemented!()
}
mod both_x {
pub use super::{ser_x as serialize, de_x as deserialize};
}
impl SerializeWith for X {
fn serialize_with<S: Serializer>(_: &Self, _: S) -> StdResult<S::Ok, S::Error> {
unimplemented!()
File diff suppressed because it is too large Load Diff
@@ -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::{
@@ -18,6 +24,9 @@ use self::fnv::FnvHasher;
#[cfg(feature = "unstable")]
use serde::ser::iterator;
#[macro_use]
mod macros;
//////////////////////////////////////////////////////////////////////////
#[derive(Serialize)]
@@ -51,7 +60,20 @@ enum Enum {
//////////////////////////////////////////////////////////////////////////
declare_ser_tests! {
macro_rules! declare_tests {
($($name:ident { $($value:expr => $tokens:expr,)+ })+) => {
$(
#[test]
fn $name() {
$(
assert_ser_tokens(&$value, $tokens);
)+
}
)+
}
}
declare_tests! {
test_unit {
() => &[Token::Unit],
}
@@ -368,6 +390,16 @@ declare_ser_tests! {
Token::Str("/usr/local/lib"),
],
}
test_cstring {
CString::new("abc").unwrap() => &[
Token::Bytes(b"abc"),
],
}
test_cstr {
(&*CString::new("abc").unwrap()) => &[
Token::Bytes(b"abc"),
],
}
}
-32
View File
@@ -1,32 +0,0 @@
[package]
name = "serde_testing"
version = "0.0.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde/"
readme = "README.md"
keywords = ["serialization"]
build = "build.rs"
publish = false
[features]
unstable-testing = ["clippy", "serde/unstable-testing", "serde_codegen/unstable-testing"]
[build-dependencies]
serde_codegen = { path = "../serde_codegen", features = ["with-syntex"] }
[dev-dependencies]
fnv = "1.0"
rustc-serialize = "0.3.16"
serde = { path = "../serde" }
serde_test = { path = "../serde_test" }
[dependencies]
clippy = { version = "0.*", optional = true }
[[test]]
name = "test"
path = "tests/test.rs"
-11
View File
@@ -1,11 +0,0 @@
extern crate serde_codegen;
use std::env;
use std::path::Path;
fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let src = Path::new("tests/test.rs.in");
let dst = Path::new(&out_dir).join("test.rs");
serde_codegen::expand(&src, &dst).unwrap();
}
-6
View File
@@ -1,6 +0,0 @@
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "unstable-testing", feature(non_ascii_idents))]
include!(concat!(env!("OUT_DIR"), "/test.rs"));
-12
View File
@@ -1,12 +0,0 @@
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;
-627
View File
@@ -1,627 +0,0 @@
extern crate serde_test;
use self::serde_test::{
Token,
assert_tokens,
assert_ser_tokens,
assert_de_tokens,
};
use std::marker::PhantomData;
// That tests that the derived Serialize implementation doesn't trigger
// any warning about `serializer` not being used, in case of empty enums.
#[derive(Serialize)]
#[allow(dead_code)]
#[deny(unused_variables)]
enum Void {}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct NamedUnit;
#[derive(Debug, PartialEq, Serialize)]
struct SerNamedTuple<'a, 'b, A: 'a, B: 'b, C>(&'a A, &'b mut B, C);
#[derive(Debug, PartialEq, Deserialize)]
struct DeNamedTuple<A, B, C>(A, B, C);
#[derive(Debug, PartialEq, Serialize)]
struct SerNamedMap<'a, 'b, A: 'a, B: 'b, C> {
a: &'a A,
b: &'b mut B,
c: C,
}
#[derive(Debug, PartialEq, Deserialize)]
struct DeNamedMap<A, B, C> {
a: A,
b: B,
c: C,
}
#[derive(Debug, PartialEq, Serialize)]
enum SerEnum<'a, B: 'a, C: 'a, D> where D: 'a {
Unit,
Seq(
i8,
B,
&'a C,
&'a mut D,
),
Map {
a: i8,
b: B,
c: &'a C,
d: &'a mut D,
},
// Make sure we can support more than one variant.
_Unit2,
_Seq2(
i8,
B,
&'a C,
&'a mut D,
),
_Map2 {
a: i8,
b: B,
c: &'a C,
d: &'a mut D,
},
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum DeEnum<B, C, D> {
Unit,
Seq(
i8,
B,
C,
D,
),
Map {
a: i8,
b: B,
c: C,
d: D,
},
// Make sure we can support more than one variant.
_Unit2,
_Seq2(
i8,
B,
C,
D,
),
_Map2 {
a: i8,
b: B,
c: C,
d: D,
},
}
#[derive(Serialize)]
enum Lifetimes<'a> {
LifetimeSeq(&'a i32),
NoLifetimeSeq(i32),
LifetimeMap { a: &'a i32 },
NoLifetimeMap { a: i32 },
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct GenericStruct<T> {
x: T,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct GenericNewTypeStruct<T>(T);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct GenericTupleStruct<T, U>(T, U);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub enum GenericEnum<T, U> {
Unit,
NewType(T),
Seq(T, U),
Map { x: T, y: U },
}
trait AssociatedType {
type X;
}
impl AssociatedType for i32 {
type X = i32;
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct DefaultTyParam<T: AssociatedType<X=i32> = i32> {
phantom: PhantomData<T>
}
#[test]
fn test_named_unit() {
assert_tokens(
&NamedUnit,
&[Token::UnitStruct("NamedUnit")]
);
}
#[test]
fn test_ser_named_tuple() {
let a = 5;
let mut b = 6;
let c = 7;
assert_ser_tokens(
&SerNamedTuple(&a, &mut b, c),
&[
Token::TupleStructStart("SerNamedTuple", 3),
Token::TupleStructSep,
Token::I32(5),
Token::TupleStructSep,
Token::I32(6),
Token::TupleStructSep,
Token::I32(7),
Token::TupleStructEnd,
],
);
}
#[test]
fn test_de_named_tuple() {
assert_de_tokens(
&DeNamedTuple(5, 6, 7),
&[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(5),
Token::SeqSep,
Token::I32(6),
Token::SeqSep,
Token::I32(7),
Token::SeqEnd,
]
);
assert_de_tokens(
&DeNamedTuple(5, 6, 7),
&[
Token::TupleStructStart("DeNamedTuple", 3),
Token::TupleStructSep,
Token::I32(5),
Token::TupleStructSep,
Token::I32(6),
Token::TupleStructSep,
Token::I32(7),
Token::TupleStructEnd,
]
);
}
#[test]
fn test_ser_named_map() {
let a = 5;
let mut b = 6;
let c = 7;
assert_ser_tokens(
&SerNamedMap {
a: &a,
b: &mut b,
c: c,
},
&[
Token::StructStart("SerNamedMap", 3),
Token::StructSep,
Token::Str("a"),
Token::I32(5),
Token::StructSep,
Token::Str("b"),
Token::I32(6),
Token::StructSep,
Token::Str("c"),
Token::I32(7),
Token::StructEnd,
]
);
}
#[test]
fn test_de_named_map() {
assert_de_tokens(
&DeNamedMap {
a: 5,
b: 6,
c: 7,
},
&[
Token::StructStart("DeNamedMap", 3),
Token::StructSep,
Token::Str("a"),
Token::I32(5),
Token::StructSep,
Token::Str("b"),
Token::I32(6),
Token::StructSep,
Token::Str("c"),
Token::I32(7),
Token::StructEnd,
]
);
}
#[test]
fn test_ser_enum_unit() {
assert_ser_tokens(
&SerEnum::Unit::<u32, u32, u32>,
&[
Token::EnumUnit("SerEnum", "Unit"),
]
);
}
#[test]
fn test_ser_enum_seq() {
let a = 1;
let b = 2;
let c = 3;
let mut d = 4;
assert_ser_tokens(
&SerEnum::Seq(
a,
b,
&c,
&mut d,
),
&[
Token::EnumSeqStart("SerEnum", "Seq", 4),
Token::EnumSeqSep,
Token::I8(1),
Token::EnumSeqSep,
Token::I32(2),
Token::EnumSeqSep,
Token::I32(3),
Token::EnumSeqSep,
Token::I32(4),
Token::EnumSeqEnd,
],
);
}
#[test]
fn test_ser_enum_map() {
let a = 1;
let b = 2;
let c = 3;
let mut d = 4;
assert_ser_tokens(
&SerEnum::Map {
a: a,
b: b,
c: &c,
d: &mut d,
},
&[
Token::EnumMapStart("SerEnum", "Map", 4),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::EnumMapSep,
Token::Str("b"),
Token::I32(2),
Token::EnumMapSep,
Token::Str("c"),
Token::I32(3),
Token::EnumMapSep,
Token::Str("d"),
Token::I32(4),
Token::EnumMapEnd,
],
);
}
#[test]
fn test_de_enum_unit() {
assert_tokens(
&DeEnum::Unit::<u32, u32, u32>,
&[
Token::EnumUnit("DeEnum", "Unit"),
],
);
}
#[test]
fn test_de_enum_seq() {
let a = 1;
let b = 2;
let c = 3;
let d = 4;
assert_tokens(
&DeEnum::Seq(
a,
b,
c,
d,
),
&[
Token::EnumSeqStart("DeEnum", "Seq", 4),
Token::EnumSeqSep,
Token::I8(1),
Token::EnumSeqSep,
Token::I32(2),
Token::EnumSeqSep,
Token::I32(3),
Token::EnumSeqSep,
Token::I32(4),
Token::EnumSeqEnd,
],
);
}
#[test]
fn test_de_enum_map() {
let a = 1;
let b = 2;
let c = 3;
let d = 4;
assert_tokens(
&DeEnum::Map {
a: a,
b: b,
c: c,
d: d,
},
&[
Token::EnumMapStart("DeEnum", "Map", 4),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::EnumMapSep,
Token::Str("b"),
Token::I32(2),
Token::EnumMapSep,
Token::Str("c"),
Token::I32(3),
Token::EnumMapSep,
Token::Str("d"),
Token::I32(4),
Token::EnumMapEnd,
],
);
}
#[test]
fn test_lifetimes() {
let value = 5;
assert_ser_tokens(
&Lifetimes::LifetimeSeq(&value),
&[
Token::EnumNewType("Lifetimes", "LifetimeSeq"),
Token::I32(5),
]
);
assert_ser_tokens(
&Lifetimes::NoLifetimeSeq(5),
&[
Token::EnumNewType("Lifetimes", "NoLifetimeSeq"),
Token::I32(5),
]
);
assert_ser_tokens(
&Lifetimes::LifetimeMap { a: &value },
&[
Token::EnumMapStart("Lifetimes", "LifetimeMap", 1),
Token::EnumMapSep,
Token::Str("a"),
Token::I32(5),
Token::EnumMapEnd,
]
);
assert_ser_tokens(
&Lifetimes::NoLifetimeMap { a: 5 },
&[
Token::EnumMapStart("Lifetimes", "NoLifetimeMap", 1),
Token::EnumMapSep,
Token::Str("a"),
Token::I32(5),
Token::EnumMapEnd,
]
);
}
#[test]
fn test_generic_struct() {
assert_tokens(
&GenericStruct { x: 5u32 },
&[
Token::StructStart("GenericStruct", 1),
Token::StructSep,
Token::Str("x"),
Token::U32(5),
Token::StructEnd,
]
);
}
#[test]
fn test_generic_newtype_struct() {
assert_tokens(
&GenericNewTypeStruct(5u32),
&[
Token::StructNewType("GenericNewTypeStruct"),
Token::U32(5),
]
);
}
#[test]
fn test_generic_tuple_struct() {
assert_tokens(
&GenericTupleStruct(5u32, 6u32),
&[
Token::TupleStructStart("GenericTupleStruct", 2),
Token::TupleStructSep,
Token::U32(5),
Token::TupleStructSep,
Token::U32(6),
Token::TupleStructEnd,
]
);
}
#[test]
fn test_generic_enum_unit() {
assert_tokens(
&GenericEnum::Unit::<u32, u32>,
&[
Token::EnumUnit("GenericEnum", "Unit"),
]
);
}
#[test]
fn test_generic_enum_newtype() {
assert_tokens(
&GenericEnum::NewType::<u32, u32>(5),
&[
Token::EnumNewType("GenericEnum", "NewType"),
Token::U32(5),
]
);
}
#[test]
fn test_generic_enum_seq() {
assert_tokens(
&GenericEnum::Seq::<u32, u32>(5, 6),
&[
Token::EnumSeqStart("GenericEnum", "Seq", 2),
Token::EnumSeqSep,
Token::U32(5),
Token::EnumSeqSep,
Token::U32(6),
Token::EnumSeqEnd,
]
);
}
#[test]
fn test_generic_enum_map() {
assert_tokens(
&GenericEnum::Map::<u32, u32> { x: 5, y: 6 },
&[
Token::EnumMapStart("GenericEnum", "Map", 2),
Token::EnumMapSep,
Token::Str("x"),
Token::U32(5),
Token::EnumMapSep,
Token::Str("y"),
Token::U32(6),
Token::EnumMapEnd,
]
);
}
#[test]
fn test_default_ty_param() {
assert_tokens(
&DefaultTyParam::<i32> { phantom: PhantomData },
&[
Token::StructStart("DefaultTyParam", 1),
Token::StructSep,
Token::Str("phantom"),
Token::UnitStruct("PhantomData"),
Token::StructEnd,
]
);
}
#[test]
fn test_enum_state_field() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum SomeEnum {
Key { key: char, state: bool },
}
assert_tokens(
&SomeEnum::Key { key: 'a', state: true },
&[
Token::EnumMapStart("SomeEnum", "Key", 2),
Token::EnumMapSep,
Token::Str("key"),
Token::Char('a'),
Token::EnumMapSep,
Token::Str("state"),
Token::Bool(true),
Token::EnumMapEnd,
]
);
}

Some files were not shown because too many files have changed in this diff Show More