Compare commits

...

369 Commits

Author SHA1 Message Date
David Tolnay 78e74886be Update syntex to 0.39 2016-07-26 09:22:33 -07:00
David Tolnay ed603d4580 Merge pull request #442 from serde-rs/override
Use cargo override instead of relative paths
2016-07-15 01:56:14 -07:00
David Tolnay 7220029055 Use cargo override instead of relative paths
This makes it possible to use `cargo clone` + `cargo build`.
2016-07-15 01:17:23 -07:00
David Tolnay 35676305da Merge pull request #401 from erickt/contributing
Add a contribution guide
2016-07-15 01:06:54 -07:00
David Tolnay 4ec0a7e672 Merge pull request #433 from softprops/add_envy
add envy
2016-07-10 20:59:50 -07:00
softprops a41dae45a5 add envy 2016-07-10 23:55:32 -04:00
David Tolnay cb9e1cfb54 Merge pull request #431 from serde-rs/version
Drop support for 1.7.0
2016-07-10 14:40:15 -07:00
David Tolnay 54ce7f2e90 Drop support for 1.7.0 2016-07-10 14:25:17 -07:00
David Tolnay ddbd139793 Merge pull request #430 from serde-rs/bump
Update syntex to 0.38
2016-07-09 11:51:38 -07:00
David Tolnay a070de28e2 Update syntex to 0.38 2016-07-09 11:37:01 -07:00
David Tolnay 57aeb26728 Merge pull request #428 from erickt/readme
Rewrite readme to front-load stable rust usage
2016-07-07 20:26:00 -07:00
Erick Tryzelaar a592828808 Rewrite readme to front-load stable rust usage 2016-07-07 14:31:24 -07:00
David Tolnay 67d86dcc4f Merge pull request #426 from serde-rs/display
impl Display for de::Type
2016-07-07 00:59:17 -07:00
David Tolnay 15764cb955 impl Display for de::Type 2016-07-06 23:33:59 -07:00
David Tolnay 97bc1e08e7 Release 0.7.13 2016-07-05 20:06:10 -07:00
Oliver Schneider 7ffb74f5bb Merge pull request #423 from dtolnay/seq
Close the seq before failing on invalid length
2016-07-05 22:44:52 +02:00
David Tolnay f25e6d3ea9 Close the seq before failing on invalid length
Equivalent to what 0f9a930 does for maps.
2016-07-05 10:08:36 -07:00
David Tolnay 431cbe48b7 Merge pull request #422 from serde-rs/missing
Close the map before checking for missing fields
2016-07-05 07:11:03 -07:00
Homu 5405ab319d Auto merge of #421 - serde-rs:length, r=oli-obk
Invalid-length when enum seq is too short

Fixes https://github.com/serde-rs/json/issues/96.
2016-07-05 18:27:33 +09:00
David Tolnay 0f9a930c4f Close the map before checking for missing fields 2016-07-05 01:42:38 -07:00
David Tolnay 1a449bb3d0 Invalid-length when enum seq is too short 2016-07-05 01:35:20 -07:00
David Tolnay c0e8164792 Merge pull request #418 from serde-rs/expninfo
Record expansion info
2016-07-04 15:22:09 -07:00
David Tolnay a3a7e4085f Add run-pass test for expansion info 2016-07-04 15:02:15 -07:00
David Tolnay 149c87d7c2 Record expansion info 2016-07-03 10:53:33 -07:00
David Tolnay 5deba439c3 Merge pull request #417 from serde-rs/bump
Update syntex to 0.37
2016-07-03 08:53:56 -07:00
David Tolnay d450de1482 Update syntex to 0.37 2016-07-02 20:20:44 -07:00
David Tolnay 47c7387279 Merge pull request #416 from dtolnay/filter
Remove filter no longer necessary for rustc >=1.7
2016-07-01 22:53:45 -07:00
David Tolnay dc8d209f29 Remove filter no longer necessary for rustc >=1.7 2016-07-01 22:34:15 -07:00
David Tolnay 831802adc8 Merge pull request #407 from dtolnay/internals
Rename serde_item to serde_codegen_internals
2016-06-30 20:06:12 -07:00
David Tolnay 2d5a26dfc0 Rename serde_internals to serde_codegen_internals 2016-06-30 19:53:57 -07:00
David Tolnay c6b6e2a5d9 Rename serde_item to serde_internals 2016-06-30 19:42:55 -07:00
Oliver Schneider d1be5ef187 Merge pull request #412 from dtolnay/test
Move Token De/Serializer to serde_test crate
2016-06-29 10:05:36 +02:00
David Tolnay f531be1524 Turn comments into doc comments 2016-06-29 00:58:33 -07:00
David Tolnay 10b1508d4a Sync serde_test version with the other crates 2016-06-29 00:17:50 -07:00
David Tolnay 041d5c0842 Make serde_test asserts more consistent 2016-06-28 23:50:19 -07:00
David Tolnay 7d09053bb8 Fix declare_ser_tests to work on old rustc 2016-06-28 23:09:37 -07:00
David Tolnay 8e87926bc2 Round out the Error variants 2016-06-28 22:57:53 -07:00
David Tolnay d6a462b862 Add serde_test to dev dependencies of serde_macros 2016-06-28 22:50:58 -07:00
David Tolnay cfc2f9adc0 Remove Error from name of Error variants 2016-06-28 22:49:13 -07:00
David Tolnay 00f94290a6 Add message to CustomError 2016-06-28 22:36:29 -07:00
David Tolnay 093201abfb Assert tokens are empty after reaching error 2016-06-28 22:23:38 -07:00
David Tolnay 6d64104375 Factor the Token De/Serializer into serde_test 2016-06-28 21:54:51 -07:00
David Tolnay fb0e62951f Rename serde_tests to testing 2016-06-28 20:43:59 -07:00
David Tolnay 6ab508a93c Release 0.7.11 2016-06-23 19:58:31 -07:00
David Tolnay 9f38c2ab59 Merge pull request #409 from knsd/patch-1
Fix typo
2016-06-23 09:52:50 -07:00
Fedor Gogolev 021ce5be88 Fix typo 2016-06-23 20:50:27 +04:00
Homu f1f8b4622b Auto merge of #402 - erickt:clippy, r=erickt
Update link to clippy lint report
2016-06-23 12:52:36 +09:00
Erick Tryzelaar 1fb2172a25 Merge pull request #405 from erickt/rustup
Version bump the syntex stack
2016-06-22 20:34:15 -07:00
Erick Tryzelaar 5941f1d071 Version bump the syntex stack 2016-06-22 20:19:47 -07:00
Erick Tryzelaar 8d6cc4dfa5 Update link to clippy lint report 2016-06-22 10:13:28 -07:00
Erick Tryzelaar 18e077eda9 Add a contributing guide 2016-06-22 07:04:13 -07:00
Homu c9e2e518ba Auto merge of #397 - dtolnay:item, r=oli-obk
Factor attr parsing into serde_item crate

Fixes #396. @KodrAus [let me know whether this fits the bill.](https://github.com/dtolnay/serde/tree/5c6a0e12e95974e3c131386e8e0528b6b9cfa6fa/serde_item/src)

a few other changes to make the API a little more presentable:

- Rename attr::{ContainerAttrs,VariantAttrs,FieldAttrs} to remove the "Attrs" (I see you worked on the corresponding [clippy lint](https://github.com/Manishearth/rust-clippy/issues/904)).
- Rename attr::Container* to attr::Item to correspond with item::Item and ast::Item. The others already had a correspondence (attr::Variant/item::Variant/ast::Variant, attr::Field/item::Field/ast::Field). Also a unit struct isn't much of a "container."
- Change item::Item::from_ast to return a meaningful error enum instead of printing a message that was hard to generalize to other uses.
- Add item::Variant.span for consistency because Item and Field already had span.
- Remove the "ident" field from attr::Name because we can just fold it into the other two fields.
- Remove attr::Name::(de)serialize_name_expr because it wasn't using the right AstBuilder in the first place.
- Rename the attr:: constructors from_item/from_variant/from_field to from_ast to line up with the item:: constructors; the signatures match.
- Remove attr's dependency on aster because we were only using it for two very simple things.
2016-06-20 16:45:25 +09:00
David Tolnay 51042bde50 Remove ident from Name struct 2016-06-19 20:31:12 -07:00
David Tolnay 5c6a0e12e9 Factor attr parsing into serde_item crate 2016-06-19 20:15:49 -07:00
Homu d4e1ef659a Auto merge of #389 - dtolnay:rule, r=oli-obk
Remove unused macro rule
2016-06-17 16:52:37 +09:00
David Tolnay f5f35677f0 Remove unused macro rule 2016-06-17 00:06:11 -07:00
David Tolnay 90d9c77186 Merge pull request #385 from dtolnay/dup
Error on duplicate attributes
2016-06-17 00:02:04 -07:00
David Tolnay 882d130e19 Test duplicates within a single attribute 2016-06-16 23:45:34 -07:00
David Tolnay 5f84e601b6 Add explanation of ignored errors in attr.rs 2016-06-16 23:25:46 -07:00
David Tolnay 0bf6a17428 Merge pull request #387 from erickt/master
Extend tuple impls up to 16 elements
2016-06-16 09:47:58 -07:00
Erick Tryzelaar db8881d845 Extend tuple impls up to 16 elements 2016-06-16 11:22:15 +01:00
David Tolnay 3403352749 Merge pull request #377 from dtolnay/travis
Remove some low-risk travis builds
2016-06-15 08:54:04 -07:00
David Tolnay ac69524258 Gather attrs at the beginning 2016-06-15 02:38:47 -07:00
David Tolnay 28589620f6 Error on duplicate attributes 2016-06-14 20:39:21 -07:00
David Tolnay 8e4da7f36b Merge pull request #383 from oli-obk/compile-fail
more cfail tests
2016-06-13 10:46:35 -07:00
Oliver Schneider 4c4a27f53c more cfail tests 2016-06-13 18:56:45 +02:00
Homu b838651ac9 Auto merge of #378 - dtolnay:str, r=oli-obk
Better error when deriving Deserialize for struct containing &str

Fixes #360. The error looks like this:

```rust
#[derive(Serialize, Deserialize)]
struct Test<'a> {
    s: &'a str,
}
```

```
src/main.rs:6:5: 6:15 error: Serde does not support deserializing fields of type &str; consider using String instead
src/main.rs:6     s: &'a str,
                  ^~~~~~~~~~
```
2016-06-14 00:49:26 +09:00
David Tolnay 5cd8212a61 Merge pull request #381 from dtolnay/nosyntex
Remove unnecessary Syntexes
2016-06-12 22:25:50 -07:00
David Tolnay c5f606f10f Remove unnecessary Syntexes 2016-06-12 15:50:45 -07:00
David Tolnay c21bea8b30 Better error when deriving Deserialize for struct containing &str 2016-06-11 21:32:53 -07:00
David Tolnay 22a26a33f4 Remove some low-risk travis builds 2016-06-11 16:21:20 -07:00
David Tolnay 8a09f05644 Release 0.7.10 2016-06-11 13:08:33 -07:00
David Tolnay 5923a0cd2f Merge pull request #371 from dtolnay/hasher
De/serialize for HashMap<K, V, S> and HashSet<T, S>
2016-06-11 11:51:57 -07:00
David Tolnay 1576b5a8a0 Serde_macros tests depend on fnv 2016-06-11 11:15:10 -07:00
Homu 2c4dbf5a84 Auto merge of #370 - dtolnay:expand, r=erickt
Use serde_codegen::expand in serde_tests/build.rs
2016-06-12 02:51:08 +09:00
David Tolnay 021f4f2d70 Use serde_codegen::expand in serde_tests/build.rs 2016-06-11 10:02:10 -07:00
David Tolnay decc571988 De/serialize for HashSet<T, S> 2016-06-11 10:00:33 -07:00
David Tolnay 322d7a90db Add ser tests for normal HashMap 2016-06-11 10:00:33 -07:00
David Tolnay dd3f653103 Move bounds to where-clause to increase legibility 2016-06-11 10:00:33 -07:00
David Tolnay 46a1860601 De/serialize for HashMap<K, V, S> 2016-06-11 10:00:33 -07:00
Homu 84a573c926 Auto merge of #372 - dtolnay:old, r=erickt
Stop building on 1.5.0

Syntex no longer supports this version of Rust.
2016-06-12 01:09:49 +09:00
Erick Tryzelaar 7dfa8f43f4 Merge pull request #373 from erickt/master
Updating to rustc 1.11.0-nightly (7d2f75a95 2016-06-09)
2016-06-11 09:09:22 -07:00
David Tolnay 7375b4e847 Add travis builds for 1.6.0 and 1.7.0 2016-06-11 08:59:02 -07:00
Erick Tryzelaar 48da62ed07 Updating to rustc 1.11.0-nightly (7d2f75a95 2016-06-09) 2016-06-11 08:19:51 -07:00
David Tolnay 9834af7ed9 Stop building on 1.5.0
Syntex no longer supports this version of Rust.
2016-06-11 01:31:17 -07:00
Homu 6b404d8529 Auto merge of #367 - dtolnay:default, r=oli-obk
Simplify implementation of #[serde(default=...)]
2016-06-10 17:57:39 +09:00
David Tolnay 3119cc8857 Simplify implementation of #[serde(default=...)] 2016-06-09 23:21:42 -07:00
David Tolnay bb059b97c0 Release 0.7.9 2016-06-09 20:16:49 -07:00
Homu b7188f7022 Auto merge of #362 - dtolnay:expand, r=oli-obk
Add serde_codegen::expand to avoid public Syntex dependency

Required for #358. We can remove `serde_codegen::register` in the next breaking release.

This allows Syntex users to avoid being broken by Serde bumping its Syntex dependency.
2016-06-10 07:46:33 +09:00
David Tolnay a64fe99d1b Add cargo override for building examples 2016-06-09 11:23:43 -07:00
David Tolnay c716c4e261 Use AsRef to accept paths in serde_codegen::expand 2016-06-09 11:23:43 -07:00
David Tolnay 3d2e3beafe Add serde_codegen::expand to avoid public Syntex dependency 2016-06-09 11:23:43 -07:00
Homu 1917e54a6e Auto merge of #363 - dtolnay:example, r=oli-obk
Fix nightly check in serde-syntex-example

Fixes #361.
2016-06-10 01:58:51 +09:00
David Tolnay 898b346d48 1.5 does not have a stable libcore 2016-06-09 09:17:21 -07:00
David Tolnay e90adb20ef Run serde-syntex-example in Travis 2016-06-09 01:42:00 -07:00
Homu a52e7f5554 Auto merge of #364 - dtolnay:rustup, r=oli-obk
Use rustup in serde-syntex-example instead of multirust

Multirust is deprecated.
2016-06-09 17:36:01 +09:00
David Tolnay 7afb8b52ae Use rustup in serde-syntex-example instead of multirust 2016-06-09 01:16:31 -07:00
David Tolnay cb4694387e Fix nightly check in serde-syntex-example 2016-06-09 01:08:12 -07:00
David Tolnay 58fa302007 Release 0.7.8 2016-06-06 10:13:52 -07:00
Homu bf33daf124 Auto merge of #354 - dtolnay:attr, r=oli-obk
Fix attributes canceling each other

Fixes #353.
2016-06-06 18:08:20 +09:00
Homu 4b472be56e Auto merge of #352 - dtolnay:where, r=oli-obk
Attribute for handwritten where clauses

Addresses (2) and (3) in https://github.com/serde-rs/serde/issues/336#issuecomment-220378916.

- If there is a `#[serde(bound="...")]` attribute on the type, use the union of that and the actual type's `where` clause as the `where` clause for the impl and do not attempt to generate any additional `where` clauses whatsoever.
- If there is a `#[serde(bound="...")]` attribute on a field, use that and do not attempt to generate any additional `where` clauses for the field.

The `bound` attribute behaves similar to `rename` in that you can specify a single attribute that applies to both ser and de, or individual ones.

```
#[serde(bound="D: Serialize + Deserialize")]

#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]
```

EDIT: now addresses (4) from https://github.com/serde-rs/serde/issues/336#issuecomment-220378916 as well.

- If a field contains direct recursion, do not generate any bounds based on that field except from `bound` attributes.
2016-06-06 17:47:45 +09:00
David Tolnay bdffaf3ea1 Re-enable clippy lint "useless_let_if_seq"
This reverts commit 4e6cd2d63f.
2016-06-05 13:01:22 -07:00
David Tolnay f197c3ce96 Readme for "bound" attribute 2016-06-05 11:54:36 -07:00
David Tolnay 01dfad6705 Fix attributes canceling each other 2016-06-05 11:40:30 -07:00
David Tolnay 2e06786262 Remove unnecessary clones 2016-06-05 11:23:01 -07:00
David Tolnay 578f34ecaf Use "bound" attribute instead of "where" 2016-06-05 11:17:43 -07:00
David Tolnay 2c8767cb46 Remove changelog in favor of github release notes 2016-06-05 10:05:56 -07:00
David Tolnay 45c51d3198 Fix build on 1.5.0 which does not have Vec::as_slice 2016-06-04 16:53:45 -07:00
David Tolnay bd40830905 Do not generate bounds from recursive types 2016-06-04 16:12:01 -07:00
David Tolnay 4e6cd2d63f Disable clippy lint "useless_let_if_seq" 2016-06-04 15:48:44 -07:00
David Tolnay 2256a04926 Address clippy lint "ptr_arg" 2016-06-04 15:48:44 -07:00
David Tolnay 660ea7bd7b Attribute for handwritten where clauses 2016-06-04 15:48:42 -07:00
Homu 7052833512 Auto merge of #351 - oli-obk:publish_nits, r=oli-obk
also publish the `.in` file used by the build script
2016-06-02 01:47:39 +09:00
Oliver Schneider 5c2cf5778f also publish the .in file used by the build script 2016-06-01 13:09:43 +02:00
Homu b5c0406afe Auto merge of #349 - oli-obk:undo, r=oli-obk
undo the breaking change introduced in 0.7.6

I should probably yank 0.7.6, too

cc @alexcrichton this should unbreak your setup, sorry about that.
2016-06-01 20:01:53 +09:00
Oliver Schneider 96cd910c92 undo the breaking change introduced in 0.7.6 2016-06-01 11:08:59 +02:00
Homu e0bd57d63c Auto merge of #347 - erickt:master, r=erickt
Add "include" to Cargo.toml files

This filters out junk files from the crates.

Closes #331.
2016-05-30 23:23:57 +09:00
Erick Tryzelaar 7c784f592e Add a changelog 2016-05-30 07:23:18 -07:00
Erick Tryzelaar 2c69ccdca4 Add the build script to the Cargo include section 2016-05-30 07:23:09 -07:00
Erick Tryzelaar 66eddd4d9b Add "include" to Cargo.toml files
This filters out junk files from the crates.

Closes #331.
2016-05-30 07:00:13 -07:00
Homu 1485f0a448 Auto merge of #346 - serde-rs:rustup, r=erickt
Rustup too rustc 1.11.0-nightly (7746a334d 2016-05-28)

cc @erickt
2016-05-30 22:45:47 +09:00
Manish Goregaokar 379c9e7148 Rustup too rustc 1.11.0-nightly (7746a334d 2016-05-28) 2016-05-30 14:01:57 +05:30
Homu 6c2af4da7a Auto merge of #343 - pyfisch:patch-1, r=oli-obk
Better documentation for de::Error::invalid_length

Closes #342
2016-05-24 20:32:57 +09:00
Pyfisch 2ff7d003ee Better documentation for de::Error::invalid_length
Closes #342
2016-05-24 13:07:26 +02:00
David Tolnay ea182e2561 Merge pull request #335 from dtolnay/tuples
Support (de)serialize_with in tuples
2016-05-23 13:33:58 -07:00
David Tolnay 938f42faf6 Support (de)serialize_with in tuples 2016-05-19 10:53:38 -07:00
Homu cc115ca43a Auto merge of #338 - dtolnay:refs, r=oli-obk
Strip more references

Fixes #337.
2016-05-20 02:45:31 +09:00
David Tolnay f1b4072444 Strip more references 2016-05-18 23:48:56 -07:00
Homu 16d3e96b77 Auto merge of #334 - dtolnay:dupl, r=oli-obk
Reduce code duplication in Deserialize generator

This combines `deserialize_newtype_struct`, `deserialize_tuple_struct`, and `deserialize_tuple_variant` into a single method `deserialize_tuple`, as well as `deserialize_struct` and `deserialize_struct_variant` into a single method `deserialize_struct`. No behavior changes.
2016-05-16 19:41:59 +09:00
David Tolnay 7d2423e856 Reduce code duplication in Deserialize generator
This combines deserialize_newtype_struct, deserialize_tuple_struct,
and deserialize_tuple_variant into a single method deserialize_tuple,
as well as deserialize_struct and deserialize_struct_variant into a
single method deserialize_struct. No behavior changes.
2016-05-15 13:32:54 -07:00
David Tolnay 9865ec23c7 Merge pull request #322 from dtolnay/unused
Remove unused imports and needless borrows
2016-05-13 11:23:15 -07:00
David Tolnay 76a321db5c Simplify redundant closure 2016-05-13 10:53:03 -07:00
David Tolnay 004dcaec3b Remove unused imports and needless borrows 2016-05-13 10:47:09 -07:00
Homu 74eb2f52b8 Auto merge of #316 - cmr:no_std, r=oli-obk
Enable use in no_std environments

Re-opening of #302 after bust merge.
2016-05-13 17:13:08 +09:00
Corey Richardson 9b7317fbb1 Address nits 2016-05-13 11:17:17 +10:00
Erick Tryzelaar 41142d41ee Merge pull request #319 from dtolnay/release
Release 0.7.5
2016-05-12 09:30:41 -07:00
Homu fd328c2f2a Auto merge of #320 - dtolnay:syntexv, r=oli-obk
Do not depend on multiple syntex versions

serde_codegen has syntex 0.32 under dependencies, but syntex 0.31 under build-dependencies...
2016-05-12 04:05:47 +09:00
David Tolnay 3ad276944a Do not depend on multiple syntex versions 2016-05-11 09:52:28 -07:00
David Tolnay bb20796e9d Bump version numbers in serde-syntex-example 2016-05-11 09:46:16 -07:00
David Tolnay 709ac64dfc Release 0.7.5 2016-05-11 09:36:30 -07:00
Homu a9a4b2d8e2 Auto merge of #293 - dtolnay:duplicate, r=oli-obk
feat(codegen): Detect repeated struct field when deserializing

Addresses #59. Let me know whether you think we need an escape hatch to opt out of this check.
2016-05-11 19:44:34 +09:00
Oliver Schneider 7374ac499d Merge pull request #311 from dtolnay/deserialize_with
Field with deserialize_with should not implement Deserialize
2016-05-11 11:48:19 +02:00
Oliver Schneider 6596f77e91 Merge pull request #315 from dtolnay/underscore
Prefix type parameters and lifetimes with double underscore
2016-05-11 11:06:25 +02:00
David Tolnay eeb4efc19c feat(codegen): Detect repeated struct field when deserializing 2016-05-10 09:52:51 -07:00
David Tolnay 76b70455ec Field with deserialize_with should not implement Deserialize 2016-05-10 09:50:32 -07:00
David Tolnay f43c8a6267 Prefix type parameters and lifetimes with double underscore 2016-05-10 09:12:38 -07:00
Corey Richardson ae806af644 Enable use in no_std environments
These changes are fairly invasive to imports and uses of non-libcore types,
but allow for some or none of the freestanding crates (core, rustc_unicode,
alloc, collections) to be supported by serde.
2016-05-10 10:23:41 +10:00
Homu 7aa0b6ce27 Auto merge of #314 - dtolnay:revert, r=erickt
Revert "Enable use in no_std environments"

This commit failed to build even before it was merged. See #313.
2016-05-09 12:47:09 +09:00
David Tolnay efdbf5795f Fix version in serde/Cargo.toml 2016-05-08 20:43:46 -07:00
David Tolnay 55355b6680 Revert "Enable use in no_std environments"
This reverts commit 9c0140968d.
2016-05-08 20:30:21 -07:00
Erick Tryzelaar f8a91e5176 Merge pull request #302 from cmr/no_std
Enable use in no_std environments
2016-05-08 19:24:48 -07:00
Erick Tryzelaar aa0cd9b3dc Merge pull request #308 from dtolnay/inference
Reduce dependence on type inference
2016-05-08 19:21:45 -07:00
Erick Tryzelaar 1f82cd6e3d Merge pull request #310 from dtolnay/withdoc
Clarify serialize_with and deserialize_with documentation
2016-05-08 19:20:12 -07:00
David Tolnay 3caac4e6f3 Clarify serialize_with and deserialize_with documentation 2016-05-08 10:52:23 -07:00
David Tolnay f4414bfc14 Reduce dependence on type inference 2016-05-07 15:25:13 -07:00
Erick Tryzelaar 8378267b9b Merge pull request #303 from antrik/rustup
Update for latest libsyntax changes
2016-05-03 22:07:38 -07:00
Corey Richardson 9c0140968d Enable use in no_std environments
These changes are fairly invasive to imports and uses of non-libcore types,
but allow for some or none of the freestanding crates (core, rustc_unicode,
alloc, collections) to be supported by serde.
2016-05-04 01:26:43 +10:00
Erick Tryzelaar 5716e8c508 Merge pull request #298 from dtolnay/scope
fix(codegen): Support `extern crate serde` not in toplevel module
2016-05-02 20:09:04 -07:00
Olaf Buddenhagen 0e9d45da60 Bump version to 0.7.4
Dependencies were updated in previous commit. (For supporting current
Nightly Rust.)

I guess this shouldn't affect our client interface -- which is why these
dependency bumps only get patch level version number updates for Serde,
I presume?
2016-05-02 07:26:16 +02:00
Olaf Buddenhagen 6e7a75c859 Adapt for parser::PathParsingMode interface change in libsyntax
This was renamed upstream in
https://github.com/rust-lang/rust/commit/6c44bea64435fd3859439a6ecab7758855a13f07

It's an incompatible change requiring new versions of syntex, aster, and
quasi.
2016-05-02 07:25:29 +02:00
Olaf Buddenhagen 0ff91e4451 Adapt for removal of old interfaces in libsyntax
https://github.com/rust-lang/rust/commit/9108fb7bae11f18715d971eeae1e5ca84662e1ee
dropped the `map()` method (among other things) -- so we need to adapt
our code.

This change should be backwards-compatible.
2016-05-02 07:08:43 +02:00
David Tolnay 305fab7c16 fix(codegen): Support extern crate serde not in toplevel module 2016-04-25 09:58:01 -07:00
Erick Tryzelaar a959073a81 Merge pull request #296 from erickt/master
Fix a warning, bump the versions
2016-04-25 07:58:23 -07:00
Erick Tryzelaar 2f0fc6e6f1 Merge pull request #295 from dtolnay/defaults
fix(codegen): Discard type defaults from impl generics
2016-04-25 07:58:03 -07:00
Erick Tryzelaar 7bd87feb62 Fix a warning, bump the versions 2016-04-19 12:43:57 -05:00
Erick Tryzelaar bff2301ac3 Document that skip_deserializing uses the default=... attribute if present 2016-04-19 12:35:16 -05:00
David Tolnay fd3c15fb68 fix(codegen): Discard type defaults from impl generics 2016-04-19 10:28:43 -07:00
Erick Tryzelaar 808b06940e Merge pull request #285 from dtolnay/bounds
feat(codegen): Infer Default and Deserialize bounds correctly
2016-04-19 12:25:13 -05:00
Erick Tryzelaar 8cce6ecf15 Merge pull request #290 from dtolnay/boxslice
fix(impls): Deserialize impl for Box<[T]>
2016-04-19 12:21:11 -05:00
Erick Tryzelaar ef97f87b96 Merge pull request #291 from dtolnay/docskip
Fix documentation of skip_serializing_if
2016-04-19 12:20:45 -05:00
David Tolnay 93a7568ff6 Fix documentation of skip_serializing_if 2016-04-17 21:31:18 -07:00
David Tolnay 0439bb9d02 Deserialize impl for Box<[T]> 2016-04-17 20:59:26 -07:00
David Tolnay 886670134a feat(codegen): Infer Default and Deserialize bounds correctly 2016-04-13 21:56:12 -07:00
Erick Tryzelaar 65e36647f5 Merge pull request #283 from dtolnay/defaultskip
fix(codegen): Take into account default=... when skip_deserializing
2016-04-13 08:43:10 -07:00
Erick Tryzelaar 51fdb0e4ef Merge pull request #284 from erickt/master
Fix doc links
2016-04-13 08:41:52 -07:00
Erick Tryzelaar a4de662adb Fix doc links 2016-04-13 08:11:02 -07:00
David Tolnay ff02b0c741 fix(codegen): Take into account default=... when skip_deserializing 2016-04-12 23:42:24 -07:00
Erick Tryzelaar 6b3958d5fc Merge pull request #282 from erickt/doc
Fix generating serde_{codegen,macros} documentation
2016-04-12 17:08:15 -07:00
Erick Tryzelaar 84b289dd7b 1.5 is unhappy that this private module is undocumented 2016-04-12 09:24:32 -07:00
Erick Tryzelaar dbba537b66 Merge branch 'skip_deserializing' of https://github.com/dtolnay/serde into dtolnay-skip_deserializing 2016-04-12 08:52:25 -07:00
Erick Tryzelaar bc2324fba7 Merge branch 'feature/inhibit' of https://github.com/dtolnay/serde into dtolnay-feature/inhibit 2016-04-12 08:41:02 -07:00
Erick Tryzelaar 9082b75e75 Fix generating serde_{codegen,macros} documentation 2016-04-12 08:36:02 -07:00
Erick Tryzelaar 4b9f751d74 Merge pull request #264 from dtolnay/docs/links
Fix broken documentation links in Cargo.toml
2016-04-12 08:32:14 -07:00
Erick Tryzelaar 451700d3d2 Add more tests for renaming missing field 2016-04-12 08:26:56 -07:00
Erick Tryzelaar 1c5d83889c Merge remote-tracking branch 'remotes/origin/master' into renamed_missing_field 2016-04-12 08:24:34 -07:00
Oliver Schneider f659fa8919 add a test 2016-04-12 12:42:07 +02:00
David Tolnay 87393b61bb feat(codegen) skip_deserializing 2016-04-10 20:29:37 -07:00
Erick Tryzelaar a84b6aaedd Bump syntex/aster/quasi version 2016-04-10 19:54:54 -07:00
Erick Tryzelaar ac98a25291 Merge pull request #275 from dtolnay/brackets
Add missing close brackets in readme
2016-04-06 07:20:41 -07:00
Erick Tryzelaar 48dd47b2b7 Merge pull request #279 from jwilm/fix-deserialize-with-result
Fix `deserialize_with` in module with Result alias
2016-04-05 19:25:48 -07:00
Joe Wilm 4af850431c Fix deserialize_with in module with Result alias
Result<T, E> aliases usually provide one or both of `T` and `E`. This
would cause an error when using deserialize_with:

    error: wrong number of type arguments: expected 1, found 2

which unhelpfully just pointed to `#[derive(Deserialize)]`
2016-04-05 15:53:51 -07:00
Oliver Schneider 95c5e8681e Merge pull request #273 from serde-rs/void-unused-variables
Silence unused_variables warning with empty enums
2016-04-03 14:49:38 +02:00
Anthony Ramine c7c5b50f35 Silence unused_variables warning with empty enums
Deriving Serialize or Deserialize on Void-like enums triggered an
unused_variables warning.
2016-04-03 14:31:04 +02:00
David Tolnay a8509a1d03 Add missing close brackets in readme 2016-04-01 09:55:54 -07:00
Oliver Schneider d9b6feef19 pass the renamed deserialize field name to missing_field 2016-03-30 17:29:27 +02:00
Erick Tryzelaar b526404707 Merge pull request #266 from serde-rs/clippy-badge
add clippy badge
2016-03-27 10:13:30 -07:00
Erick Tryzelaar 9785646246 feat(cargo): Update syntex 2016-03-16 23:52:21 -07:00
Oliver Schneider 332b51f58a add clippy badge 2016-03-09 13:51:26 +01:00
David Tolnay fb18a5cc56 Fix broken documentation links in Cargo.toml 2016-03-06 19:28:26 -08:00
Erick Tryzelaar b1cab411d6 Merge pull request #263 from dtolnay/docs/quotes
Missing quotes in upgrading-from-0.6 section of readme
2016-03-06 21:28:48 -05:00
David Tolnay b01fc032fd Missing quotes in upgrading-from-0.6 section of readme 2016-03-06 18:26:38 -08:00
Erick Tryzelaar f771eea6e6 doc(readme): Document new 0.7 skip-serializing approach 2016-03-06 21:20:04 -05:00
Erick Tryzelaar 6b127cb8d0 Update travis travis token 2016-03-06 21:14:23 -05:00
Erick Tryzelaar d0a63b451c Update README.md 2016-03-06 21:06:11 -05:00
Erick Tryzelaar 8296ff4bad Merge pull request #257 from frewsxcv/patch-1
Remove now default 'sudo: false'
2016-03-02 03:11:39 -08:00
David Tolnay eaff73a541 Where clause for generic types only 2016-02-29 21:53:58 -08:00
David Tolnay 19ec8bbdb9 feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:

    struct Test<A, B, C> {
        a: X<A>
        #[serde(skip_serializing)]
        b: B
        #[serde(serialize_with="...")]
        c: C
    }

Used to be:

    impl<A, B, C> Serialize for Test<A, B, C>
        where A: Serialize,
              B: Serialize,
              C: Serialize,
    { ... }

Now it is:

    impl<A, B, C> Serialize for Test<A, B, C>
        where X<A>: Serialize,
    { ... }

Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 19:11:51 -08:00
Corey Farwell 4d4b85318f Remove now default 'sudo: false'
`sudo: false` is now default on Travis CI
2016-02-27 15:36:29 -05:00
Erick Tryzelaar 708a310ab0 Merge pull request #254 from erickt/error-custom
feat(errors): Switch Error::custom to use Into<String>
2016-02-26 21:25:01 -08:00
Erick Tryzelaar ec75f22396 feat(errors): Switch Error::custom to use Into<String> 2016-02-26 21:12:16 -08:00
Erick Tryzelaar 6ea632e98b doc(readme): Update readme to compile with latest serde 2016-02-26 11:17:43 -08:00
Erick Tryzelaar 4117b1c054 refactor(de): Minor shuffling of methods 2016-02-24 09:11:23 -08:00
Erick Tryzelaar 761284932b doc(readme): Remove reference to old serde_json docs 2016-02-24 09:00:21 -08:00
Erick Tryzelaar c244535f9b Merge remote-tracking branch 'remotes/origin/v0.6.x' 2016-02-24 08:49:22 -08:00
Erick Tryzelaar 577c7657dc Merge pull request #252 from ReadmeCritic/v0.6.x
Update README URLs based on HTTP redirects
2016-02-24 08:48:44 -08:00
Erick Tryzelaar f05875e49a Merge pull request #250 from dtolnay/yaml
YAML serde based on yaml-rust
2016-02-24 08:48:14 -08:00
Erick Tryzelaar 56400ac0ff Merge remote-tracking branch 'remotes/origin/v0.6.x' 2016-02-24 08:31:17 -08:00
ReadmeCritic a18d8fbc09 Update README URLs based on HTTP redirects 2016-02-24 06:33:14 -08:00
David Tolnay a0eb235f0a YAML serde based on yaml-rust 2016-02-24 00:22:48 -08:00
Erick Tryzelaar c6cd8a09c0 Merge pull request #249 from erickt/master
Rename error trait methods, optimize bytes, don't expose primitive
2016-02-23 20:51:59 -08:00
Erick Tryzelaar 3e94bf2d13 fix(warnings): Fix clippy warnings 2016-02-23 20:38:06 -08:00
Erick Tryzelaar f4c8ad6c3a feat(de): Don't expose primitive 2016-02-23 20:38:06 -08:00
Erick Tryzelaar 57433e1eaa feat(codegen): Optimize deserializing fields from byte strings 2016-02-23 20:38:06 -08:00
Erick Tryzelaar 118476b98b feat(de): Rename de::Error trait methods 2016-02-23 20:21:07 -08:00
Erick Tryzelaar 6caf8a0074 fix(error): Report UnknownVariant and InvalidValue
Don't unify it with syntax errors.
2016-02-23 20:21:07 -08:00
Erick Tryzelaar 96483ee54f Merge pull request #246 from erickt/master
feat(cargo): Version bump to 0.7!
2016-02-23 20:20:52 -08:00
Erick Tryzelaar 6a9216f26a Merge pull request #248 from Yoric/v0.6.x
Resolves #183 - Serialize and Deserialize for PhantomData
2016-02-23 20:20:23 -08:00
David Rajchenbach-Teller 4bba342e42 Resolves #183 - Serialize and Deserialize for PhantomData 2016-02-23 21:43:50 +01:00
Erick Tryzelaar 2987b0d10a Merge pull request #245 from erickt/master
feat(serde): Add hooks for fixed-sized arrays
2016-02-23 05:32:56 -08:00
Erick Tryzelaar d6a50b8977 feat(cargo): Version bump to 0.7! 2016-02-23 05:26:07 -08:00
Erick Tryzelaar 76b3dead9b feat(serde): Add hooks for fixed-sized arrays
Closes #244
2016-02-23 05:15:44 -08:00
Erick Tryzelaar d24b2c86f2 Merge tag 'v0.6.15'
Tagging for release
2016-02-22 08:32:05 -08:00
Erick Tryzelaar b6965ecde8 feat(cargo): Version bump 2016-02-22 08:15:17 -08:00
Erick Tryzelaar b3d5de3b92 Merge pull request #243 from erickt/master
feat(de): Remove dependency on the `num` crate.
2016-02-22 08:08:23 -08:00
Erick Tryzelaar 49b0bfd257 feat(de): Remove dependency on the num crate. 2016-02-21 21:22:58 -08:00
Erick Tryzelaar 1132c0b0e1 Merge pull request #242 from erickt/master
feat(impls): Add impls for std::net::Ip{,v4,v6}Addr
2016-02-21 20:47:38 -08:00
Erick Tryzelaar 4cb5ee0678 feat(impls): Add impls for std::net::SocketAddr{,V4,V6} 2016-02-21 20:21:21 -08:00
Erick Tryzelaar b257084f3a feat(impls): Add impls for std::net::Ip{,v4,v6}Addr 2016-02-21 20:21:21 -08:00
Erick Tryzelaar c03587f0bf Merge remote-tracking branch 'remotes/origin/v0.6.x' 2016-02-21 20:05:38 -08:00
Erick Tryzelaar 96526dfd66 Merge pull request #241 from erickt/master
feat(de): Add an Error::unknown_variant error.
2016-02-21 17:42:02 -08:00
Erick Tryzelaar 740865b637 feat(de): Add an Error::unknown_variant error.
Closes #169
2016-02-21 16:26:52 -08:00
Erick Tryzelaar 4d10eef55d doc(serde): Document the visit_string method
Closes #184
2016-02-21 16:03:33 -08:00
Erick Tryzelaar 7adf624dee Merge pull request #238 from erickt/skip4
Add codegen expr magic for default, skip serializing, and alternative serializers
2016-02-21 15:38:31 -08:00
Erick Tryzelaar 78cf29d1d1 feat(codegen): Switch attributes to using using paths not expressions 2016-02-21 15:28:25 -08:00
Erick Tryzelaar 3f3cffe317 Merge pull request #240 from kevinmehall/nightly
Fix cargo `nightly` feature
2016-02-21 13:28:54 -08:00
Kevin Mehall 4e7b0ac089 Fix cargo nightly feature
517c2f79b7 renamed the `nightly` feature to `nightly-testing` to
reflect that the `clippy` dependency is only required when testing.
However, the code also uses `#[cfg(feature = "nightly")]` to enable
trait impls for feature-gated types. This commit restores that
functionality and fixes a few `cfg_attr`s that refer to clippy lints.
2016-02-21 13:01:04 -08:00
Erick Tryzelaar 0c35ce0a4f feat(codegen): Improve error messages in annotations 2016-02-21 09:54:03 -08:00
Erick Tryzelaar dbd05ae9cc doc(annotations): Add docs for the latest documentation 2016-02-18 19:32:10 -08:00
Erick Tryzelaar c268eb2258 feat(codegen): Remove #[serde(skip_serializing_if_{none,empty})]
`#[serde(skip_serializing_if="...")]` can replace this functionality.
2016-02-18 19:31:43 -08:00
Erick Tryzelaar 40f8e6b061 feat(codegen): Add #[serde(deserialize_with="...")]
This allows a field to be deserialized with an expression instead
of the default deserializer. This simplifies deserializing a struct
or enum that contains an external type that doesn't implement
`serde::Deserialize`. This expression is passed a variable
`deserializer` that needs to be used to deserialize the expression.
2016-02-18 19:13:55 -08:00
Erick Tryzelaar 001cb7ab01 feat(codegen): Add #[serde(serialize_with="...")]
This allows a field to be serialized with an expression instead
of the default serializer. This simplifies serializing a struct
or enum that contains an external type that doesn't implement
`serde::Serialize`. This expression is passed a variable
`serializer` that needs to be used to serialize the expression.
2016-02-18 19:13:55 -08:00
Erick Tryzelaar de89f95f31 feat(codegen): Add support for #![serde(skip_serialize_if="$expr")]
This allows end users to use an arbitrary expression to decide whether
or not to serialize some field. This expression has access to all the
fields in the struct, but none of the internal state of the Serialize
implementation. For structs, serde implements this by creating a
temporary trait and implementing the struct for it. For struct variants,
the fields are copied by reference into a temporary struct first
before implementing the temporary trait.

This also fixes a bug where the serde_codegen wasn't making calls to
Serializer::serialize_{tuple,struct}_variant{,_elt}.
2016-02-18 19:13:55 -08:00
Erick Tryzelaar 9812a4c9c6 feat(codegen): Allow #[serde(default="123")]
This feature adds support for the default to be specified to be
some expression (which unfortunately needs to be parsed from
a string) without needing this value to have an implementation
of `Default`, or for a new-type wrapper in order to provide an
alternative implementation. This expression is run in a function,
and therefore has no access to any of the internal state of
the deserializer.
2016-02-18 19:13:55 -08:00
Erick Tryzelaar 8ea6c66cf7 refactor(tests): Rename and move some structs and enums 2016-02-18 19:13:55 -08:00
Erick Tryzelaar 17bf789708 Merge branch 'v0.6.x' 2016-02-18 09:46:46 -08:00
Erick Tryzelaar f6a66a5537 feat(cargo): Rustup to latest nightly 2016-02-18 09:27:41 -08:00
Erick Tryzelaar 1236889664 Merge branch 'v0.6.x'
# Conflicts:
#	serde_codegen/src/de.rs
2016-02-14 16:45:59 -08:00
Erick Tryzelaar fd5ab8c5c8 feat(cargo): Version bump 2016-02-13 22:06:08 -08:00
Erick Tryzelaar 39fa78e2ec Merge pull request #236 from debris/rustup3
Update serde_codegen for rustc 1.8.0-nightly (ce4b75f25 2016-02-12)
2016-02-13 21:56:07 -08:00
debris e18416ac7f updated serde_tests deps 2016-02-14 03:43:37 +01:00
debris b63cc13f3a updated clippy to 0.0.41 2016-02-14 03:33:58 +01:00
debris 74b230c183 Update serde_codegen for rustc 1.8.0-nightly (ce4b75f25 2016-02-12) 2016-02-14 03:27:20 +01:00
Erick Tryzelaar 561a373d19 Merge branch 'v0.6.x'
# Conflicts:
#	serde/src/de/mod.rs
#	serde_codegen/src/attr.rs
#	serde_codegen/src/de.rs
#	serde_codegen/src/lib.rs
2016-02-12 21:43:23 -08:00
Erick Tryzelaar 064241f03c fix(serde): Rename visit_struct_key to visit_struct_field
This is more consistent with the rest of the serde naming patterns.
2016-02-12 21:22:42 -08:00
Erick Tryzelaar 32163cd53b feat(cargo): Version bump 2016-02-12 21:06:47 -08:00
Erick Tryzelaar 3a5aa00262 fix(codegen): Fix clippy cfg_attr 2016-02-12 20:21:52 -08:00
Erick Tryzelaar c3f15fd7f8 Merge pull request #234 from jwilm/fix-clippy-feature
plugin(clippy) now relies on feature = "clippy"
2016-02-10 11:44:51 -08:00
Joe Wilm 9985d2ebfc plugin(clippy) now relies on feature = "clippy"
Was previously nightly. This resulted in compilation error when the
clippy feature was not enabled because the clippy crate could not be
found.
2016-02-10 11:42:33 -08:00
Erick Tryzelaar 46f88037db Merge branch 'v0.6.x' 2016-02-08 14:17:26 -08:00
Erick Tryzelaar 7a3e3a61f4 chore(tests): Silence some warnings 2016-02-08 13:37:03 -08:00
Erick Tryzelaar 517c2f79b7 chore(cargo): Only depend on clippy when testing 2016-02-08 13:35:26 -08:00
Erick Tryzelaar 4de59494e6 Merge pull request #233 from erickt/remove-format2
Remove support for format-specific renames, replace with ser or de specific renames
2016-02-08 13:25:41 -08:00
Erick Tryzelaar 3cde6fa333 Merge pull request #228 from compressed/clippy
fix(clippy): make clippy optional
2016-02-08 11:20:54 -08:00
Erick Tryzelaar 0224e212f9 feat(codegen): Allow containers to be renamed
Closes #218
2016-02-08 11:11:36 -08:00
Erick Tryzelaar 5ad784f6c6 refactor(tests): Improve test names 2016-02-08 10:43:41 -08:00
Erick Tryzelaar b842164fd8 feat(codegen): Support renames that are different when serializing and deserializing
According to #61, if one uses serde to serialize requests that pass
url-encoded parameters to a server, it might get responses back
with a different capitalization scheme. This patch restores the
behavior implemented in #62.

# Conflicts:
#	serde_codegen/src/attr.rs
#	serde_codegen/src/de.rs
#	serde_tests/tests/test_annotations.rs
2016-02-08 10:43:41 -08:00
Erick Tryzelaar 365e5129af refactor(codegen): Add VariantAttrs 2016-02-08 10:43:32 -08:00
Erick Tryzelaar d0ee5b0b4b feat(codegen): Remove {Ser,Deser}ializer::format
This feature has never been used, and it's complicating the
implementation of #207. We could restore this functionality if there is
ever interest in it.

Closes #211.
2016-02-08 10:10:00 -08:00
Erick Tryzelaar 5d4f9ce72b refactor(codegen): Add FieldsAttr::from_{field,variant} 2016-02-08 10:09:30 -08:00
Erick Tryzelaar 807224d231 refactor(codegen): Add ContainerAttrs::from_items 2016-02-08 10:09:18 -08:00
Erick Tryzelaar 0bd380ee23 chore(cleanup): Minor reorganization of attr.rs 2016-02-08 08:30:29 -08:00
Erick Tryzelaar a926cb62f0 chore(codegen): Clean up error handling 2016-02-07 20:36:24 -08:00
Erick Tryzelaar 8c8fcdbc54 Merge pull request #231 from erickt/rename-struct-key-to-field
Rename struct key to field
2016-02-07 20:35:38 -08:00
Christopher Brickley da7bb8e109 fix(clippy): make clippy optional 2016-02-07 13:59:15 -05:00
Erick Tryzelaar f8b3990571 feat(de): Rename deserialize_struct_key to deserialize_struct_field
This makes it more consistent with the naming style used throughout
the rest of serde.
2016-02-05 17:27:18 -08:00
Erick Tryzelaar 9dffbcfedb fix(whitespace): Fixed indentation 2016-02-05 17:27:18 -08:00
Erick Tryzelaar 50c73edd6a Merge pull request #215 from TyOverby/deserialize_string-for-pathbuf
Use deserializer.deserialize_string for PathBuf
2016-02-05 07:57:28 -08:00
Erick Tryzelaar 1b1f95f372 Merge pull request #224 from erickt/path
feat(ser): Add ser::Error trait; avoid panic when serializing Paths
2016-02-05 07:56:48 -08:00
Erick Tryzelaar 9b349d08cc Merge pull request #225 from jwilm/hint-ignored-any
feat(de): Support hinting for IgnoredAny
2016-02-05 07:56:30 -08:00
Erick Tryzelaar 718822449f Merge pull request #227 from serde-rs/oli-obk-patch-1
add a build.rs file to the stable-only syntex example
2016-02-05 07:54:56 -08:00
Oliver Schneider 43624e8e7f add a build.rs file to the stable-only syntex example 2016-02-05 12:30:28 +01:00
Joe Wilm b0bc8e3594 feat(de): Support hinting for IgnoredAny
IgnoredAny was calling `deserializer.deserialize` directly which is
guaranteed to Error for certain formats like redis and bincode. This
adds a `deserialize_ignored_any` method to hint to such implementations.
2016-01-28 11:49:36 -08:00
Erick Tryzelaar f1b20577d3 feat(ser): Add ser::Error trait; avoid panic when serializing Paths
The only way to safely serialize a `Path` is to use
`.to_string_lossy()`, which replaces invalid UTF-8 characters with
the U+FFFD replacement character. Unfortunately this would lose
information, so for our default implementations, it'd be better
to punt and report an error, and leave it up to the user to
decide if they want to use the lossy encoding.

Unfortunately, we had no way for `Serializer`s to require some methods
on `Serializer::Error`, so there was no way before this patch for
the `Path` implementation to generically report that it cannot encode
this value. This adds that implementation.

breaking-change

Closes #57.
2016-01-28 10:41:21 -08:00
Erick Tryzelaar 9ae47a261e Merge branch 'v0.6.x'
# Conflicts:
#	serde/src/de/impls.rs
#	serde_codegen/src/de.rs
2016-01-28 09:49:15 -08:00
Erick Tryzelaar 4507eaec5b Use deserializer.visit_string for PathBuf 2016-01-28 09:45:38 -08:00
Erick Tryzelaar b3212f4c2b Merge pull request #223 from jwilm/hinting-for-struct-keys
feat(de): Support struct key hinting
2016-01-28 08:57:16 -08:00
Joe Wilm 6d25fc9dbb feat(de): Support struct key hinting
Formats that do not provide type hints in the serialized format
(bincode, redis) rely on hinting in the deserializer. Struct key hinting
was not previously supported. This was not an issue in the past because
bincode serializes structs as a keyless sequence of values. However,
redis data is stored (key, value, key, value, ...), and the keys must be
deserialized to properly create a struct.

The default implementation of `visit_struct_key` is simply `visit` since
that was the previous method called in codegen.
2016-01-28 08:38:07 -08:00
Erick Tryzelaar 589187874a Merge pull request #222 from jwilm/fix-readme
Fixes for README
2016-01-27 09:26:54 -08:00
Joe Wilm 1b6ae02e8a docs(readme) update links for documentation
Documentation links were all broken.
2016-01-26 20:18:49 -08:00
Joe Wilm 7ace67e997 docs(readme) fix method calls on de/serializers
Several instances of serializer and deserializer had methods like
visit_* being invoked on them when the intent was to invoke
de/serialize_*.
2016-01-26 19:34:33 -08:00
Erick Tryzelaar c072025982 Merge branch 'v0.6.x' 2016-01-26 14:06:43 -08:00
Simon Persson a5d0703e44 Bump clippy dependency to compile on 1.8. 2016-01-23 16:15:31 -08:00
Erick Tryzelaar 0a32cea26e feat(impls): Allow options to be deserialized from units 2016-01-23 16:07:50 -08:00
Erick Tryzelaar b2acda333b Merge branch 'v0.6.x' 2016-01-20 11:16:06 -08:00
Erick Tryzelaar da4e37d3f5 docs(tradeoffs): Add section that describes tradeoffs for option types 2016-01-20 11:15:43 -08:00
Ty Overby 17d825bdd9 Use deserializer.deserialize_string for PathBuf 2016-01-19 08:54:56 -08:00
Erick Tryzelaar e0254fc312 Merge branch 'v0.6.x' 2016-01-18 13:19:18 -08:00
Erick Tryzelaar 3f9cbc157a fix(cargo): serde_codegen shouldn't depend on '*' serde dependencies 2016-01-18 13:15:09 -08:00
Erick Tryzelaar a51f930101 feat(cargo): Version bump 2016-01-18 13:11:16 -08:00
Erick Tryzelaar d1e39db61e Merge branch 'v0.6.x' 2016-01-18 13:09:31 -08:00
Erick Tryzelaar 77edd8e544 fix(clippy): Switch to using or_else when we get a str parse error 2016-01-18 13:07:30 -08:00
Erick Tryzelaar 8087b7cec6 fix(cargo): Bump clippy version 2016-01-18 13:00:21 -08:00
Erick Tryzelaar 42b8b6153e Merge branch 'v0.6.x' into master
# Conflicts:
#	serde/Cargo.toml
#	serde/src/ser/impls.rs
#	serde_codegen/src/attr.rs
#	serde_codegen/src/de.rs
#	serde_codegen/src/field.rs
#	serde_codegen/src/ser.rs
2016-01-18 12:45:39 -08:00
Erick Tryzelaar 8df841f048 fix(errors): Report errors on unknown #[serde(...)] attributes
Closes #51, #175, and #187
2016-01-18 12:39:46 -08:00
Erick Tryzelaar bfa2b69193 feat(clippy): Use clippy for it's extra lints 2016-01-18 12:24:03 -08:00
Erick Tryzelaar 939e1540d4 Merge pull request #205 from JohnHeitmann/default-typo
Remove extraneous flag
2016-01-18 09:11:14 -08:00
Erick Tryzelaar 835eb94275 Merge pull request #212 from debris/patch-1
fixed typo in readme
2016-01-18 09:10:45 -08:00
Marek Kotewicz 79cc333dca fixed typo in readme 2016-01-17 15:14:25 +01:00
Erick Tryzelaar 1ced6db73e Merge remote-tracking branch 'remotes/origin/v0.6.x' 2016-01-16 15:08:06 -08:00
Erick Tryzelaar fbcf905c9f Merge pull request #210 from erickt/v0.6.x
feat(errors): Don't panic if annotating a non-struct/enum
2016-01-16 15:06:07 -08:00
Erick Tryzelaar 979a4bcd88 feat(errors): Don't panic if annotating a non-struct/enum
This also improves the error spans when there's an internal
error.

Closes #206.
2016-01-16 14:51:11 -08:00
Erick Tryzelaar 2aefa5bb1d Merge pull request #204 from JohnHeitmann/master
Implemented disallow_unknown
2016-01-16 13:32:20 -08:00
Erick Tryzelaar 4c92b877d6 Merge branch 'v0.6.x' 2016-01-16 13:17:38 -08:00
Erick Tryzelaar 342ea25290 feat(cargo): Version bump 2016-01-13 07:05:32 -08:00
Erick Tryzelaar 8d8f17982a feat(cargo): Version bump 2016-01-13 06:59:30 -08:00
John Heitmann bba21f99fe Remove extraneous flag 2016-01-11 17:51:07 -08:00
John Heitmann 8c57f433ff s/disallow_unknown/deny_unknown_fields/ 2016-01-11 10:20:07 -08:00
John Heitmann bfac1a581c Implemented disallow_unknown
* Added codegen for disallow_unknown
* ... with new default to ignore unknown values during deserialization
* Added ContainerAttrs
2016-01-10 19:34:48 -08:00
Erick Tryzelaar 59285f627b Merge branch 'v0.6.x'
# Conflicts:
#	serde_codegen/Cargo.toml
2016-01-10 11:54:46 -08:00
Erick Tryzelaar dd3233ac85 fix(cargo): Fix typos 2016-01-10 11:50:35 -08:00
Erick Tryzelaar 9b57f60c2a fix(cargo): Version bump 2016-01-07 14:50:18 -08:00
Erick Tryzelaar 8038832a79 fix(cargo): Version bump 2016-01-07 14:48:40 -08:00
Erick Tryzelaar 4ce0dfc91d Merge pull request #199 from Starefossen/patch-1
Use SVG version of Travis CI build status badge
2016-01-06 12:24:04 -08:00
Hans Kristian Flaatten 3aba2b79b8 docs(readme): Use SVG version of Travis CI build status badge 2016-01-04 09:19:23 +01:00
Erick Tryzelaar 072ff149f5 fix(rustup): Update to latest rust; silence some warnings 2015-12-24 12:12:03 -05:00
Erick Tryzelaar 14802e9666 fix(value): Handle the new value::Error variants when implementing Display 2015-12-09 15:40:45 -05:00
Erick Tryzelaar e1a44293c0 Merge pull request #162 from skade/std-error
Have serde::de::Error require std::error::Error
2015-12-08 14:10:45 -05:00
Erick Tryzelaar 8f08baf43a feat(cargo): Version bump 2015-12-08 09:57:33 -05:00
Erick Tryzelaar 188425ffe5 Merge branch 'v0.6.x' into master
# Conflicts:
#	serde_codegen/Cargo.toml
2015-12-08 09:50:10 -05:00
Erick Tryzelaar daf015799b Merge pull request #193 from killix/master
feat(cargo): Quasi version to 0.3.9
2015-12-08 09:42:37 -05:00
Erick Tryzelaar b3b3b7d565 fix(rustup): Sync serde_macros with latest nightly, aster, and quasi 2015-12-08 09:41:57 -05:00
Issam Hakimi aka Killix 566af5df9d feat(cargo): quasi_macro & quasi_codegen version to 0.3.9 2015-12-01 21:36:06 -05:00
Erick Tryzelaar 1a8a11e924 feat(impls): Add impls for num::{BigInt,BigUint,Complex,Ratio} 2015-12-01 09:03:08 -08:00
Erick Tryzelaar 25bebe76b6 Merge pull request #190 from thorbenk/master
fix typo
2015-11-29 15:54:45 -08:00
thorbenk e5beef4004 build: fix typo 2015-11-29 16:53:57 +01:00
Erick Tryzelaar b858cd9e18 Merge remote-tracking branch 'remotes/origin/v0.6.x'
# Conflicts:
#	serde_codegen/Cargo.toml
2015-11-28 21:16:51 -08:00
Erick Tryzelaar f3f098e7f5 feat(cargo): Version bump 2015-11-28 20:30:36 -08:00
Erick Tryzelaar 09822c99cc fix(rustup): Update serde_codegen to reflect Registry move 2015-11-28 20:17:21 -08:00
Erick Tryzelaar 966b104d48 fix(rustup): nightly rust moved Registry into rustc_plugin 2015-11-28 20:09:54 -08:00
Erick Tryzelaar 59e0d5e081 fix(warning): #[automatically_derived] was removed 2015-11-28 20:09:31 -08:00
Erick Tryzelaar c687ee60ff feat(example): Add an example 2015-11-28 20:09:03 -08:00
Erick Tryzelaar 2c0a4e7669 Merge pull request #189 from Ms2ger/typos
Fix typos.
2015-11-28 16:31:48 -08:00
Ms2ger 1ba6ff41f6 Fix typos. 2015-11-28 12:28:48 +01:00
Erick Tryzelaar f474c57881 Merge branch 'v0.6.x' 2015-11-02 20:39:32 -08:00
Erick Tryzelaar 4bdabea639 Merge pull request #170 from oli-obk/master
fix(#151): renaming Deserializer::visit_* to Deserializer::deserialize_*
2015-10-31 16:56:06 -07:00
Erick Tryzelaar 27c933a865 Merge pull request #174 from erickt/ignore
chore(git): Ignore swap files
2015-10-31 16:55:23 -07:00
Oliver Schneider 51912e6197 test(#151): update tests and benchmarks: visit -> (de)serialize 2015-10-20 09:30:15 +02:00
Oliver Schneider 56c42a907f fix(#151): renaming Deserializer::visit_* to Deserializer::deserialize_* 2015-10-20 09:30:15 +02:00
Erick Tryzelaar e96a213720 chore(git): Ignore swap files
Closes #172
2015-10-19 09:46:04 -07:00
Erick Tryzelaar bf31feebc4 chore(cleanup): Fix some warnings 2015-10-19 08:37:22 -07:00
Erick Tryzelaar 55de7bd99b fix(tests): Get tests to compile with new value deserializer scheme 2015-10-19 08:33:57 -07:00
Erick Tryzelaar cc67c97224 Merge remote-tracking branch 'remotes/origin/master' into error-take-2 2015-10-18 19:43:32 -07:00
Erick Tryzelaar bd87485251 Merge pull request #168 from pwoolcoc/num-no-default-features
Opt-out of `num`s `default-features`
2015-10-17 20:52:31 -07:00
Paul Woolcock 7ef2205f80 fix(dependencies): Opt-out of default features of num 2015-10-17 23:31:36 -04:00
Thomas Bahn 0b5e91d430 feat: Add deserializers that use visitors.
This deserializers can be used to delegate deserialization to another
type's visitor.

Example:
```json
fn visit_map<V>(&mut self, visitor: V) -> Result<Self::Value, V::Error>
    where V: de::MapVisitor
{
    let mut deserializer = de::value::MapVisitorDeserializer::new(visitor);
    try!(Deserialize::deserialize(&mut deserializer))
}
```
2015-10-08 15:22:02 +02:00
Thomas Bahn e0429cdd96 style: remove the redundant Error suffix 2015-10-06 01:37:39 +02:00
Thomas Bahn 7413bbb7bf feat: ValueDeserializers are generic over the error type
This makes it possible to remove the `From<de::value::Error>` trait
bound from the `de::Error` trait.

An example for using a `ValueDeserializer` to forward deserializing to
another type's visitor:

```rust
fn visit_u8<E>(&mut self, value: u8) -> Result<Self::Value, E>
    where E: de::Error
{
    try!(Deserialize::deserialize(&mut value.into_deserializer()))
}
```

Please note that there is an regression in serde-rs/json which needs to
be fixed.
2015-10-06 01:37:39 +02:00
Thomas Bahn 0a65153634 fix: forward more errors in de::value::Error
When using a `ValueDeserializer` errors produced with the methods
`type_mismatch`, `length_mismatch` and `syntax` were not forwarded
correctly. These methods now store all information in the enum
`de::value::Error`.
2015-10-05 23:40:36 +02:00
Florian Gilcher fc19895237 Have serde::de::Error require std::error::Error 2015-09-24 07:03:36 -07:00
73 changed files with 8813 additions and 3823 deletions
+7
View File
@@ -0,0 +1,7 @@
paths = [
"serde",
"serde_codegen",
"serde_codegen_internals",
"serde_macros",
"serde_test",
]
+2 -1
View File
@@ -1,2 +1,3 @@
target
Cargo.lock
target
*.sw[po]
+23 -27
View File
@@ -1,41 +1,37 @@
language: rust
sudo: false
language: rust
rust:
- stable
- beta
- nightly
- stable
- nightly
- 1.8.0
- 1.9.0
- beta
addons:
apt:
packages:
- libcurl4-openssl-dev
- libelf-dev
- libdw-dev
before_script:
- |
pip install 'travis-cargo<0.2' --user &&
export PATH=$HOME/.local/bin:$PATH
- pip install 'travis-cargo<0.2' --user
- export PATH=$HOME/.local/bin:$PATH
script:
- |
(cd serde && travis-cargo build) &&
(cd serde && travis-cargo test) &&
(cd serde_tests && travis-cargo test) &&
(cd serde_macros && travis-cargo --only nightly test) &&
(cd serde_macros && travis-cargo --only nightly bench) &&
(cd serde && travis-cargo --only stable doc) &&
(cd serde_codegen && travis-cargo --only stable doc)
- (cd serde && travis-cargo build)
- (cd serde && travis-cargo --skip nightly test)
- (cd serde && travis-cargo --only nightly test -- --features nightly-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 nightly-testing)
- (cd serde_macros && travis-cargo --only nightly test -- --features nightly-testing)
- (cd examples/serde-syntex-example && travis-cargo --skip nightly run)
- (cd examples/serde-syntex-example && travis-cargo --only nightly run -- --no-default-features --features nightly)
- (cd serde && travis-cargo --only stable doc)
after_success:
- (cd serde && travis-cargo --only stable doc-upload)
- (cd serde_tests && travis-cargo coveralls --no-sudo)
- (cd testing && travis-cargo --only stable coveralls --no-sudo)
env:
global:
# override the default `--features unstable` used for the nightly branch (optional)
- TRAVIS_CARGO_NIGHTLY_FEATURE=""
# encrypted github token for doc upload (see `GH_TOKEN` link above)
- secure: HO41LMpMXkF2In9+1sxWVu7fgolL+y9+4Q5PI6wZX2L5pDwpPJCjxaQarQXCEnoIxED1PlP03JuF7ULNz0zw1ylYhAOfOSdkxFZRnE2wMZqq6qvXBHwyMiDrAociIzoPKSGv7JVrKPsjsnd+96K6xxueIodQZrmAdyq7N/M82Mc=
- TRAVIS_CARGO_NIGHTLY_FEATURE=""
- secure: Jcd11Jy0xLyacBUB+oKOaxKBm9iZNInenRDtNBY8GKOtqF5fHUfEjgDf538hwRl5L0FP7DLr8oK0IHmzA7lPjJxlzoKVKV3IM7bRZEYzW5DMonf/lcliuGte7SH0NVFhifM87T8HI2hjGdAb+7+m34siBR7M3AY/XjLInrvUFvY=
+45
View File
@@ -0,0 +1,45 @@
# Contributing to Serde
Serde welcomes contribution from everyone. Here are the guidelines if you are
thinking of helping us:
## Contributions
Contributions to Serde or its dependencies should be made in the form of GitHub
pull requests. Each pull request will be reviewed by a core contributor
(someone with permission to land patches) and either landed in the main tree or
given feedback for changes that would be required. All contributions should
follow this format, even those from core contributors.
Should you wish to work on an issue, please claim it first by commenting on
the GitHub issue that you want to work on it. This is to prevent duplicated
efforts from contributors on the same issue.
## Pull Request Checklist
- Branch from the master branch and, if needed, rebase to the current master
branch before submitting your pull request. If it doesn't merge cleanly with
master you may be asked to rebase your changes.
- Commits should be as small as possible, while ensuring that each commit is
correct independently (i.e., each commit should compile and pass tests).
- If your patch is not getting reviewed or you need a specific person to review
it, you can @-reply a reviewer asking for a review in the pull request or a
comment, or you can ask for a review in `#serde` on `irc.mozilla.org`.
- Add tests relevant to the fixed bug or new feature.
## Conduct
In all Serde-related forums, we follow the [Rust Code of
Conduct](https://www.rust-lang.org/conduct.html). For escalation or moderation
issues, please contact Erick (erick.tryzelaar@gmail.com) instead of the Rust
moderation team.
## Communication
Beyond opening tickets on the
[serde-rs/serde](https://github.com/serde-rs/serde) project, Serde contributors
frequent the `#serde` channel on
[`irc.mozilla.org`](https://wiki.mozilla.org/IRC).
+362 -137
View File
@@ -1,9 +1,10 @@
Serde Rust Serialization Framework
==================================
[![Build Status](https://api.travis-ci.org/serde-rs/serde.png?branch=master)](https://travis-ci.org/serde-rs/serde)
[![Build Status](https://api.travis-ci.org/serde-rs/serde.svg?branch=master)](https://travis-ci.org/serde-rs/serde)
[![Coverage Status](https://coveralls.io/repos/serde-rs/serde/badge.svg?branch=master&service=github)](https://coveralls.io/github/serde-rs/serde?branch=master)
[![Latest Version](https://img.shields.io/crates/v/serde.svg)](https://crates.io/crates/serde)
[![Clippy Linting Result](https://clippy.bashy.io/github/serde-rs/serde/master/badge.svg)](https://clippy.bashy.io/github/serde-rs/serde/master/log)
Serde is a powerful framework that enables serialization libraries to
generically serialize Rust data structures without the overhead of runtime type
@@ -11,22 +12,184 @@ information. In many situations, the handshake protocol between serializers and
serializees can be completely optimized away, leaving Serde to perform roughly
the same speed as a hand written serializer for a specific type.
Documentation is available at:
[Documentation](https://serde-rs.github.io/serde/serde/index.html)
* [serde](https://serde-rs.github.io/serde/serde/serde/index.html)
* [serde\_json](https://serde-rs.github.io/serde/serde_json/serde_json/index.html)
* [serde\_codegen](https://serde-rs.github.io/serde/serde_codegen/serde_codegen/index.html)
Simple Serde Example
====================
Here is a simple example that uses
[serde_json](https://github.com/serde-rs/json), which uses Serde under the
covers, to generate and parse JSON. First, lets start off with the `Cargo.toml`
file:
```toml
[package]
name = "serde_example"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
[dependencies]
serde_json = "*"
```
Next, the `src/main.rs` file itself:
```rust,ignore
extern crate serde_json;
use std::collections::HashMap;
use serde_json::Value;
use serde_json::builder::{ArrayBuilder, ObjectBuilder};
fn main() {
// Serde has support for many of the builtin Rust types, like arrays..:
let v = vec![1, 2];
let serialized = serde_json::to_string(&v).unwrap();
println!("serialized vec: {:?}", serialized);
let deserialized: Vec<u32> = serde_json::from_str(&serialized).unwrap();
println!("deserialized vec: {:?}", deserialized);
// ... and maps:
let mut map = HashMap::new();
map.insert("x".to_string(), 1);
map.insert("y".to_string(), 2);
let serialized = serde_json::to_string(&map).unwrap();
println!("serialized map: {:?}", serialized);
let deserialized: HashMap<String, u32> = serde_json::from_str(&serialized).unwrap();
println!("deserialized map: {:?}", deserialized);
// It also can handle complex objects:
let value = ObjectBuilder::new()
.insert("int", 1)
.insert("string", "a string")
.insert("array", ArrayBuilder::new()
.push(1)
.push(2)
.unwrap())
.unwrap();
let serialized = serde_json::to_string(&value).unwrap();
println!("serialized value: {:?}", serialized);
let deserialized: serde_json::Value = serde_json::from_str(&serialized).unwrap();
println!("deserialized value: {:?}", deserialized);
}
```
This produces the following output when run:
```
% cargo run
serialized vec: "[1,2]"
deserialized vec: [1, 2]
serialized map: "{\"y\":2,\"x\":1}"
deserialized map: {"y": 2, "x": 1}
serialized value: "{\"array\":[1,2],\"int\":1,\"string\":\"a string\"}"
deserialized value: {"array":[1,2],"int":1,"string":"a string"}
```
Using Serde with Stable Rust and serde\_codegen
===============================================
The example before used `serde_json::Value` as the in-memory representation of
the JSON value, but it's also possible for Serde to serialize to and from
regular Rust types. However, the code to do this can be a bit complicated to
write. So instead, Serde also has some powerful code generation libraries that
work with Stable and Nightly Rust that eliminate much of the complexity of hand
rolling serialization and deserialization for a given type.
First lets see how we would use Stable Rust, which is currently a tad more
complicated than Nightly Rust due to having to work around compiler plugins
being unstable. We will use `serde_codegen` which is based on the code
generation library [syntex](https://github.com/serde-rs/syntex). First we need
to setup the `Cargo.toml` that builds the project:
```toml
[package]
name = "serde_example"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
build = "build.rs"
[build-dependencies]
serde_codegen = "*"
[dependencies]
serde = "*"
serde_json = "*"
```
Next, we define our source file, `src/main.rs.in`. Note this is a different
extension than usual becaues we need to do code generation:
```rust,ignore
#[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);
}
```
To finish up the main source code, we define a very simple `src/main.rs` that
uses the generated code.
`src/main.rs`:
```rust,ignore
extern crate serde;
extern crate serde_json;
include!(concat!(env!("OUT_DIR"), "/main.rs"));
```
The last step is to actually drive the code generation, with the `build.rs` script:
```rust,ignore
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();
}
```
All this produces this when run:
```
% cargo run
{"x":1,"y":2}
Point { x: 1, y: 2 }
```
While this works well with Stable Rust, be aware that the error locations
currently are reported in the generated file instead of in the source file.
Using Serde with Nightly Rust and serde\_macros
===============================================
Here is a simple example that demonstrates how to use Serde by serializing and
deserializing to JSON. Serde comes with some powerful code generation libraries
that work with Stable and Nightly Rust that eliminate much of the complexity of
hand rolling serialization and deserialization for a given type. First lets see
how we would use Nightly Rust, which is currently a bit simpler than Stable
Rust:
The prior example is a bit more complicated than it needs to be due to compiler
plugins being unstable. However, if you are already using Nightly Rust, you can
use `serde_macros`, which has a much simpler interface. First, here is the new
`Cargo.toml`:
```toml
@@ -41,13 +204,13 @@ serde_json = "*"
serde_macros = "*"
```
`src/main.rs`
Note that it doesn't need a build script. Now the `src/main.rs`, which enables
the plugin feature, and registers the `serde_macros` plugin:
```rust
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
extern crate serde_json;
#[derive(Serialize, Deserialize, Debug)]
@@ -58,17 +221,16 @@ struct Point {
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
let serialized = serde_json::to_string(&point).unwrap();
println!("{}", serialized);
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
println!("{:?}", deserialized);
}
```
When run, it produces:
This also produces the same output:
```
% cargo run
@@ -76,70 +238,7 @@ When run, it produces:
Point { x: 1, y: 2 }
```
Using Serde with Stable Rust, syntex, and serde\_codegen
========================================================
Stable Rust is a little more complicated because it does not yet support
compiler plugins. Instead we need to use the code generation library
[syntex](https://github.com/erickt/rust-syntex) for this:
```toml
[package]
name = "serde_example"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
build = "build.rs"
[build-dependencies]
serde_codegen = "*"
syntex = "*"
[dependencies]
serde = "*"
serde_json = "*"
```
`src/main.rs`:
```rust
extern crate serde;
extern crate serde_json;
include!(concat!(env!("OUT_DIR"), "/main.rs"));
```
`src/main.rs.in`:
```rust
#[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);
}
```
This also produces:
```
% cargo run
{"x":1,"y":2}
Point { x: 1, y: 2 }
```
While this works well with Stable Rust, be aware that the error locations
currently are reported in the generated file instead of in the source file. You
may find it easier to develop with Nightly Rust and `serde\_macros`, then
You may find it easier to develop with Nightly Rust and `serde\_macros`, then
deploy with Stable Rust and `serde_codegen`. It's possible to combine both
approaches in one setup:
@@ -158,7 +257,6 @@ nightly = ["serde_macros"]
[build-dependencies]
serde_codegen = { version = "*", optional = true }
syntex = "*"
[dependencies]
serde = "*"
@@ -168,10 +266,9 @@ serde_macros = { version = "*", optional = true }
`build.rs`:
```rust
```rust,ignore
#[cfg(not(feature = "serde_macros"))]
mod inner {
extern crate syntex;
extern crate serde_codegen;
use std::env;
@@ -183,10 +280,7 @@ mod inner {
let src = Path::new("src/main.rs.in");
let dst = Path::new(&out_dir).join("main.rs");
let mut registry = syntex::Registry::new();
serde_codegen::register(&mut registry);
registry.expand("", &src, &dst).unwrap();
serde_codegen::expand(&src, &dst).unwrap();
}
}
@@ -202,7 +296,7 @@ fn main() {
`src/main.rs`:
```rust
```rust,ignore
#![cfg_attr(feature = "serde_macros", feature(custom_derive, plugin))]
#![cfg_attr(feature = "serde_macros", plugin(serde_macros))]
@@ -227,7 +321,7 @@ Then to run with stable:
Or with nightly:
```rust
```
% cargo build --features nightly --no-default-features
...
```
@@ -237,9 +331,9 @@ Serialization without Macros
Under the covers, Serde extensively uses the Visitor pattern to thread state
between the
[Serializer](http://serde-rs.github.io/serde/serde/ser/trait.Serializer.html)
[Serializer](http://serde-rs.github.io/serde/serde/serde/ser/trait.Serializer.html)
and
[Serialize](http://serde-rs.github.io/serde/serde/ser/trait.Serialize.html)
[Serialize](http://serde-rs.github.io/serde/serde/serde/ser/trait.Serialize.html)
without the two having specific information about each other's concrete type.
This has many of the same benefits as frameworks that use runtime type
information without the overhead. In fact, when compiling with optimizations,
@@ -248,27 +342,27 @@ nearly as fast as a hand written serializer format for a specific type.
To see it in action, lets look at how a simple type like `i32` is serialized.
The
[Serializer](http://serde-rs.github.io/serde/serde/ser/trait.Serializer.html)
[Serializer](http://serde-rs.github.io/serde/serde/serde/ser/trait.Serializer.html)
is threaded through the type:
```rust
```rust,ignore
impl serde::Serialize for i32 {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: serde::Serializer,
{
serializer.visit_i32(*self)
serializer.serialize_i32(*self)
}
}
```
As you can see it's pretty simple. More complex types like `BTreeMap` need to
pass a
[MapVisitor](http://serde-rs.github.io/serde/serde/ser/trait.MapVisitor.html)
[MapVisitor](http://serde-rs.github.io/serde/serde/serde/ser/trait.MapVisitor.html)
to the
[Serializer](http://serde-rs.github.io/serde/serde/ser/trait.Serializer.html)
[Serializer](http://serde-rs.github.io/serde/serde/serde/ser/trait.Serializer.html)
in order to walk through the type:
```rust
```rust,ignore
impl<K, V> Serialize for BTreeMap<K, V>
where K: Serialize + Ord,
V: Serialize,
@@ -277,7 +371,7 @@ impl<K, V> Serialize for BTreeMap<K, V>
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
@@ -309,7 +403,7 @@ impl<K, V, I> MapVisitor for MapIteratorVisitor<I>
{
match self.iter.next() {
Some((key, value)) => {
let value = try!(serializer.visit_map_elt(key, value));
let value = try!(serializer.serialize_map_elt(key, value));
Ok(Some(value))
}
None => Ok(None)
@@ -329,6 +423,7 @@ the fields:
```rust
extern crate serde;
extern crate serde_json;
struct Point {
x: i32,
@@ -339,7 +434,7 @@ impl serde::Serialize for Point {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: serde::Serializer
{
serializer.visit_struct("Point", PointMapVisitor {
serializer.serialize_struct("Point", PointMapVisitor {
value: self,
state: 0,
})
@@ -358,11 +453,11 @@ impl<'a> serde::ser::MapVisitor for PointMapVisitor<'a> {
match self.state {
0 => {
self.state += 1;
Ok(Some(try!(serializer.visit_struct_elt("x", &self.value.x))))
Ok(Some(try!(serializer.serialize_struct_elt("x", &self.value.x))))
}
1 => {
self.state += 1;
Ok(Some(try!(serializer.visit_struct_elt("y", &self.value.y))))
Ok(Some(try!(serializer.serialize_struct_elt("y", &self.value.y))))
}
_ => {
Ok(None)
@@ -370,6 +465,13 @@ impl<'a> serde::ser::MapVisitor for PointMapVisitor<'a> {
}
}
}
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
println!("{}", serialized);
}
```
Deserialization without Macros
@@ -377,19 +479,19 @@ Deserialization without Macros
Deserialization is a little more complicated since there's a bit more error
handling that needs to occur. Let's start with the simple `i32`
[Deserialize](http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html)
[Deserialize](http://serde-rs.github.io/serde/serde/serde/de/trait.Deserialize.html)
implementation. It passes a
[Visitor](http://serde-rs.github.io/serde/serde/de/trait.Visitor.html) to the
[Deserializer](http://serde-rs.github.io/serde/serde/de/trait.Deserializer.html).
The [Visitor](http://serde-rs.github.io/serde/serde/de/trait.Visitor.html)
[Visitor](http://serde-rs.github.io/serde/serde/serde/de/trait.Visitor.html) to the
[Deserializer](http://serde-rs.github.io/serde/serde/serde/de/trait.Deserializer.html).
The [Visitor](http://serde-rs.github.io/serde/serde/serde/de/trait.Visitor.html)
can create the `i32` from a variety of different types:
```rust
```rust,ignore
impl Deserialize for i32 {
fn deserialize<D>(deserializer: &mut D) -> Result<i32, D::Error>
where D: serde::Deserializer,
{
deserializer.visit(I32Visitor)
deserializer.deserialize(I32Visitor)
}
}
@@ -398,7 +500,7 @@ struct I32Visitor;
impl serde::de::Visitor for I32Visitor {
type Value = i32;
fn visit_i16<E>(&mut self, value: i16) -> Result<i16, E>
fn visit_i16<E>(&mut self, value: i16) -> Result<i32, E>
where E: Error,
{
self.visit_i32(value as i32)
@@ -416,18 +518,18 @@ impl serde::de::Visitor for I32Visitor {
Since it's possible for this type to get passed an unexpected type, we need a
way to error out. This is done by way of the
[Error](http://serde-rs.github.io/serde/serde/de/trait.Error.html) trait,
[Error](http://serde-rs.github.io/serde/serde/serde/de/trait.Error.html) trait,
which allows a
[Deserialize](http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html)
[Deserialize](http://serde-rs.github.io/serde/serde/serde/de/trait.Deserialize.html)
to generate an error for a few common error conditions. Here's how it could be used:
```rust
```rust,ignore
...
fn visit_string<E>(&mut self, _: String) -> Result<i32, E>
where E: Error,
{
Err(serde::de::Error::syntax("expect a string"))
Err(serde::de::Error::custom("expect a string"))
}
...
@@ -435,11 +537,11 @@ to generate an error for a few common error conditions. Here's how it could be u
```
Maps follow a similar pattern as before, and use a
[MapVisitor](http://serde-rs.github.io/serde/serde/de/trait.MapVisitor.html)
[MapVisitor](http://serde-rs.github.io/serde/serde/serde/de/trait.MapVisitor.html)
to walk through the values generated by the
[Deserializer](http://serde-rs.github.io/serde/serde/de/trait.Deserializer.html).
[Deserializer](http://serde-rs.github.io/serde/serde/serde/de/trait.Deserializer.html).
```rust
```rust,ignore
impl<K, V> serde::Deserialize for BTreeMap<K, V>
where K: serde::Deserialize + Eq + Ord,
V: serde::Deserialize,
@@ -447,7 +549,7 @@ impl<K, V> serde::Deserialize for BTreeMap<K, V>
fn deserialize<D>(deserializer: &mut D) -> Result<BTreeMap<K, V>, D::Error>
where D: serde::Deserializer,
{
deserializer.visit(BTreeMapVisitor::new())
deserializer.deserialize(BTreeMapVisitor::new())
}
}
@@ -489,7 +591,6 @@ impl<K, V> serde::de::Visitor for BTreeMapVisitor<K, V>
Ok(values)
}
}
```
Deserializing structs goes a step further in order to support not allocating a
@@ -499,7 +600,9 @@ before, we need to generate:
```rust
extern crate serde;
extern crate serde_json;
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
@@ -525,12 +628,12 @@ impl serde::Deserialize for PointField {
match value {
"x" => Ok(PointField::X),
"y" => Ok(PointField::Y),
_ => Err(serde::de::Error::syntax("expected x or y")),
_ => Err(serde::de::Error::custom("expected x or y")),
}
}
}
deserializer.visit(PointFieldVisitor)
deserializer.deserialize(PointFieldVisitor)
}
}
@@ -539,7 +642,7 @@ impl serde::Deserialize for Point {
where D: serde::de::Deserializer
{
static FIELDS: &'static [&'static str] = &["x", "y"];
deserializer.visit_struct("Point", FIELDS, PointVisitor)
deserializer.deserialize_struct("Point", FIELDS, PointVisitor)
}
}
@@ -577,6 +680,78 @@ impl serde::de::Visitor for PointVisitor {
Ok(Point{ x: x, y: y })
}
}
fn main() {
let serialized = "{\"x\":1,\"y\":2}";
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
println!("{:?}", deserialized);
}
```
Design Considerations and tradeoffs for Serializers and Deserializers
=====================================================================
Serde serialization and deserialization implementations are written in such a
way that they err on being able to represent more values, and also provide
better error messages when they are passed an incorrect type to deserialize
from. For example, by default, it is a syntax error to deserialize a `String`
into an `Option<String>`. This is implemented such that it is possible to
distinguish between the values `None` and `Some(())`, if the serialization
format supports option types.
However, many formats do not have option types, and represents optional values
as either a `null`, or some other value. Serde `Serializer`s and
`Deserializer`s can opt-in support for this. For serialization, this is pretty
easy. Simply implement these methods:
```rust,ignore
...
fn visit_none(&mut self) -> Result<(), Self::Error> {
self.visit_unit()
}
fn visit_some<T>(&mut self, value: T) -> Result<(), Self::Error> {
value.serialize(self)
}
...
```
For deserialization, this can be implemented by way of the
`Deserializer::visit_option` hook, which presumes that there is some ability to peek at what is the
next value in the serialized token stream. This following example is from
[serde_tests::TokenDeserializer](https://github.com/serde-rs/serde/blob/master/serde_tests/tests/token.rs#L435-L454),
where it checks to see if the next value is an `Option`, a `()`, or some other
value:
```rust,ignore
...
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.tokens.peek() {
Some(&Token::Option(false)) => {
self.tokens.next();
visitor.visit_none()
}
Some(&Token::Option(true)) => {
self.tokens.next();
visitor.visit_some(self)
}
Some(&Token::Unit) => {
self.tokens.next();
visitor.visit_none()
}
Some(_) => visitor.visit_some(self),
None => Err(Error::EndOfStreamError),
}
}
...
```
Annotations
@@ -585,22 +760,72 @@ Annotations
`serde_codegen` and `serde_macros` support annotations that help to customize
how types are serialized. Here are the supported annotations:
| Annotation | Function |
| ---------- | -------- |
| `#[serde(rename(json="name1", xml="name2"))` | Serialize this field with the given name for the given formats |
| `#[serde(default)` | If the value is not specified, use the `Default::default()` |
| `#[serde(rename="name")` | Serialize this field with the given name |
| `#[serde(skip_serializing)` | Do not serialize this value |
| `#[serde(skip_serializing_if_empty)` | Do not serialize this value if `$value.is_empty()` is `true` |
| `#[serde(skip_serializing_if_none)` | Do not serialize this value if `$value.is_none()` is `true` |
Container Annotations:
| Annotation | Function |
| ---------- | -------- |
| `#[serde(rename="name")]` | Serialize and deserialize this container with the given name |
| `#[serde(rename(serialize="name1"))]` | Serialize this container with the given name |
| `#[serde(rename(deserialize="name1"))]` | Deserialize this container with the given name |
| `#[serde(deny_unknown_fields)]` | Always error during serialization when encountering unknown fields. When absent, unknown fields are ignored for self-describing formats like JSON. |
| `#[serde(bound="T: MyTrait")]` | Where-clause for the Serialize and Deserialize impls. This replaces any bounds inferred by Serde. |
| `#[serde(bound(serialize="T: MyTrait"))]` | Where-clause for the Serialize impl. |
| `#[serde(bound(deserialize="T: MyTrait"))]` | Where-clause for the Deserialize impl. |
Variant Annotations:
| Annotation | Function |
| ---------- | -------- |
| `#[serde(rename="name")]` | Serialize and deserialize this variant with the given name |
| `#[serde(rename(serialize="name1"))]` | Serialize this variant with the given name |
| `#[serde(rename(deserialize="name1"))]` | Deserialize this variant with the given name |
Field Annotations:
| Annotation | Function |
| ---------- | -------- |
| `#[serde(rename="name")]` | Serialize and deserialize this field with the given name |
| `#[serde(rename(serialize="name1"))]` | Serialize this field with the given name |
| `#[serde(rename(deserialize="name1"))]` | Deserialize this field with the given name |
| `#[serde(default)]` | If the value is not specified, use the `Default::default()` |
| `#[serde(default="$path")]` | Call the path to a function `fn() -> T` to build the value |
| `#[serde(skip_serializing)]` | Do not serialize this value |
| `#[serde(skip_deserializing)]` | Always use `Default::default()` or `#[serde(default="$path")]` instead of deserializing this value |
| `#[serde(skip_serializing_if="$path")]` | Do not serialize this value if this function `fn(&T) -> bool` returns `true` |
| `#[serde(serialize_with="$path")]` | Call a function `fn<S>(&T, &mut S) -> Result<(), S::Error> where S: Serializer` to serialize this value of type `T` |
| `#[serde(deserialize_with="$path")]` | Call a function `fn<D>(&mut D) -> Result<T, D::Error> where D: Deserializer` to deserialize this value of type `T` |
| `#[serde(bound="T: MyTrait")]` | Where-clause for the Serialize and Deserialize impls. This replaces any bounds inferred by Serde for the current field. |
| `#[serde(bound(serialize="T: MyTrait"))]` | Where-clause for the Serialize impl. |
| `#[serde(bound(deserialize="T: MyTrait"))]` | Where-clause for the Deserialize impl. |
Using in `no_std` crates
========================
The core `serde` package defines a number of features to enable usage in a
variety of freestanding environments. Enable any or none of the following
features, and use `default-features = false` in your `Cargo.toml`:
- `alloc` (implies `nightly`)
- `collections` (implies `alloc` and `nightly`)
- `std` (default)
If you only use `default-features = false`, you will receive a stock `no_std`
serde with no support for any of the collection types.
Upgrading from Serde 0.6
========================
* `#[serde(skip_serializing_if_none)]` was replaced with `#[serde(skip_serializing_if="Option::is_none")]`.
* `#[serde(skip_serializing_if_empty)]` was replaced with `#[serde(skip_serializing_if="Vec::is_empty")]`.
Serialization Formats Using Serde
=================================
| Format | Name |
| ------ | ---- |
| Bincode | [bincode](https://crates.io/crates/bincode) |
| JSON | [serde\_json](https://crates.io/crates/serde_json) |
| MessagePack | [rmp](https://crates.io/crates/rmp) |
| XML | [serde\_xml](https://github.com/serde-rs/xml) |
| YAML | [serde\_yaml](https://github.com/serde-rs/yaml/) |
| Format | Name |
| ------ | ---- |
| Bincode | [bincode](https://crates.io/crates/bincode) |
| env vars | [envy](https://crates.io/crates/envy) |
| JSON | [serde\_json](https://crates.io/crates/serde_json) |
| MessagePack | [rmp](https://crates.io/crates/rmp) |
| XML | [serde\_xml](https://github.com/serde-rs/xml) |
| YAML | [serde\_yaml](https://github.com/dtolnay/serde-yaml) |
+2
View File
@@ -0,0 +1,2 @@
target
Cargo.lock
+17
View File
@@ -0,0 +1,17 @@
[package]
name = "serde-syntex-example"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
build = "build.rs"
[features]
default = ["serde_codegen"]
nightly = ["serde_macros"]
[build-dependencies]
serde_codegen = { version = "^0.7", optional = true }
[dependencies]
serde = "^0.7"
serde_json = "^0.7"
serde_macros = { version = "^0.7", optional = true }
+20
View File
@@ -0,0 +1,20 @@
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 nightly --no-default-features
```
+25
View File
@@ -0,0 +1,25 @@
#[cfg(not(feature = "serde_macros"))]
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_macros")]
mod inner {
pub fn main() {}
}
fn main() {
inner::main();
}
+11
View File
@@ -0,0 +1,11 @@
#![cfg_attr(feature = "serde_macros", feature(custom_derive, plugin))]
#![cfg_attr(feature = "serde_macros", plugin(serde_macros))]
extern crate serde;
extern crate serde_json;
#[cfg(feature = "serde_macros")]
include!("main.rs.in");
#[cfg(not(feature = "serde_macros"))]
include!(concat!(env!("OUT_DIR"), "/main.rs"));
@@ -0,0 +1,16 @@
#[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);
}
+12 -5
View File
@@ -1,16 +1,23 @@
[package]
name = "serde"
version = "0.6.1"
version = "0.7.15"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde-rs.github.io/serde/serde/serde/index.html"
documentation = "https://serde-rs.github.io/serde/serde/"
readme = "../README.md"
keywords = ["serde", "serialization"]
[dependencies]
num = "^0.1.27"
include = ["Cargo.toml", "src/**/*.rs"]
[features]
default = ["std"]
std = []
nightly = []
alloc = ["nightly"]
collections = ["alloc"]
nightly-testing = ["clippy", "nightly", "std"]
[dependencies]
clippy = { version = "^0.*", optional = true }
+160 -136
View File
@@ -1,11 +1,15 @@
//! Helper module to enable serializing bytes more efficiently
use std::ops;
use std::fmt;
use std::ascii;
use core::{ops, fmt, char, iter, slice};
use core::fmt::Write;
use ser;
use de;
#[cfg(any(feature = "std", feature = "collections"))]
pub use self::bytebuf::{ByteBuf, ByteBufVisitor};
#[cfg(feature = "collections")]
use collections::Vec;
///////////////////////////////////////////////////////////////////////////////
@@ -17,7 +21,11 @@ pub struct Bytes<'a> {
impl<'a> fmt::Debug for Bytes<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "b\"{}\"", escape_bytestring(self.bytes))
try!(f.write_str("b\""));
for c in escape_bytestring(self.bytes) {
try!(f.write_char(c));
}
f.write_char('"')
}
}
@@ -29,10 +37,11 @@ impl<'a> From<&'a [u8]> for Bytes<'a> {
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a> From<&'a Vec<u8>> for Bytes<'a> {
fn from(bytes: &'a Vec<u8>) -> Self {
Bytes {
bytes: &bytes,
bytes: bytes,
}
}
}
@@ -54,163 +63,178 @@ impl<'a> ser::Serialize for Bytes<'a> {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: ser::Serializer
{
serializer.visit_bytes(self.bytes)
serializer.serialize_bytes(self.bytes)
}
}
///////////////////////////////////////////////////////////////////////////////
/// `ByteBuf` wraps a `Vec<u8>` and serializes as a byte array.
#[derive(Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct ByteBuf {
bytes: Vec<u8>,
}
#[cfg(any(feature = "std", feature = "collections"))]
mod bytebuf {
use core::ops;
use core::fmt;
use core::fmt::Write;
impl ByteBuf {
/// Construct a new, empty `ByteBuf`.
pub fn new() -> Self {
ByteBuf {
bytes: Vec::new(),
use ser;
use de;
#[cfg(feature = "collections")]
use collections::Vec;
/// `ByteBuf` wraps a `Vec<u8>` and serializes as a byte array.
#[derive(Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct ByteBuf {
bytes: Vec<u8>,
}
impl ByteBuf {
/// Construct a new, empty `ByteBuf`.
pub fn new() -> Self {
ByteBuf {
bytes: Vec::new(),
}
}
/// Construct a new, empty `ByteBuf` with the specified capacity.
pub fn with_capacity(cap: usize) -> Self {
ByteBuf {
bytes: Vec::with_capacity(cap)
}
}
}
/// Construct a new, empty `ByteBuf` with the specified capacity.
pub fn with_capacity(cap: usize) -> Self {
ByteBuf {
bytes: Vec::with_capacity(cap)
impl fmt::Debug for ByteBuf {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(f.write_str("b\""));
for c in super::escape_bytestring(self.bytes.as_ref()) {
try!(f.write_char(c));
}
f.write_char('"')
}
}
}
impl fmt::Debug for ByteBuf {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "b\"{}\"", escape_bytestring(self.bytes.as_ref()))
}
}
impl Into<Vec<u8>> for ByteBuf {
fn into(self) -> Vec<u8> {
self.bytes
}
}
impl From<Vec<u8>> for ByteBuf {
fn from(bytes: Vec<u8>) -> Self {
ByteBuf {
bytes: bytes,
impl Into<Vec<u8>> for ByteBuf {
fn into(self) -> Vec<u8> {
self.bytes
}
}
}
impl AsRef<Vec<u8>> for ByteBuf {
fn as_ref(&self) -> &Vec<u8> {
&self.bytes
}
}
impl AsRef<[u8]> for ByteBuf {
fn as_ref(&self) -> &[u8] {
&self.bytes
}
}
impl AsMut<Vec<u8>> for ByteBuf {
fn as_mut(&mut self) -> &mut Vec<u8> {
&mut self.bytes
}
}
impl AsMut<[u8]> for ByteBuf {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.bytes
}
}
impl ops::Deref for ByteBuf {
type Target = [u8];
fn deref(&self) -> &[u8] { &self.bytes[..] }
}
impl ops::DerefMut for ByteBuf {
fn deref_mut(&mut self) -> &mut [u8] { &mut self.bytes[..] }
}
impl ser::Serialize for ByteBuf {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: ser::Serializer
{
serializer.visit_bytes(&self)
}
}
/// This type implements the `serde::de::Visitor` trait for a `ByteBuf`.
pub struct ByteBufVisitor;
impl de::Visitor for ByteBufVisitor {
type Value = ByteBuf;
#[inline]
fn visit_unit<E>(&mut self) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf {
bytes: Vec::new(),
})
impl From<Vec<u8>> for ByteBuf {
fn from(bytes: Vec<u8>) -> Self {
ByteBuf {
bytes: bytes,
}
}
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<ByteBuf, V::Error>
where V: de::SeqVisitor,
{
let (len, _) = visitor.size_hint();
let mut values = Vec::with_capacity(len);
impl AsRef<Vec<u8>> for ByteBuf {
fn as_ref(&self) -> &Vec<u8> {
&self.bytes
}
}
while let Some(value) = try!(visitor.visit()) {
values.push(value);
impl AsRef<[u8]> for ByteBuf {
fn as_ref(&self) -> &[u8] {
&self.bytes
}
}
impl AsMut<Vec<u8>> for ByteBuf {
fn as_mut(&mut self) -> &mut Vec<u8> {
&mut self.bytes
}
}
impl AsMut<[u8]> for ByteBuf {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.bytes
}
}
impl ops::Deref for ByteBuf {
type Target = [u8];
fn deref(&self) -> &[u8] { &self.bytes[..] }
}
impl ops::DerefMut for ByteBuf {
fn deref_mut(&mut self) -> &mut [u8] { &mut self.bytes[..] }
}
impl ser::Serialize for ByteBuf {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: ser::Serializer
{
serializer.serialize_bytes(self)
}
}
/// This type implements the `serde::de::Visitor` trait for a `ByteBuf`.
pub struct ByteBufVisitor;
impl de::Visitor for ByteBufVisitor {
type Value = ByteBuf;
#[inline]
fn visit_unit<E>(&mut self) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf {
bytes: Vec::new(),
})
}
try!(visitor.end());
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<ByteBuf, V::Error>
where V: de::SeqVisitor,
{
let (len, _) = visitor.size_hint();
let mut values = Vec::with_capacity(len);
Ok(ByteBuf {
bytes: values,
})
while let Some(value) = try!(visitor.visit()) {
values.push(value);
}
try!(visitor.end());
Ok(ByteBuf {
bytes: values,
})
}
#[inline]
fn visit_bytes<E>(&mut self, v: &[u8]) -> Result<ByteBuf, E>
where E: de::Error,
{
self.visit_byte_buf(v.to_vec())
}
#[inline]
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf {
bytes: v,
})
}
}
#[inline]
fn visit_bytes<E>(&mut self, v: &[u8]) -> Result<ByteBuf, E>
where E: de::Error,
{
self.visit_byte_buf(v.to_vec())
}
#[inline]
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf {
bytes: v,
})
}
}
impl de::Deserialize for ByteBuf {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<ByteBuf, D::Error>
where D: de::Deserializer
{
deserializer.visit_bytes(ByteBufVisitor)
impl de::Deserialize for ByteBuf {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<ByteBuf, D::Error>
where D: de::Deserializer
{
deserializer.deserialize_bytes(ByteBufVisitor)
}
}
}
///////////////////////////////////////////////////////////////////////////////
fn escape_bytestring(bytes: &[u8]) -> String {
let mut result = String::new();
for &b in bytes {
for esc in ascii::escape_default(b) {
result.push(esc as char);
}
#[inline]
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()
}
result
bytes.iter().flat_map(f as fn(&u8) -> char::EscapeDefault)
}
+409
View File
@@ -0,0 +1,409 @@
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Extracted from https://github.com/rust-num/num.
// Rust 1.5 is unhappy that this private module is undocumented.
#![allow(missing_docs)]
use core::{usize, u8, u16, u32, u64};
use core::{isize, i8, i16, i32, i64};
use core::{f32, f64};
use core::mem::size_of;
/// Numbers which have upper and lower bounds
pub trait Bounded {
// FIXME (#5527): These should be associated constants
/// returns the smallest finite number this type can represent
fn min_value() -> Self;
/// returns the largest finite number this type can represent
fn max_value() -> Self;
}
macro_rules! bounded_impl {
($t:ty, $min:expr, $max:expr) => {
impl Bounded for $t {
#[inline]
fn min_value() -> $t { $min }
#[inline]
fn max_value() -> $t { $max }
}
}
}
bounded_impl!(usize, usize::MIN, usize::MAX);
bounded_impl!(u8, u8::MIN, u8::MAX);
bounded_impl!(u16, u16::MIN, u16::MAX);
bounded_impl!(u32, u32::MIN, u32::MAX);
bounded_impl!(u64, u64::MIN, u64::MAX);
bounded_impl!(isize, isize::MIN, isize::MAX);
bounded_impl!(i8, i8::MIN, i8::MAX);
bounded_impl!(i16, i16::MIN, i16::MAX);
bounded_impl!(i32, i32::MIN, i32::MAX);
bounded_impl!(i64, i64::MIN, i64::MAX);
bounded_impl!(f32, f32::MIN, f32::MAX);
bounded_impl!(f64, f64::MIN, f64::MAX);
/// A generic trait for converting a value to a number.
pub trait ToPrimitive {
/// Converts the value of `self` to an `isize`.
#[inline]
fn to_isize(&self) -> Option<isize> {
self.to_i64().and_then(|x| x.to_isize())
}
/// Converts the value of `self` to an `i8`.
#[inline]
fn to_i8(&self) -> Option<i8> {
self.to_i64().and_then(|x| x.to_i8())
}
/// Converts the value of `self` to an `i16`.
#[inline]
fn to_i16(&self) -> Option<i16> {
self.to_i64().and_then(|x| x.to_i16())
}
/// Converts the value of `self` to an `i32`.
#[inline]
fn to_i32(&self) -> Option<i32> {
self.to_i64().and_then(|x| x.to_i32())
}
/// Converts the value of `self` to an `i64`.
fn to_i64(&self) -> Option<i64>;
/// Converts the value of `self` to a `usize`.
#[inline]
fn to_usize(&self) -> Option<usize> {
self.to_u64().and_then(|x| x.to_usize())
}
/// Converts the value of `self` to an `u8`.
#[inline]
fn to_u8(&self) -> Option<u8> {
self.to_u64().and_then(|x| x.to_u8())
}
/// Converts the value of `self` to an `u16`.
#[inline]
fn to_u16(&self) -> Option<u16> {
self.to_u64().and_then(|x| x.to_u16())
}
/// Converts the value of `self` to an `u32`.
#[inline]
fn to_u32(&self) -> Option<u32> {
self.to_u64().and_then(|x| x.to_u32())
}
/// Converts the value of `self` to an `u64`.
#[inline]
fn to_u64(&self) -> Option<u64>;
/// Converts the value of `self` to an `f32`.
#[inline]
fn to_f32(&self) -> Option<f32> {
self.to_f64().and_then(|x| x.to_f32())
}
/// Converts the value of `self` to an `f64`.
#[inline]
fn to_f64(&self) -> Option<f64> {
self.to_i64().and_then(|x| x.to_f64())
}
}
macro_rules! impl_to_primitive_int_to_int {
($SrcT:ty, $DstT:ty, $slf:expr) => (
{
if size_of::<$SrcT>() <= size_of::<$DstT>() {
Some($slf as $DstT)
} else {
let n = $slf as i64;
let min_value: $DstT = Bounded::min_value();
let max_value: $DstT = Bounded::max_value();
if min_value as i64 <= n && n <= max_value as i64 {
Some($slf as $DstT)
} else {
None
}
}
}
)
}
macro_rules! impl_to_primitive_int_to_uint {
($SrcT:ty, $DstT:ty, $slf:expr) => (
{
let zero: $SrcT = 0;
let max_value: $DstT = Bounded::max_value();
if zero <= $slf && $slf as u64 <= max_value as u64 {
Some($slf as $DstT)
} else {
None
}
}
)
}
macro_rules! impl_to_primitive_int {
($T:ty) => (
impl ToPrimitive for $T {
#[inline]
fn to_isize(&self) -> Option<isize> { impl_to_primitive_int_to_int!($T, isize, *self) }
#[inline]
fn to_i8(&self) -> Option<i8> { impl_to_primitive_int_to_int!($T, i8, *self) }
#[inline]
fn to_i16(&self) -> Option<i16> { impl_to_primitive_int_to_int!($T, i16, *self) }
#[inline]
fn to_i32(&self) -> Option<i32> { impl_to_primitive_int_to_int!($T, i32, *self) }
#[inline]
fn to_i64(&self) -> Option<i64> { impl_to_primitive_int_to_int!($T, i64, *self) }
#[inline]
fn to_usize(&self) -> Option<usize> { impl_to_primitive_int_to_uint!($T, usize, *self) }
#[inline]
fn to_u8(&self) -> Option<u8> { impl_to_primitive_int_to_uint!($T, u8, *self) }
#[inline]
fn to_u16(&self) -> Option<u16> { impl_to_primitive_int_to_uint!($T, u16, *self) }
#[inline]
fn to_u32(&self) -> Option<u32> { impl_to_primitive_int_to_uint!($T, u32, *self) }
#[inline]
fn to_u64(&self) -> Option<u64> { impl_to_primitive_int_to_uint!($T, u64, *self) }
#[inline]
fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
#[inline]
fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
}
)
}
impl_to_primitive_int! { isize }
impl_to_primitive_int! { i8 }
impl_to_primitive_int! { i16 }
impl_to_primitive_int! { i32 }
impl_to_primitive_int! { i64 }
macro_rules! impl_to_primitive_uint_to_int {
($DstT:ty, $slf:expr) => (
{
let max_value: $DstT = Bounded::max_value();
if $slf as u64 <= max_value as u64 {
Some($slf as $DstT)
} else {
None
}
}
)
}
macro_rules! impl_to_primitive_uint_to_uint {
($SrcT:ty, $DstT:ty, $slf:expr) => (
{
if size_of::<$SrcT>() <= size_of::<$DstT>() {
Some($slf as $DstT)
} else {
let zero: $SrcT = 0;
let max_value: $DstT = Bounded::max_value();
if zero <= $slf && $slf as u64 <= max_value as u64 {
Some($slf as $DstT)
} else {
None
}
}
}
)
}
macro_rules! impl_to_primitive_uint {
($T:ty) => (
impl ToPrimitive for $T {
#[inline]
fn to_isize(&self) -> Option<isize> { impl_to_primitive_uint_to_int!(isize, *self) }
#[inline]
fn to_i8(&self) -> Option<i8> { impl_to_primitive_uint_to_int!(i8, *self) }
#[inline]
fn to_i16(&self) -> Option<i16> { impl_to_primitive_uint_to_int!(i16, *self) }
#[inline]
fn to_i32(&self) -> Option<i32> { impl_to_primitive_uint_to_int!(i32, *self) }
#[inline]
fn to_i64(&self) -> Option<i64> { impl_to_primitive_uint_to_int!(i64, *self) }
#[inline]
fn to_usize(&self) -> Option<usize> {
impl_to_primitive_uint_to_uint!($T, usize, *self)
}
#[inline]
fn to_u8(&self) -> Option<u8> { impl_to_primitive_uint_to_uint!($T, u8, *self) }
#[inline]
fn to_u16(&self) -> Option<u16> { impl_to_primitive_uint_to_uint!($T, u16, *self) }
#[inline]
fn to_u32(&self) -> Option<u32> { impl_to_primitive_uint_to_uint!($T, u32, *self) }
#[inline]
fn to_u64(&self) -> Option<u64> { impl_to_primitive_uint_to_uint!($T, u64, *self) }
#[inline]
fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
#[inline]
fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
}
)
}
impl_to_primitive_uint! { usize }
impl_to_primitive_uint! { u8 }
impl_to_primitive_uint! { u16 }
impl_to_primitive_uint! { u32 }
impl_to_primitive_uint! { u64 }
macro_rules! impl_to_primitive_float_to_float {
($SrcT:ident, $DstT:ident, $slf:expr) => (
if size_of::<$SrcT>() <= size_of::<$DstT>() {
Some($slf as $DstT)
} else {
let n = $slf as f64;
let max_value: $SrcT = ::core::$SrcT::MAX;
if -max_value as f64 <= n && n <= max_value as f64 {
Some($slf as $DstT)
} else {
None
}
}
)
}
macro_rules! impl_to_primitive_float {
($T:ident) => (
impl ToPrimitive for $T {
#[inline]
fn to_isize(&self) -> Option<isize> { Some(*self as isize) }
#[inline]
fn to_i8(&self) -> Option<i8> { Some(*self as i8) }
#[inline]
fn to_i16(&self) -> Option<i16> { Some(*self as i16) }
#[inline]
fn to_i32(&self) -> Option<i32> { Some(*self as i32) }
#[inline]
fn to_i64(&self) -> Option<i64> { Some(*self as i64) }
#[inline]
fn to_usize(&self) -> Option<usize> { Some(*self as usize) }
#[inline]
fn to_u8(&self) -> Option<u8> { Some(*self as u8) }
#[inline]
fn to_u16(&self) -> Option<u16> { Some(*self as u16) }
#[inline]
fn to_u32(&self) -> Option<u32> { Some(*self as u32) }
#[inline]
fn to_u64(&self) -> Option<u64> { Some(*self as u64) }
#[inline]
fn to_f32(&self) -> Option<f32> { impl_to_primitive_float_to_float!($T, f32, *self) }
#[inline]
fn to_f64(&self) -> Option<f64> { impl_to_primitive_float_to_float!($T, f64, *self) }
}
)
}
impl_to_primitive_float! { f32 }
impl_to_primitive_float! { f64 }
pub trait FromPrimitive: Sized {
#[inline]
fn from_isize(n: isize) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
#[inline]
fn from_i8(n: i8) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
fn from_i64(n: i64) -> Option<Self>;
#[inline]
fn from_usize(n: usize) -> Option<Self> {
FromPrimitive::from_u64(n as u64)
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
FromPrimitive::from_u64(n as u64)
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
FromPrimitive::from_u64(n as u64)
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
FromPrimitive::from_u64(n as u64)
}
fn from_u64(n: u64) -> Option<Self>;
#[inline]
fn from_f32(n: f32) -> Option<Self> {
FromPrimitive::from_f64(n as f64)
}
#[inline]
fn from_f64(n: f64) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
}
macro_rules! impl_from_primitive {
($T:ty, $to_ty:ident) => (
impl FromPrimitive for $T {
#[inline] fn from_i8(n: i8) -> Option<$T> { n.$to_ty() }
#[inline] fn from_i16(n: i16) -> Option<$T> { n.$to_ty() }
#[inline] fn from_i32(n: i32) -> Option<$T> { n.$to_ty() }
#[inline] fn from_i64(n: i64) -> Option<$T> { n.$to_ty() }
#[inline] fn from_u8(n: u8) -> Option<$T> { n.$to_ty() }
#[inline] fn from_u16(n: u16) -> Option<$T> { n.$to_ty() }
#[inline] fn from_u32(n: u32) -> Option<$T> { n.$to_ty() }
#[inline] fn from_u64(n: u64) -> Option<$T> { n.$to_ty() }
#[inline] fn from_f32(n: f32) -> Option<$T> { n.$to_ty() }
#[inline] fn from_f64(n: f64) -> Option<$T> { n.$to_ty() }
}
)
}
impl_from_primitive! { isize, to_isize }
impl_from_primitive! { i8, to_i8 }
impl_from_primitive! { i16, to_i16 }
impl_from_primitive! { i32, to_i32 }
impl_from_primitive! { i64, to_i64 }
impl_from_primitive! { usize, to_usize }
impl_from_primitive! { u8, to_u8 }
impl_from_primitive! { u16, to_u16 }
impl_from_primitive! { u32, to_u32 }
impl_from_primitive! { u64, to_u64 }
impl_from_primitive! { f32, to_f32 }
impl_from_primitive! { f64, to_f64 }
+397 -107
View File
@@ -1,31 +1,63 @@
//! This module contains `Deserialize` and `Visitor` implementations.
#[cfg(feature = "std")]
use std::borrow::Cow;
use std::collections::{
#[cfg(all(feature = "nightly", feature = "collections", not(feature = "std")))]
use collections::borrow::Cow;
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::{
BinaryHeap,
BTreeMap,
BTreeSet,
LinkedList,
VecDeque,
Vec,
String,
};
#[cfg(feature = "std")]
use std::collections::{
HashMap,
HashSet,
BinaryHeap,
BTreeMap,
BTreeSet,
LinkedList,
VecDeque,
};
#[cfg(feature = "nightly")]
use collections::enum_set::{CLike, EnumSet};
use std::hash::Hash;
use std::marker::PhantomData;
use std::path;
use std::rc::Rc;
use std::str;
use std::sync::Arc;
use num::FromPrimitive;
#[cfg(all(feature = "nightly", feature = "collections"))]
use collections::enum_set::{CLike, EnumSet};
#[cfg(all(feature = "nightly", feature = "collections"))]
use collections::borrow::ToOwned;
use core::hash::{Hash, BuildHasher};
use core::marker::PhantomData;
#[cfg(feature = "std")]
use std::net;
#[cfg(feature = "std")]
use std::path;
use core::str;
#[cfg(feature = "std")]
use std::rc::Rc;
#[cfg(all(feature = "nightly", feature = "alloc", not(feature = "std")))]
use alloc::rc::Rc;
#[cfg(feature = "std")]
use std::sync::Arc;
#[cfg(all(feature = "nightly", feature = "alloc", not(feature = "std")))]
use alloc::arc::Arc;
#[cfg(all(feature = "nightly", feature = "alloc", not(feature = "std")))]
use alloc::boxed::Box;
#[cfg(feature = "nightly")]
use core::nonzero::{NonZero, Zeroable};
#[cfg(feature = "nightly")]
use std::num::Zero;
use core::num::Zero;
use de::{
Deserialize,
@@ -38,6 +70,7 @@ use de::{
VariantVisitor,
Visitor,
};
use de::from_primitive::FromPrimitive;
///////////////////////////////////////////////////////////////////////////////
@@ -64,7 +97,7 @@ impl Deserialize for () {
fn deserialize<D>(deserializer: &mut D) -> Result<(), D::Error>
where D: Deserializer,
{
deserializer.visit_unit(UnitVisitor)
deserializer.deserialize_unit(UnitVisitor)
}
}
@@ -85,10 +118,10 @@ impl Visitor for BoolVisitor {
fn visit_str<E>(&mut self, s: &str) -> Result<bool, E>
where E: Error,
{
match s.trim() {
match s.trim_matches(::utils::Pattern_White_Space) {
"true" => Ok(true),
"false" => Ok(false),
_ => Err(Error::type_mismatch(Type::Bool)),
_ => Err(Error::invalid_type(Type::Bool)),
}
}
}
@@ -97,7 +130,7 @@ impl Deserialize for bool {
fn deserialize<D>(deserializer: &mut D) -> Result<bool, D::Error>
where D: Deserializer,
{
deserializer.visit_bool(BoolVisitor)
deserializer.deserialize_bool(BoolVisitor)
}
}
@@ -111,30 +144,30 @@ macro_rules! impl_deserialize_num_method {
{
match FromPrimitive::$from_method(v) {
Some(v) => Ok(v),
None => Err(Error::type_mismatch($ty)),
None => Err(Error::invalid_type($ty)),
}
}
}
}
/// A visitor that produces a primitive type.
pub struct PrimitiveVisitor<T> {
struct PrimitiveVisitor<T> {
marker: PhantomData<T>,
}
impl<T> PrimitiveVisitor<T> {
/// Construct a new `PrimitiveVisitor`.
#[inline]
pub fn new() -> Self {
fn new() -> Self {
PrimitiveVisitor {
marker: PhantomData,
}
}
}
impl<
T: Deserialize + FromPrimitive + str::FromStr
> Visitor for PrimitiveVisitor<T> {
impl<T> Visitor for PrimitiveVisitor<T>
where T: Deserialize + FromPrimitive + str::FromStr
{
type Value = T;
impl_deserialize_num_method!(isize, visit_isize, from_isize, Type::Isize);
@@ -151,10 +184,12 @@ impl<
impl_deserialize_num_method!(f64, visit_f64, from_f64, Type::F64);
#[inline]
fn visit_str<E>(&mut self, v: &str) -> Result<T, E>
fn visit_str<E>(&mut self, s: &str) -> Result<T, E>
where E: Error,
{
str::FromStr::from_str(v.trim()).or(Err(Error::type_mismatch(Type::Str)))
str::FromStr::from_str(s.trim_matches(::utils::Pattern_White_Space)).or_else(|_| {
Err(Error::invalid_type(Type::Str))
})
}
}
@@ -171,18 +206,18 @@ macro_rules! impl_deserialize_num {
}
}
impl_deserialize_num!(isize, visit_isize);
impl_deserialize_num!(i8, visit_i8);
impl_deserialize_num!(i16, visit_i16);
impl_deserialize_num!(i32, visit_i32);
impl_deserialize_num!(i64, visit_i64);
impl_deserialize_num!(usize, visit_usize);
impl_deserialize_num!(u8, visit_u8);
impl_deserialize_num!(u16, visit_u16);
impl_deserialize_num!(u32, visit_u32);
impl_deserialize_num!(u64, visit_u64);
impl_deserialize_num!(f32, visit_f32);
impl_deserialize_num!(f64, visit_f64);
impl_deserialize_num!(isize, deserialize_isize);
impl_deserialize_num!(i8, deserialize_i8);
impl_deserialize_num!(i16, deserialize_i16);
impl_deserialize_num!(i32, deserialize_i32);
impl_deserialize_num!(i64, deserialize_i64);
impl_deserialize_num!(usize, deserialize_usize);
impl_deserialize_num!(u8, deserialize_u8);
impl_deserialize_num!(u16, deserialize_u16);
impl_deserialize_num!(u32, deserialize_u32);
impl_deserialize_num!(u64, deserialize_u64);
impl_deserialize_num!(f32, deserialize_f32);
impl_deserialize_num!(f64, deserialize_f64);
///////////////////////////////////////////////////////////////////////////////
@@ -205,7 +240,7 @@ impl Visitor for CharVisitor {
let mut iter = v.chars();
if let Some(v) = iter.next() {
if iter.next().is_some() {
Err(Error::type_mismatch(Type::Char))
Err(Error::invalid_type(Type::Char))
} else {
Ok(v)
}
@@ -220,21 +255,23 @@ impl Deserialize for char {
fn deserialize<D>(deserializer: &mut D) -> Result<char, D::Error>
where D: Deserializer,
{
deserializer.visit_char(CharVisitor)
deserializer.deserialize_char(CharVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))]
struct StringVisitor;
#[cfg(any(feature = "std", feature = "collections"))]
impl Visitor for StringVisitor {
type Value = String;
fn visit_str<E>(&mut self, v: &str) -> Result<String, E>
where E: Error,
{
Ok(v.to_string())
Ok(v.to_owned())
}
fn visit_string<E>(&mut self, v: String) -> Result<String, E>
@@ -247,26 +284,27 @@ impl Visitor for StringVisitor {
where E: Error,
{
match str::from_utf8(v) {
Ok(s) => Ok(s.to_string()),
Err(_) => Err(Error::type_mismatch(Type::String)),
Ok(s) => Ok(s.to_owned()),
Err(_) => Err(Error::invalid_type(Type::String)),
}
}
fn visit_byte_buf<'a, E>(&mut self, v: Vec<u8>) -> Result<String, E>
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<String, E>
where E: Error,
{
match String::from_utf8(v) {
Ok(s) => Ok(s),
Err(_) => Err(Error::type_mismatch(Type::String)),
Err(_) => Err(Error::invalid_type(Type::String)),
}
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl Deserialize for String {
fn deserialize<D>(deserializer: &mut D) -> Result<String, D::Error>
where D: Deserializer,
{
deserializer.visit_string(StringVisitor)
deserializer.deserialize_string(StringVisitor)
}
}
@@ -281,6 +319,13 @@ impl<
> Visitor for OptionVisitor<T> {
type Value = Option<T>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<Option<T>, E>
where E: Error,
{
Ok(None)
}
#[inline]
fn visit_none<E>(&mut self) -> Result<Option<T>, E>
where E: Error,
@@ -300,7 +345,34 @@ impl<T> Deserialize for Option<T> where T: Deserialize {
fn deserialize<D>(deserializer: &mut D) -> Result<Option<T>, D::Error>
where D: Deserializer,
{
deserializer.visit_option(OptionVisitor { marker: PhantomData })
deserializer.deserialize_option(OptionVisitor { marker: PhantomData })
}
}
///////////////////////////////////////////////////////////////////////////////
/// A visitor that produces a `PhantomData`.
pub struct PhantomDataVisitor<T> {
marker: PhantomData<T>,
}
impl<T> Visitor for PhantomDataVisitor<T> where T: Deserialize {
type Value = PhantomData<T>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<PhantomData<T>, E>
where E: Error,
{
Ok(PhantomData)
}
}
impl<T> Deserialize for PhantomData<T> where T: Deserialize {
fn deserialize<D>(deserializer: &mut D) -> Result<PhantomData<T>, D::Error>
where D: Deserializer,
{
let visitor = PhantomDataVisitor { marker: PhantomData };
deserializer.deserialize_unit_struct("PhantomData", visitor)
}
}
@@ -309,29 +381,30 @@ impl<T> Deserialize for Option<T> where T: Deserialize {
macro_rules! seq_impl {
(
$ty:ty,
< $($constraints:ident),* >,
$visitor_name:ident,
$visitor_ty:ident < $($typaram:ident : $bound1:ident $(+ $bound2:ident)*),* >,
$visitor:ident,
$ctor:expr,
$with_capacity:expr,
$insert:expr
) => {
/// A visitor that produces a sequence.
pub struct $visitor_name<T> {
marker: PhantomData<T>,
pub struct $visitor_ty<$($typaram),*> {
marker: PhantomData<$ty>,
}
impl<T> $visitor_name<T> {
impl<$($typaram),*> $visitor_ty<$($typaram),*>
where $($typaram: $bound1 $(+ $bound2)*),*
{
/// Construct a new sequence visitor.
pub fn new() -> Self {
$visitor_name {
$visitor_ty {
marker: PhantomData,
}
}
}
impl<T> Visitor for $visitor_name<T>
where T: $($constraints +)*,
impl<$($typaram),*> Visitor for $visitor_ty<$($typaram),*>
where $($typaram: $bound1 $(+ $bound2)*),*
{
type Value = $ty;
@@ -358,77 +431,77 @@ macro_rules! seq_impl {
}
}
impl<T> Deserialize for $ty
where T: $($constraints +)*,
impl<$($typaram),*> Deserialize for $ty
where $($typaram: $bound1 $(+ $bound2)*),*
{
fn deserialize<D>(deserializer: &mut D) -> Result<$ty, D::Error>
where D: Deserializer,
{
deserializer.visit_seq($visitor_name::new())
deserializer.deserialize_seq($visitor_ty::new())
}
}
}
}
#[cfg(any(feature = "std", feature = "collections"))]
seq_impl!(
BinaryHeap<T>,
<Deserialize, Ord>,
BinaryHeapVisitor,
BinaryHeapVisitor<T: Deserialize + Ord>,
visitor,
BinaryHeap::new(),
BinaryHeap::with_capacity(visitor.size_hint().0),
BinaryHeap::push);
#[cfg(any(feature = "std", feature = "collections"))]
seq_impl!(
BTreeSet<T>,
<Deserialize, Eq, Ord>,
BTreeSetVisitor,
BTreeSetVisitor<T: Deserialize + Eq + Ord>,
visitor,
BTreeSet::new(),
BTreeSet::new(),
BTreeSet::insert);
#[cfg(feature = "nightly")]
#[cfg(all(feature = "nightly", feature = "collections"))]
seq_impl!(
EnumSet<T>,
<Deserialize, CLike>,
EnumSetVisitor,
EnumSetVisitor<T: Deserialize + CLike>,
visitor,
EnumSet::new(),
EnumSet::new(),
EnumSet::insert);
#[cfg(any(feature = "std", feature = "collections"))]
seq_impl!(
LinkedList<T>,
<Deserialize>,
LinkedListVisitor,
LinkedListVisitor<T: Deserialize>,
visitor,
LinkedList::new(),
LinkedList::new(),
LinkedList::push_back);
#[cfg(feature = "std")]
seq_impl!(
HashSet<T>,
<Deserialize, Eq, Hash>,
HashSetVisitor,
HashSet<T, S>,
HashSetVisitor<T: Deserialize + Eq + Hash,
S: BuildHasher + Default>,
visitor,
HashSet::new(),
HashSet::with_capacity(visitor.size_hint().0),
HashSet::with_hasher(S::default()),
HashSet::with_capacity_and_hasher(visitor.size_hint().0, S::default()),
HashSet::insert);
#[cfg(any(feature = "std", feature = "collections"))]
seq_impl!(
Vec<T>,
<Deserialize>,
VecVisitor,
VecVisitor<T: Deserialize>,
visitor,
Vec::new(),
Vec::with_capacity(visitor.size_hint().0),
Vec::push);
#[cfg(any(feature = "std", feature = "collections"))]
seq_impl!(
VecDeque<T>,
<Deserialize>,
VecDequeVisitor,
VecDequeVisitor<T: Deserialize>,
visitor,
VecDeque::new(),
VecDeque::with_capacity(visitor.size_hint().0),
@@ -474,7 +547,7 @@ impl<T> Deserialize for [T; 0]
fn deserialize<D>(deserializer: &mut D) -> Result<[T; 0], D::Error>
where D: Deserializer,
{
deserializer.visit_seq(ArrayVisitor0::new())
deserializer.deserialize_seq(ArrayVisitor0::new())
}
}
@@ -520,7 +593,7 @@ macro_rules! array_impls {
fn deserialize<D>(deserializer: &mut D) -> Result<[T; $len], D::Error>
where D: Deserializer,
{
deserializer.visit_seq($visitor::new())
deserializer.deserialize_fixed_size_array($len, $visitor::new())
}
}
)+
@@ -573,7 +646,6 @@ array_impls! {
///////////////////////////////////////////////////////////////////////////////
macro_rules! tuple_impls {
() => {};
($($len:expr => $visitor:ident => ($($name:ident),+),)+) => {
$(
/// Construct a tuple visitor.
@@ -621,7 +693,7 @@ macro_rules! tuple_impls {
fn deserialize<D>(deserializer: &mut D) -> Result<($($name,)+), D::Error>
where D: Deserializer,
{
deserializer.visit_tuple($len, $visitor::new())
deserializer.deserialize_tuple($len, $visitor::new())
}
}
)+
@@ -641,6 +713,10 @@ tuple_impls! {
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),
}
///////////////////////////////////////////////////////////////////////////////
@@ -648,30 +724,29 @@ tuple_impls! {
macro_rules! map_impl {
(
$ty:ty,
< $($constraints:ident),* >,
$visitor_name:ident,
$visitor_ty:ident < $($typaram:ident : $bound1:ident $(+ $bound2:ident)*),* >,
$visitor:ident,
$ctor:expr,
$with_capacity:expr,
$insert:expr
$with_capacity:expr
) => {
/// A visitor that produces a map.
pub struct $visitor_name<K, V> {
pub struct $visitor_ty<$($typaram),*> {
marker: PhantomData<$ty>,
}
impl<K, V> $visitor_name<K, V> {
impl<$($typaram),*> $visitor_ty<$($typaram),*>
where $($typaram: $bound1 $(+ $bound2)*),*
{
/// Construct a `MapVisitor*<T>`.
pub fn new() -> Self {
$visitor_name {
$visitor_ty {
marker: PhantomData,
}
}
}
impl<K, V> Visitor for $visitor_name<K, V>
where K: $($constraints +)*,
V: Deserialize,
impl<$($typaram),*> Visitor for $visitor_ty<$($typaram),*>
where $($typaram: $bound1 $(+ $bound2)*),*
{
type Value = $ty;
@@ -689,7 +764,7 @@ macro_rules! map_impl {
let mut values = $with_capacity;
while let Some((key, value)) = try!($visitor.visit()) {
$insert(&mut values, key, value);
values.insert(key, value);
}
try!($visitor.end());
@@ -698,41 +773,125 @@ macro_rules! map_impl {
}
}
impl<K, V> Deserialize for $ty
where K: $($constraints +)*,
V: Deserialize,
impl<$($typaram),*> Deserialize for $ty
where $($typaram: $bound1 $(+ $bound2)*),*
{
fn deserialize<D>(deserializer: &mut D) -> Result<$ty, D::Error>
where D: Deserializer,
{
deserializer.visit_map($visitor_name::new())
deserializer.deserialize_map($visitor_ty::new())
}
}
}
}
#[cfg(any(feature = "std", feature = "collections"))]
map_impl!(
BTreeMap<K, V>,
<Deserialize, Eq, Ord>,
BTreeMapVisitor,
BTreeMapVisitor<K: Deserialize + Eq + Ord,
V: Deserialize>,
visitor,
BTreeMap::new(),
BTreeMap::new(),
BTreeMap::insert);
BTreeMap::new());
#[cfg(feature = "std")]
map_impl!(
HashMap<K, V>,
<Deserialize, Eq, Hash>,
HashMapVisitor,
HashMap<K, V, S>,
HashMapVisitor<K: Deserialize + Eq + Hash,
V: Deserialize,
S: BuildHasher + Default>,
visitor,
HashMap::new(),
HashMap::with_capacity(visitor.size_hint().0),
HashMap::insert);
HashMap::with_hasher(S::default()),
HashMap::with_capacity_and_hasher(visitor.size_hint().0, S::default()));
///////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "nightly", feature = "std"))]
impl Deserialize for net::IpAddr {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer,
{
let s = try!(String::deserialize(deserializer));
match s.parse() {
Ok(s) => Ok(s),
Err(err) => Err(D::Error::invalid_value(&err.to_string())),
}
}
}
#[cfg(feature = "std")]
impl Deserialize for net::Ipv4Addr {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer,
{
let s = try!(String::deserialize(deserializer));
match s.parse() {
Ok(s) => Ok(s),
Err(err) => Err(D::Error::invalid_value(&err.to_string())),
}
}
}
#[cfg(feature = "std")]
impl Deserialize for net::Ipv6Addr {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer,
{
let s = try!(String::deserialize(deserializer));
match s.parse() {
Ok(s) => Ok(s),
Err(err) => Err(D::Error::invalid_value(&err.to_string())),
}
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl Deserialize for net::SocketAddr {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer,
{
let s = try!(String::deserialize(deserializer));
match s.parse() {
Ok(s) => Ok(s),
Err(err) => Err(D::Error::invalid_value(&err.to_string())),
}
}
}
#[cfg(feature = "std")]
impl Deserialize for net::SocketAddrV4 {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer,
{
let s = try!(String::deserialize(deserializer));
match s.parse() {
Ok(s) => Ok(s),
Err(err) => Err(D::Error::invalid_value(&err.to_string())),
}
}
}
#[cfg(feature = "std")]
impl Deserialize for net::SocketAddrV6 {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer,
{
let s = try!(String::deserialize(deserializer));
match s.parse() {
Ok(s) => Ok(s),
Err(err) => Err(D::Error::invalid_value(&err.to_string())),
}
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
struct PathBufVisitor;
#[cfg(feature = "std")]
impl Visitor for PathBufVisitor {
type Value = path::PathBuf;
@@ -749,16 +908,18 @@ impl Visitor for PathBufVisitor {
}
}
#[cfg(feature = "std")]
impl Deserialize for path::PathBuf {
fn deserialize<D>(deserializer: &mut D) -> Result<path::PathBuf, D::Error>
where D: Deserializer,
{
deserializer.visit(PathBufVisitor)
deserializer.deserialize_string(PathBufVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Deserialize> Deserialize for Box<T> {
fn deserialize<D>(deserializer: &mut D) -> Result<Box<T>, D::Error>
where D: Deserializer,
@@ -768,6 +929,17 @@ impl<T: Deserialize> Deserialize for Box<T> {
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T: Deserialize> Deserialize for Box<[T]> {
fn deserialize<D>(deserializer: &mut D) -> Result<Box<[T]>, D::Error>
where D: Deserializer,
{
let v: Vec<T> = try!(Deserialize::deserialize(deserializer));
Ok(v.into_boxed_slice())
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Deserialize> Deserialize for Arc<T> {
fn deserialize<D>(deserializer: &mut D) -> Result<Arc<T>, D::Error>
where D: Deserializer,
@@ -777,6 +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: &mut D) -> Result<Rc<T>, D::Error>
where D: Deserializer,
@@ -786,6 +959,7 @@ 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, {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<Cow<'a, T>, D::Error>
@@ -803,7 +977,7 @@ impl<T> Deserialize for NonZero<T> where T: Deserialize + PartialEq + Zeroable +
fn deserialize<D>(deserializer: &mut D) -> Result<NonZero<T>, D::Error> where D: Deserializer {
let value = try!(Deserialize::deserialize(deserializer));
if value == Zero::zero() {
return Err(Error::syntax("expected a non-zero value"))
return Err(Error::invalid_value("expected a non-zero value"))
}
unsafe {
Ok(NonZero::new(value))
@@ -832,7 +1006,10 @@ impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
impl ::de::Visitor for FieldVisitor {
type Value = Field;
#[cfg(any(feature = "std", feature = "collections"))]
fn visit_usize<E>(&mut self, value: usize) -> Result<Field, E> where E: Error {
#[cfg(feature = "collections")]
use collections::string::ToString;
match value {
0 => Ok(Field::Ok),
1 => Ok(Field::Err),
@@ -840,6 +1017,15 @@ impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
}
}
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
fn visit_usize<E>(&mut self, value: usize) -> Result<Field, E> where E: Error {
match value {
0 => Ok(Field::Ok),
1 => Ok(Field::Err),
_ => Err(Error::unknown_field("some number")),
}
}
fn visit_str<E>(&mut self, value: &str) -> Result<Field, E> where E: Error {
match value {
"Ok" => Ok(Field::Ok),
@@ -855,14 +1041,14 @@ impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
_ => {
match str::from_utf8(value) {
Ok(value) => Err(Error::unknown_field(value)),
Err(_) => Err(Error::type_mismatch(Type::String)),
Err(_) => Err(Error::invalid_type(Type::String)),
}
}
}
}
}
deserializer.visit(FieldVisitor)
deserializer.deserialize(FieldVisitor)
}
}
@@ -892,6 +1078,110 @@ impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
const VARIANTS: &'static [&'static str] = &["Ok", "Err"];
deserializer.visit_enum("Result", VARIANTS, Visitor(PhantomData))
deserializer.deserialize_enum("Result", VARIANTS, Visitor(PhantomData))
}
}
///////////////////////////////////////////////////////////////////////////////
/// A target for deserializers that want to ignore data. Implements
/// Deserialize and silently eats data given to it.
pub struct IgnoredAny;
impl Deserialize for IgnoredAny {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<IgnoredAny, D::Error>
where D: Deserializer,
{
struct IgnoredAnyVisitor;
impl Visitor for IgnoredAnyVisitor {
type Value = IgnoredAny;
#[inline]
fn visit_bool<E>(&mut self, _: bool) -> Result<IgnoredAny, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_i64<E>(&mut self, _: i64) -> Result<IgnoredAny, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_u64<E>(&mut self, _: u64) -> Result<IgnoredAny, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_f64<E>(&mut self, _: f64) -> Result<IgnoredAny, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_str<E>(&mut self, _: &str) -> Result<IgnoredAny, E>
where E: Error,
{
Ok(IgnoredAny)
}
#[inline]
fn visit_none<E>(&mut self) -> Result<IgnoredAny, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_some<D>(&mut self, _: &mut D) -> Result<IgnoredAny, D::Error>
where D: Deserializer,
{
Ok(IgnoredAny)
}
#[inline]
fn visit_newtype_struct<D>(&mut self, _: &mut D) -> Result<IgnoredAny, D::Error>
where D: Deserializer,
{
Ok(IgnoredAny)
}
#[inline]
fn visit_unit<E>(&mut self) -> Result<IgnoredAny, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<IgnoredAny, V::Error>
where V: SeqVisitor,
{
while let Some(_) = try!(visitor.visit::<IgnoredAny>()) {
// Gobble
}
try!(visitor.end());
Ok(IgnoredAny)
}
#[inline]
fn visit_map<V>(&mut self, mut visitor: V) -> Result<IgnoredAny, V::Error>
where V: MapVisitor,
{
while let Some((_, _)) = try!(visitor.visit::<IgnoredAny, IgnoredAny>()) {
// Gobble
}
try!(visitor.end());
Ok(IgnoredAny)
}
#[inline]
fn visit_bytes<E>(&mut self, _: &[u8]) -> Result<IgnoredAny, E>
where E: Error,
{
Ok(IgnoredAny)
}
}
// TODO maybe not necessary with impl specialization
deserializer.deserialize_ignored_any(IgnoredAnyVisitor)
}
}
+276 -165
View File
@@ -1,38 +1,78 @@
//! Generic deserialization framework.
#[cfg(feature = "std")]
use std::error;
#[cfg(not(feature = "std"))]
use error;
#[cfg(all(not(feature = "std"), feature = "collections"))]
use collections::{String, Vec};
use core::fmt;
pub mod impls;
pub mod value;
mod from_primitive;
///////////////////////////////////////////////////////////////////////////////
/// `Error` is a trait that allows a `Deserialize` to generically create a
/// `Deserializer` error.
pub trait Error: Sized {
pub trait Error: Sized + error::Error {
/// Raised when there is general error when deserializing a type.
fn syntax(msg: &str) -> Self;
#[cfg(any(feature = "std", feature = "collections"))]
fn custom<T: Into<String>>(msg: T) -> Self;
/// Raised when a fixed sized sequence or map was passed in the wrong amount of arguments.
fn length_mismatch(_len: usize) -> Self {
Error::syntax("incorrect length")
}
/// Raised when a `Deserialize` was passed an incorrect type.
fn type_mismatch(_type: Type) -> Self {
Error::syntax("incorrect type")
}
/// Raised when there is general error when deserializing a type.
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
fn custom<T: Into<&'static str>>(msg: T) -> Self;
/// Raised when a `Deserialize` type unexpectedly hit the end of the stream.
fn end_of_stream() -> Self;
/// Raised when a `Deserialize` struct type received an unexpected struct field.
fn unknown_field(field: &str) -> Self;
/// Raised when a `Deserialize` was passed an incorrect type.
fn invalid_type(ty: Type) -> Self {
Error::custom(format!("Invalid type. Expected `{:?}`", ty))
}
/// Raised when a `Deserialize` struct type did not receive a field.
fn missing_field(field: &'static str) -> Self;
/// Raised when a `Deserialize` was passed an incorrect value.
fn invalid_value(msg: &str) -> Self {
Error::custom(format!("Invalid value: {}", msg))
}
/// Raised when a fixed sized sequence or map was passed in the wrong amount of arguments.
///
/// The parameter `len` is the number of arguments found in the serialization. The sequence
/// may either expect more arguments or less arguments.
fn invalid_length(len: usize) -> Self {
Error::custom(format!("Invalid length: {}", len))
}
/// Raised when a `Deserialize` enum type received an unexpected variant.
fn unknown_variant(field: &str) -> Self {
Error::custom(format!("Unknown variant `{}`", field))
}
/// Raised when a `Deserialize` struct type received an unexpected struct field.
fn unknown_field(field: &str) -> Self {
Error::custom(format!("Unknown field `{}`", field))
}
/// raised when a `deserialize` struct type did not receive a field.
fn missing_field(field: &'static str) -> Self {
Error::custom(format!("Missing field `{}`", field))
}
/// Raised when a `Deserialize` struct type received more than one of the
/// same struct field.
fn duplicate_field(field: &'static str) -> Self {
Error::custom(format!("Duplicate field `{}`", field))
}
}
/// `Type` represents all the primitive types that can be deserialized. This is used by
/// `Error::kind_mismatch`.
/// `Error::invalid_type`.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Type {
/// Represents a `bool` type.
Bool,
@@ -106,12 +146,18 @@ pub enum Type {
/// Represents a struct type.
Struct,
/// Represents a struct field name.
FieldName,
/// Represents a tuple type.
Tuple,
/// Represents an `enum` type.
Enum,
/// Represents an enum variant name.
VariantName,
/// Represents a struct variant.
StructVariant,
@@ -125,6 +171,46 @@ pub enum Type {
Bytes,
}
impl fmt::Display for Type {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let display = match *self {
Type::Bool => "bool",
Type::Usize => "usize",
Type::U8 => "u8",
Type::U16 => "u16",
Type::U32 => "u32",
Type::U64 => "u64",
Type::Isize => "isize",
Type::I8 => "i8",
Type::I16 => "i16",
Type::I32 => "i32",
Type::I64 => "i64",
Type::F32 => "f32",
Type::F64 => "f64",
Type::Char => "char",
Type::Str => "str",
Type::String => "string",
Type::Unit => "unit",
Type::Option => "option",
Type::Seq => "seq",
Type::Map => "map",
Type::UnitStruct => "unit struct",
Type::NewtypeStruct => "newtype struct",
Type::TupleStruct => "tuple struct",
Type::Struct => "struct",
Type::FieldName => "field name",
Type::Tuple => "tuple",
Type::Enum => "enum",
Type::VariantName => "variant name",
Type::StructVariant => "struct variant",
Type::TupleVariant => "tuple variant",
Type::UnitVariant => "unit variant",
Type::Bytes => "bytes",
};
display.fmt(formatter)
}
}
///////////////////////////////////////////////////////////////////////////////
/// `Deserialize` represents a type that can be deserialized.
@@ -139,272 +225,295 @@ pub trait Deserialize: Sized {
/// `Deserializer` is a trait that can deserialize values by threading a `Visitor` trait through a
/// value. It supports two entry point styles which enables different kinds of deserialization.
///
/// 1) The `visit` method. File formats like JSON embed the type of it's construct in it's file
/// 1) The `deserialize` method. File formats like JSON embed the type of its construct in its file
/// format. This allows the `Deserializer` to deserialize into a generic type like
/// `json::Value`, which can represent all JSON types.
///
/// 2) The `visit_*` methods. File formats like bincode do not embed in it's format how to decode
/// it's values. It relies instead on the `Deserialize` type to hint to the `Deserializer` with
/// the `visit_*` methods how it should parse the next value. One downside though to only
/// supporting the `visit_*` types is that it does not allow for deserializing into a generic
/// `json::Value`-esque type.
/// 2) The `deserialize_*` methods. File formats like bincode do not embed in its format how to
/// decode its values. It relies instead on the `Deserialize` type to hint to the `Deserializer`
/// with the `deserialize_*` methods how it should parse the next value. One downside though to
/// only supporting the `deserialize_*` types is that it does not allow for deserializing into a
/// generic `json::Value`-esque type.
pub trait Deserializer {
/// The error type that can be returned if some error occurs during deserialization.
type Error: Error;
/// This method walks a visitor through a value as it is being deserialized.
fn visit<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a `bool` value.
#[inline]
fn visit_bool<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_bool<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `usize` value.
#[inline]
fn visit_usize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_usize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_u64(visitor)
self.deserialize_u64(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `u8` value.
#[inline]
fn visit_u8<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_u8<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_u64(visitor)
self.deserialize_u64(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `u16` value.
#[inline]
fn visit_u16<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_u16<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_u64(visitor)
self.deserialize_u64(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `u32` value.
#[inline]
fn visit_u32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_u32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_u64(visitor)
self.deserialize_u64(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `u64` value.
#[inline]
fn visit_u64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_u64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `isize` value.
#[inline]
fn visit_isize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_isize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_i64(visitor)
self.deserialize_i64(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `i8` value.
#[inline]
fn visit_i8<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_i8<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_i64(visitor)
self.deserialize_i64(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `i16` value.
#[inline]
fn visit_i16<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_i16<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_i64(visitor)
self.deserialize_i64(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `i32` value.
#[inline]
fn visit_i32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_i32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_i64(visitor)
self.deserialize_i64(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `i64` value.
#[inline]
fn visit_i64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_i64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a `f32` value.
#[inline]
fn visit_f32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_f32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_f64(visitor)
self.deserialize_f64(visitor)
}
/// This method hints that the `Deserialize` type is expecting a `f64` value.
#[inline]
fn visit_f64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_f64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a `char` value.
#[inline]
fn visit_char<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_char<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a `&str` value.
#[inline]
fn visit_str<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_str<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a `String` value.
#[inline]
fn visit_string<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_string<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_str(visitor)
self.deserialize_str(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `unit` value.
#[inline]
fn visit_unit<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_unit<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `Option` value. This allows
/// deserializers that encode an optional value as a nullable value to convert the null value
/// into a `None`, and a regular value as `Some(value)`.
#[inline]
fn visit_option<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_option<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a sequence value. This allows
/// deserializers to parse sequences that aren't tagged as sequences.
#[inline]
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_seq<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a map of values. This allows
/// deserializers to parse sequences that aren't tagged as maps.
/// This method hints that the `Deserialize` type is expecting a fixed size array. This allows
/// deserializers to parse arrays that aren't tagged as arrays.
///
/// By default, this deserializes arrays from a sequence.
#[inline]
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_fixed_size_array<V>(&mut self,
_len: usize,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting a unit struct. This allows
/// deserializers to a unit struct that aren't tagged as a unit struct.
#[inline]
fn visit_unit_struct<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_unit(visitor)
}
/// This method hints that the `Deserialize` type is expecting a newtype struct. This allows
/// deserializers to a newtype struct that aren't tagged as a newtype struct.
#[inline]
fn visit_newtype_struct<V>(&mut self,
name: &'static str,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_tuple_struct(name, 1, visitor)
}
/// This method hints that the `Deserialize` type is expecting a tuple struct. This allows
/// deserializers to parse sequences that aren't tagged as sequences.
#[inline]
fn visit_tuple_struct<V>(&mut self,
_name: &'static str,
len: usize,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_tuple(len, visitor)
}
/// This method hints that the `Deserialize` type is expecting a struct. This allows
/// deserializers to parse sequences that aren't tagged as maps.
#[inline]
fn visit_struct<V>(&mut self,
_name: &'static str,
_fields: &'static [&'static str],
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_map(visitor)
}
/// This method hints that the `Deserialize` type is expecting a tuple value. This allows
/// deserializers that provide a custom tuple serialization to properly deserialize the type.
#[inline]
fn visit_tuple<V>(&mut self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_seq(visitor)
}
/// This method hints that the `Deserialize` type is expecting an enum value. This allows
/// deserializers that provide a custom enumeration serialization to properly deserialize the
/// type.
#[inline]
fn visit_enum<V>(&mut self,
_enum: &'static str,
_variants: &'static [&'static str],
_visitor: V) -> Result<V::Value, Self::Error>
where V: EnumVisitor,
{
Err(Error::syntax("expected an enum"))
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a `Vec<u8>`. This allows
/// deserializers that provide a custom byte vector serialization to properly deserialize the
/// type.
#[inline]
fn visit_bytes<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_bytes<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_seq(visitor)
self.deserialize_seq(visitor)
}
/// Specify a format string for the deserializer.
///
/// The deserializer format is used to determine which format
/// specific field attributes should be used with the
/// deserializer.
fn format() -> &'static str {
""
/// This method hints that the `Deserialize` type is expecting a map of values. This allows
/// deserializers to parse sequences that aren't tagged as maps.
#[inline]
fn deserialize_map<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a unit struct. This allows
/// deserializers to a unit struct that aren't tagged as a unit struct.
#[inline]
fn deserialize_unit_struct<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_unit(visitor)
}
/// This method hints that the `Deserialize` type is expecting a newtype struct. This allows
/// deserializers to a newtype struct that aren't tagged as a newtype struct.
#[inline]
fn deserialize_newtype_struct<V>(&mut self,
name: &'static str,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_tuple_struct(name, 1, visitor)
}
/// This method hints that the `Deserialize` type is expecting a tuple struct. This allows
/// deserializers to parse sequences that aren't tagged as sequences.
#[inline]
fn deserialize_tuple_struct<V>(&mut self,
_name: &'static str,
len: usize,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_tuple(len, visitor)
}
/// This method hints that the `Deserialize` type is expecting a struct. This allows
/// deserializers to parse sequences that aren't tagged as maps.
#[inline]
fn deserialize_struct<V>(&mut self,
_name: &'static str,
_fields: &'static [&'static str],
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_map(visitor)
}
/// This method hints that the `Deserialize` type is expecting some sort of struct field
/// name. This allows deserializers to choose between &str, usize, or &[u8] to properly
/// deserialize a struct field.
#[inline]
fn deserialize_struct_field<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a tuple value. This allows
/// deserializers that provide a custom tuple serialization to properly deserialize the type.
#[inline]
fn deserialize_tuple<V>(&mut self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_seq(visitor)
}
/// This method hints that the `Deserialize` type is expecting an enum value. This allows
/// deserializers that provide a custom enumeration serialization to properly deserialize the
/// type.
#[inline]
fn deserialize_enum<V>(&mut self,
_enum: &'static str,
_variants: &'static [&'static str],
_visitor: V) -> Result<V::Value, Self::Error>
where V: EnumVisitor,
{
Err(Error::invalid_type(Type::Enum))
}
/// This method hints that the `Deserialize` type needs to deserialize a value whose type
/// doesn't matter because it is ignored.
#[inline]
fn deserialize_ignored_any<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
self.deserialize(visitor)
}
}
@@ -419,7 +528,7 @@ pub trait Visitor {
fn visit_bool<E>(&mut self, _v: bool) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::type_mismatch(Type::Bool))
Err(Error::invalid_type(Type::Bool))
}
/// `visit_isize` deserializes a `isize` into a `Value`.
@@ -454,7 +563,7 @@ pub trait Visitor {
fn visit_i64<E>(&mut self, _v: i64) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::type_mismatch(Type::I64))
Err(Error::invalid_type(Type::I64))
}
/// `visit_usize` deserializes a `usize` into a `Value`.
@@ -489,7 +598,7 @@ pub trait Visitor {
fn visit_u64<E>(&mut self, _v: u64) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::type_mismatch(Type::U64))
Err(Error::invalid_type(Type::U64))
}
/// `visit_f32` deserializes a `f32` into a `Value`.
@@ -503,7 +612,7 @@ pub trait Visitor {
fn visit_f64<E>(&mut self, _v: f64) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::type_mismatch(Type::F64))
Err(Error::invalid_type(Type::F64))
}
/// `visit_char` deserializes a `char` into a `Value`.
@@ -511,20 +620,21 @@ pub trait Visitor {
fn visit_char<E>(&mut self, v: char) -> Result<Self::Value, E>
where E: Error,
{
// FIXME: this allocation is required in order to be compatible with stable rust, which
// doesn't support encoding a `char` into a stack buffer.
self.visit_string(v.to_string())
self.visit_str(::utils::encode_utf8(v).as_str())
}
/// `visit_str` deserializes a `&str` into a `Value`.
fn visit_str<E>(&mut self, _v: &str) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::type_mismatch(Type::Str))
Err(Error::invalid_type(Type::Str))
}
/// `visit_string` deserializes a `String` into a `Value`.
/// `visit_string` deserializes a `String` into a `Value`. This allows a deserializer to avoid
/// a copy if it is deserializing a string from a `String` type. By default it passes a `&str`
/// to the `visit_str` method.
#[inline]
#[cfg(any(feature = "std", feature = "collections"))]
fn visit_string<E>(&mut self, v: String) -> Result<Self::Value, E>
where E: Error,
{
@@ -535,7 +645,7 @@ pub trait Visitor {
fn visit_unit<E>(&mut self) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::type_mismatch(Type::Unit))
Err(Error::invalid_type(Type::Unit))
}
/// `visit_unit_struct` deserializes a unit struct into a `Value`.
@@ -550,45 +660,46 @@ pub trait Visitor {
fn visit_none<E>(&mut self) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::type_mismatch(Type::Option))
Err(Error::invalid_type(Type::Option))
}
/// `visit_some` deserializes a value into a `Value`.
fn visit_some<D>(&mut self, _deserializer: &mut D) -> Result<Self::Value, D::Error>
where D: Deserializer,
{
Err(Error::type_mismatch(Type::Option))
Err(Error::invalid_type(Type::Option))
}
/// `visit_newtype_struct` deserializes a value into a `Value`.
fn visit_newtype_struct<D>(&mut self, _deserializer: &mut D) -> Result<Self::Value, D::Error>
where D: Deserializer,
{
Err(Error::type_mismatch(Type::NewtypeStruct))
Err(Error::invalid_type(Type::NewtypeStruct))
}
/// `visit_bool` deserializes a `SeqVisitor` into a `Value`.
/// `visit_seq` deserializes a `SeqVisitor` into a `Value`.
fn visit_seq<V>(&mut self, _visitor: V) -> Result<Self::Value, V::Error>
where V: SeqVisitor,
{
Err(Error::type_mismatch(Type::Seq))
Err(Error::invalid_type(Type::Seq))
}
/// `visit_map` deserializes a `MapVisitor` into a `Value`.
fn visit_map<V>(&mut self, _visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor,
{
Err(Error::type_mismatch(Type::Map))
Err(Error::invalid_type(Type::Map))
}
/// `visit_bytes` deserializes a `&[u8]` into a `Value`.
fn visit_bytes<E>(&mut self, _v: &[u8]) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::type_mismatch(Type::Bytes))
Err(Error::invalid_type(Type::Bytes))
}
/// `visit_byte_buf` deserializes a `Vec<u8>` into a `Value`.
#[cfg(any(feature = "std", feature = "collections"))]
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<Self::Value, E>
where E: Error,
{
@@ -685,7 +796,7 @@ pub trait MapVisitor {
(0, None)
}
/// Report that there
/// Report that the struct has a field that wasn't deserialized
fn missing_field<V>(&mut self, field: &'static str) -> Result<V, Self::Error>
where V: Deserialize,
{
@@ -756,7 +867,7 @@ pub trait VariantVisitor {
/// `visit_unit` is called when deserializing a variant with no values.
fn visit_unit(&mut self) -> Result<(), Self::Error> {
Err(Error::type_mismatch(Type::UnitVariant))
Err(Error::invalid_type(Type::UnitVariant))
}
/// `visit_newtype` is called when deserializing a variant with a single value. By default this
@@ -775,7 +886,7 @@ pub trait VariantVisitor {
_visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
Err(Error::type_mismatch(Type::TupleVariant))
Err(Error::invalid_type(Type::TupleVariant))
}
/// `visit_struct` is called when deserializing a struct-like variant.
@@ -784,7 +895,7 @@ pub trait VariantVisitor {
_visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
Err(Error::type_mismatch(Type::StructVariant))
Err(Error::invalid_type(Type::StructVariant))
}
}
@@ -816,8 +927,8 @@ impl<'a, T> VariantVisitor for &'a mut T where T: VariantVisitor {
}
fn visit_struct<V>(&mut self,
fields: &'static [&'static str],
visitor: V) -> Result<V::Value, T::Error>
fields: &'static [&'static str],
visitor: V) -> Result<V::Value, T::Error>
where V: Visitor,
{
(**self).visit_struct(fields, visitor)
+350 -127
View File
@@ -1,5 +1,6 @@
//! This module supports deserializing from primitives with the `ValueDeserializer` trait.
#[cfg(feature = "std")]
use std::collections::{
BTreeMap,
BTreeSet,
@@ -10,9 +11,32 @@ use std::collections::{
hash_map,
hash_set,
};
use std::hash::Hash;
#[cfg(feature = "std")]
use std::vec;
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::{
BTreeMap,
BTreeSet,
Vec,
String,
btree_map,
btree_set,
vec,
};
#[cfg(all(feature = "nightly", feature = "collections"))]
use collections::borrow::ToOwned;
use core::hash::Hash;
#[cfg(feature = "std")]
use std::error;
#[cfg(not(feature = "std"))]
use error;
use core::fmt;
use core::marker::PhantomData;
use de;
use bytes;
@@ -21,32 +45,110 @@ use bytes;
/// This represents all the possible errors that can occur using the `ValueDeserializer`.
#[derive(Clone, Debug, PartialEq)]
pub enum Error {
/// The value had some syntatic error.
SyntaxError,
/// The value had some custom error.
#[cfg(any(feature = "std", feature = "collections"))]
Custom(String),
/// The value had some custom error.
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
Custom(&'static str),
/// The value had an incorrect type.
InvalidType(de::Type),
/// The value had an invalid length.
InvalidLength(usize),
/// The value is invalid and cannot be deserialized.
#[cfg(any(feature = "std", feature = "collections"))]
InvalidValue(String),
/// The value is invalid and cannot be deserialized.
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
InvalidValue(&'static str),
/// EOF while deserializing a value.
EndOfStreamError,
EndOfStream,
/// Unknown variant in enum.
#[cfg(any(feature = "std", feature = "collections"))]
UnknownVariant(String),
/// Unknown variant in enum.
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
UnknownVariant(&'static str),
/// Unknown field in struct.
UnknownFieldError(String),
#[cfg(any(feature = "std", feature = "collections"))]
UnknownField(String),
/// Unknown field in struct.
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
UnknownField(&'static str),
/// Struct is missing a field.
MissingFieldError(&'static str),
MissingField(&'static str),
}
impl de::Error for Error {
fn syntax(_: &str) -> Self { Error::SyntaxError }
fn end_of_stream() -> Self { Error::EndOfStreamError }
fn unknown_field(field: &str) -> Self { Error::UnknownFieldError(String::from(field)) }
fn missing_field(field: &'static str) -> Self { Error::MissingFieldError(field) }
#[cfg(any(feature = "std", feature = "collections"))]
fn custom<T: Into<String>>(msg: T) -> Self { Error::Custom(msg.into()) }
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
fn custom<T: Into<&'static str>>(msg: T) -> Self { Error::Custom(msg.into()) }
fn end_of_stream() -> Self { Error::EndOfStream }
fn invalid_type(ty: de::Type) -> Self { Error::InvalidType(ty) }
#[cfg(any(feature = "std", feature = "collections"))]
fn invalid_value(msg: &str) -> Self { Error::InvalidValue(msg.to_owned()) }
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
fn invalid_value(msg: &str) -> Self { Error::InvalidValue("invalid value") }
fn invalid_length(len: usize) -> Self { Error::InvalidLength(len) }
#[cfg(any(feature = "std", feature = "collections"))]
fn unknown_variant(variant: &str) -> Self { Error::UnknownVariant(String::from(variant)) }
#[cfg(any(feature = "std", feature = "collections"))]
fn unknown_field(field: &str) -> Self { Error::UnknownField(String::from(field)) }
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
fn unknown_variant(variant: &str) -> Self { Error::UnknownVariant("unknown variant") }
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
fn unknown_field(field: &str) -> Self { Error::UnknownField("unknown field") }
fn missing_field(field: &'static str) -> Self { Error::MissingField(field) }
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
Error::Custom(ref s) => write!(formatter, "{}", s),
Error::EndOfStream => formatter.write_str("End of stream"),
Error::InvalidType(ty) => write!(formatter, "Invalid type, expected `{:?}`", ty),
Error::InvalidValue(ref value) => write!(formatter, "Invalid value: {}", value),
Error::InvalidLength(len) => write!(formatter, "Invalid length: {}", len),
Error::UnknownVariant(ref variant) => {
write!(formatter, "Unknown variant: {}", variant)
}
Error::UnknownField(ref field) => write!(formatter, "Unknown field: {}", field),
Error::MissingField(ref field) => write!(formatter, "Missing field: {}", field),
}
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Deserialization Error"
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
///////////////////////////////////////////////////////////////////////////////
/// This trait converts primitive types into a deserializer.
pub trait ValueDeserializer {
pub trait ValueDeserializer<E: de::Error = Error> {
/// The actual deserializer type.
type Deserializer: de::Deserializer<Error=Error>;
type Deserializer: de::Deserializer<Error=E>;
/// Convert this value into a deserializer.
fn into_deserializer(self) -> Self::Deserializer;
@@ -54,27 +156,31 @@ pub trait ValueDeserializer {
///////////////////////////////////////////////////////////////////////////////
impl ValueDeserializer for () {
type Deserializer = UnitDeserializer;
impl<E> ValueDeserializer<E> for ()
where E: de::Error,
{
type Deserializer = UnitDeserializer<E>;
fn into_deserializer(self) -> UnitDeserializer {
UnitDeserializer
fn into_deserializer(self) -> UnitDeserializer<E> {
UnitDeserializer(PhantomData)
}
}
/// A helper deserializer that deserializes a `()`.
pub struct UnitDeserializer;
pub struct UnitDeserializer<E>(PhantomData<E>);
impl de::Deserializer for UnitDeserializer {
type Error = Error;
impl<E> de::Deserializer for UnitDeserializer<E>
where E: de::Error
{
type Error = E;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
visitor.visit_unit()
}
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
visitor.visit_none()
@@ -86,20 +192,24 @@ impl de::Deserializer for UnitDeserializer {
macro_rules! primitive_deserializer {
($ty:ty, $name:ident, $method:ident) => {
/// A helper deserializer that deserializes a number.
pub struct $name(Option<$ty>);
pub struct $name<E>(Option<$ty>, PhantomData<E>);
impl ValueDeserializer for $ty {
type Deserializer = $name;
impl<E> ValueDeserializer<E> for $ty
where E: de::Error,
{
type Deserializer = $name<E>;
fn into_deserializer(self) -> $name {
$name(Some(self))
fn into_deserializer(self) -> $name<E> {
$name(Some(self), PhantomData)
}
}
impl de::Deserializer for $name {
type Error = Error;
impl<E> de::Deserializer for $name<E>
where E: de::Error,
{
type Error = E;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
match self.0.take() {
@@ -129,20 +239,24 @@ primitive_deserializer!(char, CharDeserializer, visit_char);
///////////////////////////////////////////////////////////////////////////////
/// A helper deserializer that deserializes a `&str`.
pub struct StrDeserializer<'a>(Option<&'a str>);
pub struct StrDeserializer<'a, E>(Option<&'a str>, PhantomData<E>);
impl<'a> ValueDeserializer for &'a str {
type Deserializer = StrDeserializer<'a>;
impl<'a, E> ValueDeserializer<E> for &'a str
where E: de::Error,
{
type Deserializer = StrDeserializer<'a, E>;
fn into_deserializer(self) -> StrDeserializer<'a> {
StrDeserializer(Some(self))
fn into_deserializer(self) -> StrDeserializer<'a, E> {
StrDeserializer(Some(self), PhantomData)
}
}
impl<'a> de::Deserializer for StrDeserializer<'a> {
type Error = Error;
impl<'a, E> de::Deserializer for StrDeserializer<'a, E>
where E: de::Error,
{
type Error = E;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
match self.0.take() {
@@ -151,26 +265,28 @@ impl<'a> de::Deserializer for StrDeserializer<'a> {
}
}
fn visit_enum<V>(&mut self,
fn deserialize_enum<V>(&mut self,
_name: &str,
_variants: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Error>
mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::EnumVisitor,
{
visitor.visit(self)
}
}
impl<'a> de::VariantVisitor for StrDeserializer<'a> {
type Error = Error;
impl<'a, E> de::VariantVisitor for StrDeserializer<'a, E>
where E: de::Error,
{
type Error = E;
fn visit_variant<T>(&mut self) -> Result<T, Error>
fn visit_variant<T>(&mut self) -> Result<T, Self::Error>
where T: de::Deserialize,
{
de::Deserialize::deserialize(self)
}
fn visit_unit(&mut self) -> Result<(), Error> {
fn visit_unit(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
@@ -178,20 +294,27 @@ impl<'a> de::VariantVisitor for StrDeserializer<'a> {
///////////////////////////////////////////////////////////////////////////////
/// A helper deserializer that deserializes a `String`.
pub struct StringDeserializer(Option<String>);
#[cfg(any(feature = "std", feature = "collections"))]
pub struct StringDeserializer<E>(Option<String>, PhantomData<E>);
impl ValueDeserializer for String {
type Deserializer = StringDeserializer;
#[cfg(any(feature = "std", feature = "collections"))]
impl<E> ValueDeserializer<E> for String
where E: de::Error,
{
type Deserializer = StringDeserializer<E>;
fn into_deserializer(self) -> StringDeserializer {
StringDeserializer(Some(self))
fn into_deserializer(self) -> StringDeserializer<E> {
StringDeserializer(Some(self), PhantomData)
}
}
impl de::Deserializer for StringDeserializer {
type Error = Error;
#[cfg(any(feature = "std", feature = "collections"))]
impl<E> de::Deserializer for StringDeserializer<E>
where E: de::Error,
{
type Error = E;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
match self.0.take() {
@@ -200,26 +323,29 @@ impl de::Deserializer for StringDeserializer {
}
}
fn visit_enum<V>(&mut self,
fn deserialize_enum<V>(&mut self,
_name: &str,
_variants: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Error>
mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::EnumVisitor,
{
visitor.visit(self)
}
}
impl<'a> de::VariantVisitor for StringDeserializer {
type Error = Error;
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a, E> de::VariantVisitor for StringDeserializer<E>
where E: de::Error,
{
type Error = E;
fn visit_variant<T>(&mut self) -> Result<T, Error>
fn visit_variant<T>(&mut self) -> Result<T, Self::Error>
where T: de::Deserialize,
{
de::Deserialize::deserialize(self)
}
fn visit_unit(&mut self) -> Result<(), Error> {
fn visit_unit(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
@@ -227,41 +353,47 @@ impl<'a> de::VariantVisitor for StringDeserializer {
///////////////////////////////////////////////////////////////////////////////
/// A helper deserializer that deserializes a sequence.
pub struct SeqDeserializer<I> {
pub struct SeqDeserializer<I, E> {
iter: I,
len: usize,
marker: PhantomData<E>,
}
impl<I> SeqDeserializer<I> {
impl<I, E> SeqDeserializer<I, E>
where E: de::Error,
{
/// Construct a new `SeqDeserializer<I>`.
pub fn new(iter: I, len: usize) -> Self {
SeqDeserializer {
iter: iter,
len: len,
marker: PhantomData,
}
}
}
impl<I, T> de::Deserializer for SeqDeserializer<I>
impl<I, T, E> de::Deserializer for SeqDeserializer<I, E>
where I: Iterator<Item=T>,
T: ValueDeserializer,
T: ValueDeserializer<E>,
E: de::Error,
{
type Error = Error;
type Error = E;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
visitor.visit_seq(self)
}
}
impl<I, T> de::SeqVisitor for SeqDeserializer<I>
impl<I, T, E> de::SeqVisitor for SeqDeserializer<I, E>
where I: Iterator<Item=T>,
T: ValueDeserializer,
T: ValueDeserializer<E>,
E: de::Error,
{
type Error = Error;
type Error = E;
fn visit<V>(&mut self) -> Result<Option<V>, Error>
fn visit<V>(&mut self) -> Result<Option<V>, Self::Error>
where V: de::Deserialize
{
match self.iter.next() {
@@ -274,11 +406,11 @@ impl<I, T> de::SeqVisitor for SeqDeserializer<I>
}
}
fn end(&mut self) -> Result<(), Error> {
fn end(&mut self) -> Result<(), Self::Error> {
if self.len == 0 {
Ok(())
} else {
Err(de::Error::length_mismatch(self.len))
Err(de::Error::invalid_length(self.len))
}
}
@@ -289,34 +421,40 @@ impl<I, T> de::SeqVisitor for SeqDeserializer<I>
///////////////////////////////////////////////////////////////////////////////
impl<T> ValueDeserializer for Vec<T>
where T: ValueDeserializer,
#[cfg(any(feature = "std", feature = "collections"))]
impl<T, E> ValueDeserializer<E> for Vec<T>
where T: ValueDeserializer<E>,
E: de::Error,
{
type Deserializer = SeqDeserializer<vec::IntoIter<T>>;
type Deserializer = SeqDeserializer<vec::IntoIter<T>, E>;
fn into_deserializer(self) -> SeqDeserializer<vec::IntoIter<T>> {
fn into_deserializer(self) -> Self::Deserializer {
let len = self.len();
SeqDeserializer::new(self.into_iter(), len)
}
}
impl<T> ValueDeserializer for BTreeSet<T>
where T: ValueDeserializer + Eq + Ord,
#[cfg(any(feature = "std", feature = "collections"))]
impl<T, E> ValueDeserializer<E> for BTreeSet<T>
where T: ValueDeserializer<E> + Eq + Ord,
E: de::Error,
{
type Deserializer = SeqDeserializer<btree_set::IntoIter<T>>;
type Deserializer = SeqDeserializer<btree_set::IntoIter<T>, E>;
fn into_deserializer(self) -> SeqDeserializer<btree_set::IntoIter<T>> {
fn into_deserializer(self) -> Self::Deserializer {
let len = self.len();
SeqDeserializer::new(self.into_iter(), len)
}
}
impl<T> ValueDeserializer for HashSet<T>
where T: ValueDeserializer + Eq + Hash,
#[cfg(feature = "std")]
impl<T, E> ValueDeserializer<E> for HashSet<T>
where T: ValueDeserializer<E> + Eq + Hash,
E: de::Error,
{
type Deserializer = SeqDeserializer<hash_set::IntoIter<T>>;
type Deserializer = SeqDeserializer<hash_set::IntoIter<T>, E>;
fn into_deserializer(self) -> SeqDeserializer<hash_set::IntoIter<T>> {
fn into_deserializer(self) -> Self::Deserializer {
let len = self.len();
SeqDeserializer::new(self.into_iter(), len)
}
@@ -324,21 +462,56 @@ impl<T> ValueDeserializer for HashSet<T>
///////////////////////////////////////////////////////////////////////////////
/// A helper deserializer that deserializes a sequence using a `SeqVisitor`.
pub struct SeqVisitorDeserializer<V_, E> {
visitor: V_,
marker: PhantomData<E>,
}
impl<V_, E> SeqVisitorDeserializer<V_, E>
where V_: de::SeqVisitor<Error = E>,
E: de::Error,
{
/// Construct a new `SeqVisitorDeserializer<V_, E>`.
pub fn new(visitor: V_) -> Self {
SeqVisitorDeserializer{
visitor: visitor,
marker: PhantomData
}
}
}
impl<V_, E> de::Deserializer for SeqVisitorDeserializer<V_, E>
where V_: de::SeqVisitor<Error = E>,
E: de::Error,
{
type Error = E;
fn deserialize<V: de::Visitor>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_seq(&mut self.visitor)
}
}
///////////////////////////////////////////////////////////////////////////////
/// A helper deserializer that deserializes a map.
pub struct MapDeserializer<I, K, V>
pub struct MapDeserializer<I, K, V, E>
where I: Iterator<Item=(K, V)>,
K: ValueDeserializer,
V: ValueDeserializer,
K: ValueDeserializer<E>,
V: ValueDeserializer<E>,
E: de::Error,
{
iter: I,
value: Option<V>,
len: usize,
marker: PhantomData<E>,
}
impl<I, K, V> MapDeserializer<I, K, V>
impl<I, K, V, E> MapDeserializer<I, K, V, E>
where I: Iterator<Item=(K, V)>,
K: ValueDeserializer,
V: ValueDeserializer,
K: ValueDeserializer<E>,
V: ValueDeserializer<E>,
E: de::Error,
{
/// Construct a new `MapDeserializer<I, K, V>`.
pub fn new(iter: I, len: usize) -> Self {
@@ -346,32 +519,35 @@ impl<I, K, V> MapDeserializer<I, K, V>
iter: iter,
value: None,
len: len,
marker: PhantomData,
}
}
}
impl<I, K, V> de::Deserializer for MapDeserializer<I, K, V>
impl<I, K, V, E> de::Deserializer for MapDeserializer<I, K, V, E>
where I: Iterator<Item=(K, V)>,
K: ValueDeserializer,
V: ValueDeserializer,
K: ValueDeserializer<E>,
V: ValueDeserializer<E>,
E: de::Error,
{
type Error = Error;
type Error = E;
fn visit<V_>(&mut self, mut visitor: V_) -> Result<V_::Value, Error>
fn deserialize<V_>(&mut self, mut visitor: V_) -> Result<V_::Value, Self::Error>
where V_: de::Visitor,
{
visitor.visit_map(self)
}
}
impl<I, K, V> de::MapVisitor for MapDeserializer<I, K, V>
impl<I, K, V, E> de::MapVisitor for MapDeserializer<I, K, V, E>
where I: Iterator<Item=(K, V)>,
K: ValueDeserializer,
V: ValueDeserializer,
K: ValueDeserializer<E>,
V: ValueDeserializer<E>,
E: de::Error,
{
type Error = Error;
type Error = E;
fn visit_key<T>(&mut self) -> Result<Option<T>, Error>
fn visit_key<T>(&mut self) -> Result<Option<T>, Self::Error>
where T: de::Deserialize,
{
match self.iter.next() {
@@ -385,7 +561,7 @@ impl<I, K, V> de::MapVisitor for MapDeserializer<I, K, V>
}
}
fn visit_value<T>(&mut self) -> Result<T, Error>
fn visit_value<T>(&mut self) -> Result<T, Self::Error>
where T: de::Deserialize,
{
match self.value.take() {
@@ -393,15 +569,17 @@ impl<I, K, V> de::MapVisitor for MapDeserializer<I, K, V>
let mut de = value.into_deserializer();
de::Deserialize::deserialize(&mut de)
}
None => Err(de::Error::syntax("expected a map value"))
None => {
Err(de::Error::end_of_stream())
}
}
}
fn end(&mut self) -> Result<(), Error> {
fn end(&mut self) -> Result<(), Self::Error> {
if self.len == 0 {
Ok(())
} else {
Err(de::Error::length_mismatch(self.len))
Err(de::Error::invalid_length(self.len))
}
}
@@ -412,25 +590,29 @@ impl<I, K, V> de::MapVisitor for MapDeserializer<I, K, V>
///////////////////////////////////////////////////////////////////////////////
impl<K, V> ValueDeserializer for BTreeMap<K, V>
where K: ValueDeserializer + Eq + Ord,
V: ValueDeserializer,
#[cfg(any(feature = "std", feature = "collections"))]
impl<K, V, E> ValueDeserializer<E> for BTreeMap<K, V>
where K: ValueDeserializer<E> + Eq + Ord,
V: ValueDeserializer<E>,
E: de::Error,
{
type Deserializer = MapDeserializer<btree_map::IntoIter<K, V>, K, V>;
type Deserializer = MapDeserializer<btree_map::IntoIter<K, V>, K, V, E>;
fn into_deserializer(self) -> MapDeserializer<btree_map::IntoIter<K, V>, K, V> {
fn into_deserializer(self) -> Self::Deserializer {
let len = self.len();
MapDeserializer::new(self.into_iter(), len)
}
}
impl<K, V> ValueDeserializer for HashMap<K, V>
where K: ValueDeserializer + Eq + Hash,
V: ValueDeserializer,
#[cfg(feature = "std")]
impl<K, V, E> ValueDeserializer<E> for HashMap<K, V>
where K: ValueDeserializer<E> + Eq + Hash,
V: ValueDeserializer<E>,
E: de::Error,
{
type Deserializer = MapDeserializer<hash_map::IntoIter<K, V>, K, V>;
type Deserializer = MapDeserializer<hash_map::IntoIter<K, V>, K, V, E>;
fn into_deserializer(self) -> MapDeserializer<hash_map::IntoIter<K, V>, K, V> {
fn into_deserializer(self) -> Self::Deserializer {
let len = self.len();
MapDeserializer::new(self.into_iter(), len)
}
@@ -438,22 +620,57 @@ impl<K, V> ValueDeserializer for HashMap<K, V>
///////////////////////////////////////////////////////////////////////////////
impl<'a> ValueDeserializer for bytes::Bytes<'a>
{
type Deserializer = BytesDeserializer<'a>;
/// A helper deserializer that deserializes a map using a `MapVisitor`.
pub struct MapVisitorDeserializer<V_, E> {
visitor: V_,
marker: PhantomData<E>,
}
fn into_deserializer(self) -> BytesDeserializer<'a> {
BytesDeserializer(Some(self.into()))
impl<V_, E> MapVisitorDeserializer<V_, E>
where V_: de::MapVisitor<Error = E>,
E: de::Error,
{
/// Construct a new `MapVisitorDeserializer<V_, E>`.
pub fn new(visitor: V_) -> Self {
MapVisitorDeserializer{
visitor: visitor,
marker: PhantomData
}
}
}
impl<V_, E> de::Deserializer for MapVisitorDeserializer<V_, E>
where V_: de::MapVisitor<Error = E>,
E: de::Error,
{
type Error = E;
fn deserialize<V: de::Visitor>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_map(&mut self.visitor)
}
}
///////////////////////////////////////////////////////////////////////////////
impl<'a, E> ValueDeserializer<E> for bytes::Bytes<'a>
where E: de::Error,
{
type Deserializer = BytesDeserializer<'a, E>;
fn into_deserializer(self) -> BytesDeserializer<'a, E> {
BytesDeserializer(Some(self.into()), PhantomData)
}
}
/// A helper deserializer that deserializes a `&[u8]`.
pub struct BytesDeserializer<'a> (Option<&'a [u8]>);
pub struct BytesDeserializer<'a, E> (Option<&'a [u8]>, PhantomData<E>);
impl<'a> de::Deserializer for BytesDeserializer<'a> {
type Error = Error;
impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
where E: de::Error
{
type Error = E;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
match self.0.take() {
@@ -466,22 +683,28 @@ impl<'a> de::Deserializer for BytesDeserializer<'a> {
///////////////////////////////////////////////////////////////////////////////
impl ValueDeserializer for bytes::ByteBuf
#[cfg(any(feature = "std", feature = "collections"))]
impl<E> ValueDeserializer<E> for bytes::ByteBuf
where E: de::Error,
{
type Deserializer = ByteBufDeserializer;
type Deserializer = ByteBufDeserializer<E>;
fn into_deserializer(self) -> Self::Deserializer {
ByteBufDeserializer(Some(self.into()))
ByteBufDeserializer(Some(self.into()), PhantomData)
}
}
/// A helper deserializer that deserializes a `Vec<u8>`.
pub struct ByteBufDeserializer(Option<Vec<u8>>);
#[cfg(any(feature = "std", feature = "collections"))]
pub struct ByteBufDeserializer<E>(Option<Vec<u8>>, PhantomData<E>);
impl de::Deserializer for ByteBufDeserializer {
type Error = Error;
#[cfg(any(feature = "std", feature = "collections"))]
impl<E> de::Deserializer for ByteBufDeserializer<E>
where E: de::Error,
{
type Error = E;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
match self.0.take() {
+44
View File
@@ -0,0 +1,44 @@
//! A stand-in for `std::error`
use core::any::TypeId;
use core::fmt::{Debug, Display};
/// A stand-in for `std::error::Error`, which requires no allocation.
#[cfg(feature = "nightly")]
pub trait Error: Debug + Display + ::core::marker::Reflect {
/// A short description of the error.
///
/// The description should not contain newlines or sentence-ending
/// punctuation, to facilitate embedding in larger user-facing
/// strings.
fn description(&self) -> &str;
/// The lower-level cause of this error, if any.
fn cause(&self) -> Option<&Error> { None }
/// Get the `TypeId` of `self`
#[doc(hidden)]
fn type_id(&self) -> TypeId where Self: 'static {
TypeId::of::<Self>()
}
}
/// A stand-in for `std::error::Error`, which requires no allocation.
#[cfg(not(feature = "nightly"))]
pub trait Error: Debug + Display {
/// A short description of the error.
///
/// The description should not contain newlines or sentence-ending
/// punctuation, to facilitate embedding in larger user-facing
/// strings.
fn description(&self) -> &str;
/// The lower-level cause of this error, if any.
fn cause(&self) -> Option<&Error> { None }
/// Stubbed! Returns type_id of `()`
#[doc(hidden)]
fn type_id(&self) -> TypeId where Self: 'static {
TypeId::of::<()>()
}
}
+30 -6
View File
@@ -10,22 +10,46 @@
//! [github repository](https://github.com/serde-rs/serde)
#![doc(html_root_url="https://serde-rs.github.io/serde/serde")]
#![cfg_attr(feature = "nightly", feature(collections, core, enumset, nonzero, step_trait, zero_one))]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "nightly", feature(reflect_marker, unicode, nonzero, plugin, step_trait, zero_one))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "collections", feature(collections, enumset))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", allow(linkedlist))]
#![cfg_attr(any(not(feature = "std"), feature = "nightly"), allow(unused_variables, unused_imports, unused_features, dead_code))]
#![deny(missing_docs)]
extern crate num;
#[cfg(feature = "nightly")]
#[cfg(all(feature = "nightly", feature = "collections"))]
extern crate collections;
#[cfg(feature = "nightly")]
extern crate core;
#[cfg(all(feature = "nightly", feature = "alloc"))]
extern crate alloc;
#[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};
#[cfg(feature = "nightly")]
extern crate core;
#[cfg(feature = "nightly")]
pub use self::core::nonzero;
}
pub use ser::{Serialize, Serializer};
pub use de::{Deserialize, Deserializer, Error};
#[cfg(not(feature = "std"))]
macro_rules! format {
($s:expr, $($rest:tt)*) => ($s)
}
pub mod bytes;
pub mod de;
#[cfg(feature = "std")]
pub mod iter;
pub mod ser;
#[cfg(not(feature = "std"))]
pub mod error;
mod utils;
+248 -49
View File
@@ -1,6 +1,11 @@
//! Implementations for all of Rust's builtin types.
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::borrow::Cow;
#[cfg(feature = "std")]
use std::collections::{
BinaryHeap,
BTreeMap,
@@ -10,23 +15,53 @@ use std::collections::{
HashSet,
VecDeque,
};
#[cfg(feature = "nightly")]
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::{
BinaryHeap,
BTreeMap,
BTreeSet,
LinkedList,
VecDeque,
String,
Vec,
};
#[cfg(all(feature = "nightly", feature = "collections"))]
use collections::enum_set::{CLike, EnumSet};
use std::hash::Hash;
#[cfg(all(feature = "nightly", feature = "collections"))]
use collections::borrow::ToOwned;
use core::hash::{Hash, BuildHasher};
#[cfg(feature = "nightly")]
use std::iter;
use core::iter;
#[cfg(feature = "std")]
use std::net;
#[cfg(feature = "nightly")]
use std::num;
use core::num;
#[cfg(feature = "nightly")]
use std::ops;
use core::ops;
#[cfg(feature = "std")]
use std::path;
#[cfg(feature = "std")]
use std::rc::Rc;
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::rc::Rc;
#[cfg(feature = "std")]
use std::sync::Arc;
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::arc::Arc;
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::boxed::Box;
use core::marker::PhantomData;
#[cfg(feature = "nightly")]
use core::nonzero::{NonZero, Zeroable};
use super::{
Error,
Serialize,
Serializer,
SeqVisitor,
@@ -48,20 +83,20 @@ macro_rules! impl_visit {
}
}
impl_visit!(bool, visit_bool);
impl_visit!(isize, visit_isize);
impl_visit!(i8, visit_i8);
impl_visit!(i16, visit_i16);
impl_visit!(i32, visit_i32);
impl_visit!(i64, visit_i64);
impl_visit!(usize, visit_usize);
impl_visit!(u8, visit_u8);
impl_visit!(u16, visit_u16);
impl_visit!(u32, visit_u32);
impl_visit!(u64, visit_u64);
impl_visit!(f32, visit_f32);
impl_visit!(f64, visit_f64);
impl_visit!(char, visit_char);
impl_visit!(bool, serialize_bool);
impl_visit!(isize, serialize_isize);
impl_visit!(i8, serialize_i8);
impl_visit!(i16, serialize_i16);
impl_visit!(i32, serialize_i32);
impl_visit!(i64, serialize_i64);
impl_visit!(usize, serialize_usize);
impl_visit!(u8, serialize_u8);
impl_visit!(u16, serialize_u16);
impl_visit!(u32, serialize_u32);
impl_visit!(u64, serialize_u64);
impl_visit!(f32, serialize_f32);
impl_visit!(f64, serialize_f64);
impl_visit!(char, serialize_char);
///////////////////////////////////////////////////////////////////////////////
@@ -70,10 +105,11 @@ impl Serialize for str {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_str(self)
serializer.serialize_str(self)
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl Serialize for String {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
@@ -91,8 +127,8 @@ impl<T> Serialize for Option<T> where T: Serialize {
where S: Serializer,
{
match *self {
Some(ref value) => serializer.visit_some(value),
None => serializer.visit_none(),
Some(ref value) => serializer.serialize_some(value),
None => serializer.serialize_none(),
}
}
}
@@ -104,7 +140,7 @@ impl<T> SeqVisitor for Option<T> where T: Serialize {
{
match self.take() {
Some(value) => {
try!(serializer.visit_seq_elt(value));
try!(serializer.serialize_seq_elt(value));
Ok(Some(()))
}
None => Ok(None),
@@ -119,6 +155,17 @@ impl<T> SeqVisitor for Option<T> where T: Serialize {
///////////////////////////////////////////////////////////////////////////////
impl<T> Serialize for PhantomData<T> {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_unit_struct("PhantomData")
}
}
///////////////////////////////////////////////////////////////////////////////
/// A `serde::Visitor` for sequence iterators.
///
/// # Examples
@@ -133,7 +180,7 @@ impl<T> SeqVisitor for Option<T> where T: Serialize {
/// fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
/// where S: Serializer,
/// {
/// ser.visit_seq(SeqIteratorVisitor::new(
/// ser.serialize_seq(SeqIteratorVisitor::new(
/// self.0.iter(),
/// Some(self.0.len()),
/// ))
@@ -168,7 +215,7 @@ impl<T, Iter> SeqVisitor for SeqIteratorVisitor<Iter>
{
match self.iter.next() {
Some(value) => {
try!(serializer.visit_seq_elt(value));
try!(serializer.serialize_seq_elt(value));
Ok(Some(()))
}
None => Ok(None),
@@ -190,10 +237,12 @@ impl<T> Serialize for [T]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! array_impls {
($len:expr) => {
impl<T> Serialize for [T; $len] where T: Serialize {
@@ -201,7 +250,8 @@ macro_rules! array_impls {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some($len)))
let visitor = SeqIteratorVisitor::new(self.iter(), Some($len));
serializer.serialize_fixed_size_array(visitor)
}
}
}
@@ -243,6 +293,7 @@ array_impls!(32);
///////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for BinaryHeap<T>
where T: Serialize + Ord
{
@@ -250,10 +301,11 @@ impl<T> Serialize for BinaryHeap<T>
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for BTreeSet<T>
where T: Serialize + Ord,
{
@@ -261,11 +313,11 @@ impl<T> Serialize for BTreeSet<T>
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
#[cfg(feature = "nightly")]
#[cfg(all(feature = "nightly", feature = "collections"))]
impl<T> Serialize for EnumSet<T>
where T: Serialize + CLike
{
@@ -273,21 +325,24 @@ impl<T> Serialize for EnumSet<T>
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
impl<T> Serialize for HashSet<T>
#[cfg(feature = "std")]
impl<T, H> Serialize for HashSet<T, H>
where T: Serialize + Eq + Hash,
H: BuildHasher,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for LinkedList<T>
where T: Serialize,
{
@@ -295,7 +350,7 @@ impl<T> Serialize for LinkedList<T>
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
@@ -309,10 +364,11 @@ impl<A> Serialize for ops::Range<A>
where S: Serializer,
{
let len = iter::Step::steps_between(&self.start, &self.end, &A::one());
serializer.visit_seq(SeqIteratorVisitor::new(self.clone(), len))
serializer.serialize_seq(SeqIteratorVisitor::new(self.clone(), len))
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for Vec<T> where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
@@ -322,12 +378,13 @@ impl<T> Serialize for Vec<T> where T: Serialize {
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for VecDeque<T> where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
@@ -338,7 +395,7 @@ impl Serialize for () {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_unit()
serializer.serialize_unit()
}
}
@@ -382,7 +439,7 @@ macro_rules! tuple_impls {
$(
$state => {
self.state += 1;
Ok(Some(try!(serializer.visit_tuple_elt(&e!(self.tuple.$idx)))))
Ok(Some(try!(serializer.serialize_tuple_elt(&e!(self.tuple.$idx)))))
}
)+
_ => {
@@ -401,7 +458,7 @@ macro_rules! tuple_impls {
{
#[inline]
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
serializer.visit_tuple($TupleVisitor::new(self))
serializer.serialize_tuple($TupleVisitor::new(self))
}
}
)+
@@ -511,6 +568,72 @@ tuple_impls! {
10 => 10,
11 => 11,
}
TupleVisitor13 (13, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
7 => 7,
8 => 8,
9 => 9,
10 => 10,
11 => 11,
12 => 12,
}
TupleVisitor14 (14, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
7 => 7,
8 => 8,
9 => 9,
10 => 10,
11 => 11,
12 => 12,
13 => 13,
}
TupleVisitor15 (15, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
7 => 7,
8 => 8,
9 => 9,
10 => 10,
11 => 11,
12 => 12,
13 => 13,
14 => 14,
}
TupleVisitor16 (16, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
7 => 7,
8 => 8,
9 => 9,
10 => 10,
11 => 11,
12 => 12,
13 => 13,
14 => 14,
15 => 15,
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -530,7 +653,7 @@ tuple_impls! {
/// fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
/// where S: Serializer,
/// {
/// ser.visit_map(MapIteratorVisitor::new(
/// ser.serialize_map(MapIteratorVisitor::new(
/// self.0.iter(),
/// Some(self.0.len()),
/// ))
@@ -566,8 +689,8 @@ impl<K, V, I> MapVisitor for MapIteratorVisitor<I>
{
match self.iter.next() {
Some((key, value)) => {
let value = try!(serializer.visit_map_elt(key, value));
Ok(Some(value))
try!(serializer.serialize_map_elt(key, value));
Ok(Some(()))
}
None => Ok(None)
}
@@ -581,6 +704,7 @@ impl<K, V, I> MapVisitor for MapIteratorVisitor<I>
///////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))]
impl<K, V> Serialize for BTreeMap<K, V>
where K: Serialize + Ord,
V: Serialize,
@@ -589,19 +713,21 @@ impl<K, V> Serialize for BTreeMap<K, V>
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
impl<K, V> Serialize for HashMap<K, V>
#[cfg(feature = "std")]
impl<K, V, H> Serialize for HashMap<K, V, H>
where K: Serialize + Eq + Hash,
V: Serialize,
H: BuildHasher,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
@@ -625,6 +751,7 @@ impl<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize {
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: ?Sized> Serialize for Box<T> where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
@@ -634,6 +761,7 @@ impl<T: ?Sized> Serialize for Box<T> where T: Serialize {
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T> Serialize for Rc<T> where T: Serialize, {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
@@ -643,6 +771,7 @@ impl<T> Serialize for Rc<T> where T: Serialize, {
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T> Serialize for Arc<T> where T: Serialize, {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
@@ -652,6 +781,7 @@ impl<T> Serialize for Arc<T> where T: Serialize, {
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned, {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
@@ -667,10 +797,10 @@ impl<T, E> Serialize for Result<T, E> where T: Serialize, E: Serialize {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
match *self {
Result::Ok(ref value) => {
serializer.visit_newtype_variant("Result", 0, "Ok", value)
serializer.serialize_newtype_variant("Result", 0, "Ok", value)
}
Result::Err(ref value) => {
serializer.visit_newtype_variant("Result", 1, "Err", value)
serializer.serialize_newtype_variant("Result", 1, "Err", value)
}
}
}
@@ -678,19 +808,88 @@ impl<T, E> Serialize for Result<T, E> where T: Serialize, E: Serialize {
///////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "std", feature = "nightly"))]
impl Serialize for net::IpAddr {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
match *self {
net::IpAddr::V4(ref addr) => addr.serialize(serializer),
net::IpAddr::V6(ref addr) => addr.serialize(serializer),
}
}
}
#[cfg(feature = "std")]
impl Serialize for net::Ipv4Addr {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
self.to_string().serialize(serializer)
}
}
#[cfg(feature = "std")]
impl Serialize for net::Ipv6Addr {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
self.to_string().serialize(serializer)
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl Serialize for net::SocketAddr {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
match *self {
net::SocketAddr::V4(ref addr) => addr.serialize(serializer),
net::SocketAddr::V6(ref addr) => addr.serialize(serializer),
}
}
}
#[cfg(feature = "std")]
impl Serialize for net::SocketAddrV4 {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
self.to_string().serialize(serializer)
}
}
#[cfg(feature = "std")]
impl Serialize for net::SocketAddrV6 {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
self.to_string().serialize(serializer)
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl Serialize for path::Path {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
self.to_str().unwrap().serialize(serializer)
match self.to_str() {
Some(s) => s.serialize(serializer),
None => Err(Error::invalid_value("Path contains invalid UTF-8 characters")),
}
}
}
#[cfg(feature = "std")]
impl Serialize for path::PathBuf {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
self.to_str().unwrap().serialize(serializer)
self.as_path().serialize(serializer)
}
}
+155 -126
View File
@@ -1,9 +1,36 @@
//! Generic serialization framework.
#[cfg(feature = "std")]
use std::error;
#[cfg(not(feature = "std"))]
use error;
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::String;
pub mod impls;
///////////////////////////////////////////////////////////////////////////////
/// `Error` is a trait that allows a `Serialize` to generically create a
/// `Serializer` error.
pub trait Error: Sized + error::Error {
/// Raised when there is general error when deserializing a type.
#[cfg(any(feature = "std", feature = "collections"))]
fn custom<T: Into<String>>(msg: T) -> Self;
/// Raised when there is general error when deserializing a type.
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
fn custom<T: Into<&'static str>>(msg: T) -> Self;
/// Raised when a `Serialize` was passed an incorrect value.
fn invalid_value(msg: &str) -> Self {
Error::custom(format!("invalid value: {}", msg))
}
}
///////////////////////////////////////////////////////////////////////////////
/// A trait that describes a type that can be serialized by a `Serializer`.
pub trait Serialize {
/// Serializes this value into this serializer.
@@ -16,249 +43,257 @@ pub trait Serialize {
/// A trait that describes a type that can serialize a stream of values into the underlying format.
pub trait Serializer {
/// The error type that can be returned if some error occurs during serialization.
type Error;
type Error: Error;
/// `visit_bool` serializes a `bool` value.
fn visit_bool(&mut self, v: bool) -> Result<(), Self::Error>;
/// Serializes a `bool` value.
fn serialize_bool(&mut self, v: bool) -> Result<(), Self::Error>;
/// `visit_isize` serializes a `isize` value. By default it casts the value to a `i64` and
/// passes it to the `visit_i64` method.
/// Serializes a `isize` value. By default it casts the value to a `i64` and
/// passes it to the `serialize_i64` method.
#[inline]
fn visit_isize(&mut self, v: isize) -> Result<(), Self::Error> {
self.visit_i64(v as i64)
fn serialize_isize(&mut self, v: isize) -> Result<(), Self::Error> {
self.serialize_i64(v as i64)
}
/// `visit_i8` serializes a `i8` value. By default it casts the value to a `i64` and
/// passes it to the `visit_i64` method.
/// Serializes a `i8` value. By default it casts the value to a `i64` and
/// passes it to the `serialize_i64` method.
#[inline]
fn visit_i8(&mut self, v: i8) -> Result<(), Self::Error> {
self.visit_i64(v as i64)
fn serialize_i8(&mut self, v: i8) -> Result<(), Self::Error> {
self.serialize_i64(v as i64)
}
/// `visit_i16` serializes a `i16` value. By default it casts the value to a `i64` and
/// passes it to the `visit_i64` method.
/// Serializes a `i16` value. By default it casts the value to a `i64` and
/// passes it to the `serialize_i64` method.
#[inline]
fn visit_i16(&mut self, v: i16) -> Result<(), Self::Error> {
self.visit_i64(v as i64)
fn serialize_i16(&mut self, v: i16) -> Result<(), Self::Error> {
self.serialize_i64(v as i64)
}
/// `visit_i32` serializes a `i32` value. By default it casts the value to a `i64` and
/// passes it to the `visit_i64` method.
/// Serializes a `i32` value. By default it casts the value to a `i64` and
/// passes it to the `serialize_i64` method.
#[inline]
fn visit_i32(&mut self, v: i32) -> Result<(), Self::Error> {
self.visit_i64(v as i64)
fn serialize_i32(&mut self, v: i32) -> Result<(), Self::Error> {
self.serialize_i64(v as i64)
}
/// `visit_i64` serializes a `i64` value.
/// Serializes a `i64` value.
#[inline]
fn visit_i64(&mut self, v: i64) -> Result<(), Self::Error>;
fn serialize_i64(&mut self, v: i64) -> Result<(), Self::Error>;
/// `visit_usize` serializes a `usize` value. By default it casts the value to a `u64` and
/// passes it to the `visit_u64` method.
/// Serializes a `usize` value. By default it casts the value to a `u64` and
/// passes it to the `serialize_u64` method.
#[inline]
fn visit_usize(&mut self, v: usize) -> Result<(), Self::Error> {
self.visit_u64(v as u64)
fn serialize_usize(&mut self, v: usize) -> Result<(), Self::Error> {
self.serialize_u64(v as u64)
}
/// `visit_u8` serializes a `u8` value. By default it casts the value to a `u64` and passes
/// it to the `visit_u64` method.
/// Serializes a `u8` value. By default it casts the value to a `u64` and passes
/// it to the `serialize_u64` method.
#[inline]
fn visit_u8(&mut self, v: u8) -> Result<(), Self::Error> {
self.visit_u64(v as u64)
fn serialize_u8(&mut self, v: u8) -> Result<(), Self::Error> {
self.serialize_u64(v as u64)
}
/// `visit_u32` serializes a `u32` value. By default it casts the value to a `u64` and passes
/// it to the `visit_u64` method.
/// Serializes a `u32` value. By default it casts the value to a `u64` and passes
/// it to the `serialize_u64` method.
#[inline]
fn visit_u16(&mut self, v: u16) -> Result<(), Self::Error> {
self.visit_u64(v as u64)
fn serialize_u16(&mut self, v: u16) -> Result<(), Self::Error> {
self.serialize_u64(v as u64)
}
/// `visit_u32` serializes a `u32` value. By default it casts the value to a `u64` and passes
/// it to the `visit_u64` method.
/// Serializes a `u32` value. By default it casts the value to a `u64` and passes
/// it to the `serialize_u64` method.
#[inline]
fn visit_u32(&mut self, v: u32) -> Result<(), Self::Error> {
self.visit_u64(v as u64)
fn serialize_u32(&mut self, v: u32) -> Result<(), Self::Error> {
self.serialize_u64(v as u64)
}
/// `visit_u64` serializes a `u64` value.
/// `Serializes a `u64` value.
#[inline]
fn visit_u64(&mut self, v: u64) -> Result<(), Self::Error>;
fn serialize_u64(&mut self, v: u64) -> Result<(), Self::Error>;
/// `visit_f32` serializes a `f32` value. By default it casts the value to a `f64` and passes
/// it to the `visit_f64` method.
/// Serializes a `f32` value. By default it casts the value to a `f64` and passes
/// it to the `serialize_f64` method.
#[inline]
fn visit_f32(&mut self, v: f32) -> Result<(), Self::Error> {
self.visit_f64(v as f64)
fn serialize_f32(&mut self, v: f32) -> Result<(), Self::Error> {
self.serialize_f64(v as f64)
}
/// `visit_f64` serializes a `f64` value.
fn visit_f64(&mut self, v: f64) -> Result<(), Self::Error>;
/// Serializes a `f64` value.
fn serialize_f64(&mut self, v: f64) -> Result<(), Self::Error>;
/// `visit_char` serializes a character. By default it serializes it as a `&str` containing a
/// Serializes a character. By default it serializes it as a `&str` containing a
/// single character.
#[inline]
fn visit_char(&mut self, v: char) -> Result<(), Self::Error> {
// FIXME: this allocation is required in order to be compatible with stable rust, which
// doesn't support encoding a `char` into a stack buffer.
self.visit_str(&v.to_string())
fn serialize_char(&mut self, v: char) -> Result<(), Self::Error> {
self.serialize_str(::utils::encode_utf8(v).as_str())
}
/// `visit_str` serializes a `&str`.
fn visit_str(&mut self, value: &str) -> Result<(), Self::Error>;
/// Serializes a `&str`.
fn serialize_str(&mut self, value: &str) -> Result<(), Self::Error>;
/// `visit_bytes` is a hook that enables those serialization formats that support serializing
/// Enables those serialization formats that support serializing
/// byte slices separately from generic arrays. By default it serializes as a regular array.
#[inline]
fn visit_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error> {
self.visit_seq(impls::SeqIteratorVisitor::new(value.iter(), Some(value.len())))
fn serialize_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error> {
self.serialize_seq(impls::SeqIteratorVisitor::new(value.iter(), Some(value.len())))
}
/// Serializes a `()` value.
fn visit_unit(&mut self) -> Result<(), Self::Error>;
fn serialize_unit(&mut self) -> Result<(), Self::Error>;
/// Serializes a unit struct value.
///
/// By default, unit structs are serialized as a `()`.
#[inline]
fn visit_unit_struct(&mut self, _name: &'static str) -> Result<(), Self::Error> {
self.visit_unit()
fn serialize_unit_struct(&mut self, _name: &'static str) -> Result<(), Self::Error> {
self.serialize_unit()
}
/// Serializes a unit variant, otherwise known as a variant with no arguments.
///
/// By default, unit variants are serialized as a `()`.
#[inline]
fn visit_unit_variant(&mut self,
_name: &'static str,
_variant_index: usize,
_variant: &'static str) -> Result<(), Self::Error> {
self.visit_unit()
fn serialize_unit_variant(&mut self,
_name: &'static str,
_variant_index: usize,
_variant: &'static str) -> Result<(), Self::Error> {
self.serialize_unit()
}
/// The `visit_newtype_struct` allows a tuple struct with a single element, also known as a
/// Allows a tuple struct with a single element, also known as a
/// newtyped value, to be more efficiently serialized than a tuple struct with multiple items.
/// By default it just serializes the value as a tuple struct sequence.
#[inline]
fn visit_newtype_struct<T>(&mut self,
name: &'static str,
value: T) -> Result<(), Self::Error>
fn serialize_newtype_struct<T>(&mut self,
name: &'static str,
value: T) -> Result<(), Self::Error>
where T: Serialize,
{
self.visit_tuple_struct(name, Some(value))
self.serialize_tuple_struct(name, Some(value))
}
/// The `visit_newtype_variant` allows a variant with a single item to be more efficiently
/// Allows a variant with a single item to be more efficiently
/// serialized than a variant with multiple items. By default it just serializes the value as a
/// tuple variant sequence.
#[inline]
fn visit_newtype_variant<T>(&mut self,
name: &'static str,
variant_index: usize,
variant: &'static str,
value: T) -> Result<(), Self::Error>
fn serialize_newtype_variant<T>(&mut self,
name: &'static str,
variant_index: usize,
variant: &'static str,
value: T) -> Result<(), Self::Error>
where T: Serialize,
{
self.visit_tuple_variant(
self.serialize_tuple_variant(
name,
variant_index,
variant,
Some(value))
}
/// Serializes a `None` value.
fn visit_none(&mut self) -> Result<(), Self::Error>;
/// Serializes a `None` value..serialize
fn serialize_none(&mut self) -> Result<(), Self::Error>;
/// Serializes a `Some(...)` value.
fn visit_some<V>(&mut self, value: V) -> Result<(), Self::Error>
fn serialize_some<V>(&mut self, value: V) -> Result<(), Self::Error>
where V: Serialize;
/// Serializes a sequence.
///
/// Callees of this method need to construct a `SeqVisitor`, which iterates through each item
/// in the sequence.
fn visit_seq<V>(&mut self, visitor: V) -> Result<(), Self::Error>
fn serialize_seq<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor;
/// Serializes a sequence element.
fn visit_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
fn serialize_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize;
/// Serializes a tuple.
///
/// By default this serializes a tuple as a sequence.
#[inline]
fn visit_tuple<V>(&mut self, visitor: V) -> Result<(), Self::Error>
fn serialize_tuple<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.visit_seq(visitor)
self.serialize_seq(visitor)
}
/// Serializes a tuple element.
///
/// By default, tuples are serialized as a sequence.
#[inline]
fn visit_tuple_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
fn serialize_tuple_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize
{
self.visit_seq_elt(value)
self.serialize_seq_elt(value)
}
/// Serializes a fixed-size array.
///
/// By default this serializes an array as a sequence.
#[inline]
fn serialize_fixed_size_array<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.serialize_seq(visitor)
}
/// Serializes a tuple struct.
///
/// By default, tuple structs are serialized as a tuple.
#[inline]
fn visit_tuple_struct<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<(), Self::Error>
fn serialize_tuple_struct<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.visit_tuple(visitor)
self.serialize_tuple(visitor)
}
/// Serializes a tuple struct element.
///
/// By default, tuple struct elements are serialized as a tuple element.
#[inline]
fn visit_tuple_struct_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
fn serialize_tuple_struct_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize
{
self.visit_tuple_elt(value)
self.serialize_tuple_elt(value)
}
/// Serializes a tuple variant.
///
/// By default, tuple variants are serialized as a tuple struct.
#[inline]
fn visit_tuple_variant<V>(&mut self,
_name: &'static str,
_variant_index: usize,
variant: &'static str,
visitor: V) -> Result<(), Self::Error>
fn serialize_tuple_variant<V>(&mut self,
_name: &'static str,
_variant_index: usize,
variant: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.visit_tuple_struct(variant, visitor)
self.serialize_tuple_struct(variant, visitor)
}
/// Serializes a tuple element.
///
/// By default, tuples are serialized as a sequence.
#[inline]
fn visit_tuple_variant_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
fn serialize_tuple_variant_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize
{
self.visit_tuple_struct_elt(value)
self.serialize_tuple_struct_elt(value)
}
/// Serializes a map.
///
/// Callees of this method need to construct a `MapVisitor`, which iterates through each item
/// in the map.
fn visit_map<V>(&mut self, visitor: V) -> Result<(), Self::Error>
fn serialize_map<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: MapVisitor;
/// Serializes a map element (key-value pair).
fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
fn serialize_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
where K: Serialize,
V: Serialize;
@@ -266,62 +301,55 @@ pub trait Serializer {
///
/// By default, structs are serialized as a map with the field name as the key.
#[inline]
fn visit_struct<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<(), Self::Error>
fn serialize_struct<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: MapVisitor,
{
self.visit_map(visitor)
self.serialize_map(visitor)
}
/// Serializes an element of a struct.
///
/// By default, struct elements are serialized as a map element with the field name as the key.
#[inline]
fn visit_struct_elt<V>(&mut self,
key: &'static str,
value: V) -> Result<(), Self::Error>
fn serialize_struct_elt<V>(&mut self,
key: &'static str,
value: V) -> Result<(), Self::Error>
where V: Serialize,
{
self.visit_map_elt(key, value)
self.serialize_map_elt(key, value)
}
/// Serializes a struct variant.
///
/// By default, struct variants are serialized as a struct.
#[inline]
fn visit_struct_variant<V>(&mut self,
_name: &'static str,
_variant_index: usize,
variant: &'static str,
visitor: V) -> Result<(), Self::Error>
fn serialize_struct_variant<V>(&mut self,
_name: &'static str,
_variant_index: usize,
variant: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: MapVisitor,
{
self.visit_struct(variant, visitor)
self.serialize_struct(variant, visitor)
}
/// Serializes an element of a struct variant.
///
/// By default, struct variant elements are serialized as a struct element.
#[inline]
fn visit_struct_variant_elt<V>(&mut self,
key: &'static str,
value: V) -> Result<(), Self::Error>
fn serialize_struct_variant_elt<V>(&mut self,
key: &'static str,
value: V) -> Result<(), Self::Error>
where V: Serialize,
{
self.visit_struct_elt(key, value)
}
/// Specify a format string for the serializer.
///
/// The serializer format is used to determine which format
/// specific field attributes should be used with the serializer.
fn format() -> &'static str {
""
self.serialize_struct_elt(key, value)
}
}
/// A trait that is used by a `Serialize` to iterate through a sequence.
#[cfg_attr(feature = "nightly-testing", allow(len_without_is_empty))]
pub trait SeqVisitor {
/// Serializes a sequence item in the serializer.
///
@@ -338,6 +366,7 @@ pub trait SeqVisitor {
}
/// A trait that is used by a `Serialize` to iterate through a map.
#[cfg_attr(feature = "nightly-testing", allow(len_without_is_empty))]
pub trait MapVisitor {
/// Serializes a map item in the serializer.
///
+72
View File
@@ -0,0 +1,72 @@
//! Private utility functions
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;
#[inline]
pub fn encode_utf8(c: char) -> EncodeUtf8 {
let code = c as u32;
let mut buf = [0; 4];
let pos = if code < MAX_ONE_B {
buf[3] = code as u8;
3
} else if code < MAX_TWO_B {
buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
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[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[3] = (code & 0x3F) as u8 | TAG_CONT;
0
};
EncodeUtf8 { buf: buf, pos: pos }
}
pub struct EncodeUtf8 {
buf: [u8; 4],
pos: usize,
}
impl EncodeUtf8 {
// FIXME: use this from_utf8_unchecked, since we know it can never fail
pub fn as_str(&self) -> &str {
::core::str::from_utf8(&self.buf[self.pos..]).unwrap()
}
}
#[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}')
];
fn bsearch_range_table(c: char, r: &'static [(char, char)]) -> bool {
use core::cmp::Ordering::{Equal, Less, Greater};
r.binary_search_by(|&(lo, hi)| {
if c < lo {
Greater
} else if hi < c {
Less
} else {
Equal
}
})
.is_ok()
}
#[allow(non_snake_case)]
pub fn Pattern_White_Space(c: char) -> bool {
bsearch_range_table(c, Pattern_White_Space_table)
}
+22 -11
View File
@@ -1,26 +1,37 @@
[package]
name = "serde_codegen"
version = "0.6.4"
version = "0.7.15"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde-rs.github.io/serde/serde_codegen/serde_codegen/index.html"
build = "build.rs"
documentation = "https://github.com/serde-rs/serde"
keywords = ["serde", "serialization"]
build = "build.rs"
include = ["Cargo.toml", "build.rs", "src/**/*.rs", "src/lib.rs.in"]
[features]
default = ["with-syntex"]
nightly = ["quasi_macros"]
with-syntex = ["quasi/with-syntex", "quasi_codegen", "quasi_codegen/with-syntex", "syntex", "syntex_syntax"]
nightly-testing = ["clippy"]
with-syntex = [
"quasi/with-syntex",
"quasi_codegen",
"quasi_codegen/with-syntex",
"serde_codegen_internals/with-syntex",
"syntex",
"syntex_syntax",
]
[build-dependencies]
quasi_codegen = { verision = "^0.3.8", optional = true }
syntex = { version = "^0.22.0", optional = true }
quasi_codegen = { version = "^0.16.0", optional = true }
syntex = { version = "^0.39.0", optional = true }
[dependencies]
aster = { version = "^0.8.0", default-features = false }
quasi = { verision = "^0.3.8", default-features = false }
quasi_macros = { version = "^0.3.8", optional = true }
syntex = { version = "^0.22.0", optional = true }
syntex_syntax = { version = "^0.22.0", optional = true }
aster = { version = "^0.22.0", default-features = false }
clippy = { version = "^0.*", optional = true }
quasi = { version = "^0.16.0", default-features = false }
quasi_macros = { version = "^0.16.0", optional = true }
serde_codegen_internals = { version = "^0.4.0", default-features = false }
syntex = { version = "^0.39.0", optional = true }
syntex_syntax = { version = "^0.39.0", optional = true }
+1 -4
View File
@@ -1,6 +1,5 @@
#[cfg(feature = "with-syntex")]
mod inner {
extern crate syntex;
extern crate quasi_codegen;
use std::env;
@@ -8,13 +7,11 @@ mod inner {
pub fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let mut registry = syntex::Registry::new();
quasi_codegen::register(&mut registry);
let src = Path::new("src/lib.rs.in");
let dst = Path::new(&out_dir).join("lib.rs");
registry.expand("", &src, &dst).unwrap();
quasi_codegen::expand(&src, &dst).unwrap();
}
}
-245
View File
@@ -1,245 +0,0 @@
use std::collections::HashMap;
use std::collections::HashSet;
use syntax::ast;
use syntax::attr;
use syntax::ext::base::ExtCtxt;
use syntax::ptr::P;
use aster;
/// Represents field name information
#[derive(Debug)]
pub enum FieldNames {
Global(P<ast::Expr>),
Format{
formats: HashMap<P<ast::Expr>, P<ast::Expr>>,
default: P<ast::Expr>,
}
}
/// Represents field attribute information
#[derive(Debug)]
pub struct FieldAttrs {
skip_serializing_field: bool,
skip_serializing_field_if_empty: bool,
skip_serializing_field_if_none: bool,
names: FieldNames,
use_default: bool,
}
impl FieldAttrs {
/// Return a set of formats that the field has attributes for.
pub fn formats(&self) -> HashSet<P<ast::Expr>> {
match self.names {
FieldNames::Format{ref formats, default: _} => {
let mut set = HashSet::new();
for (fmt, _) in formats.iter() {
set.insert(fmt.clone());
};
set
},
_ => HashSet::new()
}
}
/// Return an expression for the field key name for serialisation.
///
/// The resulting expression assumes that `S` refers to a type
/// that implements `Serializer`.
pub fn serializer_key_expr(&self, cx: &ExtCtxt) -> P<ast::Expr> {
match self.names {
FieldNames::Global(ref name) => name.clone(),
FieldNames::Format { ref formats, ref default } => {
let arms = formats.iter()
.map(|(fmt, lit)| {
quote_arm!(cx, $fmt => { $lit })
})
.collect::<Vec<_>>();
quote_expr!(cx,
match S::format() {
$arms
_ => { $default }
}
)
},
}
}
/// Return the default field name for the field.
pub fn default_key_expr(&self) -> &P<ast::Expr> {
match self.names {
FieldNames::Global(ref expr) => expr,
FieldNames::Format{formats: _, ref default} => default,
}
}
/// Return the field name for the field in the specified format.
pub fn key_expr(&self, format: &P<ast::Expr>) -> &P<ast::Expr> {
match self.names {
FieldNames::Global(ref expr) => expr,
FieldNames::Format { ref formats, ref default } => {
formats.get(format).unwrap_or(default)
}
}
}
/// Predicate for using a field's default value
pub fn use_default(&self) -> bool {
self.use_default
}
/// Predicate for ignoring a field when serializing a value
pub fn skip_serializing_field(&self) -> bool {
self.skip_serializing_field
}
pub fn skip_serializing_field_if_empty(&self) -> bool {
self.skip_serializing_field_if_empty
}
pub fn skip_serializing_field_if_none(&self) -> bool {
self.skip_serializing_field_if_none
}
}
pub struct FieldAttrsBuilder<'a> {
builder: &'a aster::AstBuilder,
skip_serializing_field: bool,
skip_serializing_field_if_empty: bool,
skip_serializing_field_if_none: bool,
name: Option<P<ast::Expr>>,
format_rename: HashMap<P<ast::Expr>, P<ast::Expr>>,
use_default: bool,
}
impl<'a> FieldAttrsBuilder<'a> {
pub fn new(builder: &'a aster::AstBuilder) -> FieldAttrsBuilder<'a> {
FieldAttrsBuilder {
builder: builder,
skip_serializing_field: false,
skip_serializing_field_if_empty: false,
skip_serializing_field_if_none: false,
name: None,
format_rename: HashMap::new(),
use_default: false,
}
}
pub fn field(mut self, field: &ast::StructField) -> FieldAttrsBuilder<'a> {
match field.node.kind {
ast::NamedField(name, _) => {
self.name = Some(self.builder.expr().str(name));
}
ast::UnnamedField(_) => { }
};
self.attrs(&field.node.attrs)
}
pub fn attrs(self, attrs: &[ast::Attribute]) -> FieldAttrsBuilder<'a> {
attrs.iter().fold(self, FieldAttrsBuilder::attr)
}
pub fn attr(self, attr: &ast::Attribute) -> FieldAttrsBuilder<'a> {
match attr.node.value.node {
ast::MetaList(ref name, ref items) if name == &"serde" => {
attr::mark_used(&attr);
items.iter().fold(self, FieldAttrsBuilder::meta_item)
}
_ => {
self
}
}
}
pub fn meta_item(mut self, meta_item: &P<ast::MetaItem>) -> FieldAttrsBuilder<'a> {
match meta_item.node {
ast::MetaNameValue(ref name, ref lit) if name == &"rename" => {
let expr = self.builder.expr().build_lit(P(lit.clone()));
self.name(expr)
}
ast::MetaList(ref name, ref items) if name == &"rename" => {
for item in items {
match item.node {
ast::MetaNameValue(ref name, ref lit) => {
let name = self.builder.expr().str(name);
let expr = self.builder.expr().build_lit(P(lit.clone()));
self = self.format_rename(name, expr);
}
_ => { }
}
}
self
}
ast::MetaWord(ref name) if name == &"default" => {
self.default()
}
ast::MetaWord(ref name) if name == &"skip_serializing" => {
self.skip_serializing_field()
}
ast::MetaWord(ref name) if name == &"skip_serializing_if_empty" => {
self.skip_serializing_field_if_empty()
}
ast::MetaWord(ref name) if name == &"skip_serializing_if_none" => {
self.skip_serializing_field_if_none()
}
_ => {
// Ignore unknown meta variables for now.
self
}
}
}
pub fn skip_serializing_field(mut self) -> FieldAttrsBuilder<'a> {
self.skip_serializing_field = true;
self
}
pub fn skip_serializing_field_if_empty(mut self) -> FieldAttrsBuilder<'a> {
self.skip_serializing_field_if_empty = true;
self
}
pub fn skip_serializing_field_if_none(mut self) -> FieldAttrsBuilder<'a> {
self.skip_serializing_field_if_none = true;
self
}
pub fn name(mut self, name: P<ast::Expr>) -> FieldAttrsBuilder<'a> {
self.name = Some(name);
self
}
pub fn format_rename(mut self, format: P<ast::Expr>, name: P<ast::Expr>) -> FieldAttrsBuilder<'a> {
self.format_rename.insert(format, name);
self
}
pub fn default(mut self) -> FieldAttrsBuilder<'a> {
self.use_default = true;
self
}
pub fn build(self) -> FieldAttrs {
let name = self.name.expect("here");
let names = if self.format_rename.is_empty() {
FieldNames::Global(name)
} else {
FieldNames::Format {
formats: self.format_rename,
default: name,
}
};
FieldAttrs {
skip_serializing_field: self.skip_serializing_field,
skip_serializing_field_if_empty: self.skip_serializing_field_if_empty,
skip_serializing_field_if_none: self.skip_serializing_field_if_none,
names: names,
use_default: self.use_default,
}
}
}
+150
View File
@@ -0,0 +1,150 @@
use aster::AstBuilder;
use syntax::ast;
use syntax::ptr::P;
use syntax::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: &ast::Generics) -> ast::Generics {
ast::Generics {
ty_params: generics.ty_params.iter().map(|ty_param| {
ast::TyParam {
default: None,
.. ty_param.clone()
}}).collect(),
.. generics.clone()
}
}
pub fn with_where_predicates(
builder: &AstBuilder,
generics: &ast::Generics,
predicates: &[ast::WherePredicate],
) -> ast::Generics {
builder.from_generics(generics.clone())
.with_predicates(predicates.to_vec())
.build()
}
pub fn with_where_predicates_from_fields<F>(
builder: &AstBuilder,
item: &Item,
generics: &ast::Generics,
from_field: F,
) -> ast::Generics
where F: Fn(&attr::Field) -> Option<&[ast::WherePredicate]>,
{
builder.from_generics(generics.clone())
.with_predicates(
item.body.all_fields()
.flat_map(|field| from_field(&field.attrs))
.flat_map(|predicates| predicates.to_vec()))
.build()
}
pub fn with_bound<F>(
builder: &AstBuilder,
item: &Item,
generics: &ast::Generics,
filter: F,
bound: &ast::Path,
) -> ast::Generics
where F: Fn(&attr::Field) -> bool,
{
builder.from_generics(generics.clone())
.with_predicates(
item.body.all_fields()
.filter(|&field| filter(&field.attrs))
.map(|field| &field.ty)
.filter(|ty| !contains_recursion(ty, item.ident))
.map(|ty| strip_reference(ty))
.map(|ty| builder.where_predicate()
// the type that is being bounded e.g. T
.bound().build(ty.clone())
// the bound e.g. Serialize
.bound().trait_(bound.clone()).build()
.build()))
.build()
}
// We do not attempt to generate any bounds based on field types that are
// directly recursive, as in:
//
// struct Test<D> {
// next: Box<Test<D>>,
// }
//
// This does not catch field types that are mutually recursive with some other
// type. For those, we require bounds to be specified by a `bound` attribute if
// the inferred ones are not correct.
//
// struct Test<D> {
// #[serde(bound="D: Serialize + Deserialize")]
// next: Box<Other<D>>,
// }
// struct Other<D> {
// #[serde(bound="D: Serialize + Deserialize")]
// next: Box<Test<D>>,
// }
fn contains_recursion(ty: &ast::Ty, ident: ast::Ident) -> bool {
struct FindRecursion {
ident: ast::Ident,
found_recursion: bool,
}
impl visit::Visitor for FindRecursion {
fn visit_path(&mut self, path: &ast::Path, _id: ast::NodeId) {
if !path.global
&& path.segments.len() == 1
&& path.segments[0].identifier == self.ident {
self.found_recursion = true;
} else {
visit::walk_path(self, path);
}
}
}
let mut visitor = FindRecursion {
ident: ident,
found_recursion: false,
};
visit::walk_ty(&mut visitor, ty);
visitor.found_recursion
}
// This is required to handle types that use both a reference and a value of
// the same type, as in:
//
// enum Test<'a, T> where T: 'a {
// Lifetime(&'a T),
// NoLifetime(T),
// }
//
// Preserving references, we would generate an impl like:
//
// impl<'a, T> Serialize for Test<'a, T>
// where &'a T: Serialize,
// T: Serialize { ... }
//
// And taking a reference to one of the elements would fail with:
//
// error: cannot infer an appropriate lifetime for pattern due
// to conflicting requirements [E0495]
// Test::NoLifetime(ref v) => { ... }
// ^~~~~
//
// Instead, we strip references before adding `T: Serialize` bounds in order to
// generate:
//
// impl<'a, T> Serialize for Test<'a, T>
// where T: Serialize { ... }
fn strip_reference(mut ty: &P<ast::Ty>) -> &P<ast::Ty> {
while let ast::TyKind::Rptr(_, ref mut_ty) = ty.node {
ty = &mut_ty.ty;
}
ty
}
+768 -600
View File
File diff suppressed because it is too large Load Diff
-17
View File
@@ -1,17 +0,0 @@
use syntax::ast;
use syntax::ext::base::ExtCtxt;
use aster;
use attr::{FieldAttrs, FieldAttrsBuilder};
pub fn struct_field_attrs(
_cx: &ExtCtxt,
builder: &aster::AstBuilder,
fields: &[ast::StructField],
) -> Vec<FieldAttrs> {
fields.iter()
.map(|field| {
FieldAttrsBuilder::new(builder).field(field).build()
})
.collect()
}
+36 -11
View File
@@ -1,20 +1,33 @@
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(feature = "nightly-testing", allow(too_many_arguments))]
#![cfg_attr(feature = "nightly-testing", allow(used_underscore_binding))]
#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private, plugin))]
#![cfg_attr(not(feature = "with-syntex"), plugin(quasi_macros))]
extern crate aster;
extern crate quasi;
extern crate serde_codegen_internals as internals;
#[cfg(feature = "with-syntex")]
extern crate syntex;
#[cfg(feature = "with-syntex")]
#[macro_use]
extern crate syntex_syntax as syntax;
#[cfg(not(feature = "with-syntex"))]
#[macro_use]
extern crate syntax;
#[cfg(not(feature = "with-syntex"))]
extern crate rustc;
extern crate rustc_plugin;
#[cfg(feature = "with-syntex")]
use std::path::Path;
#[cfg(not(feature = "with-syntex"))]
use syntax::feature_gate::AttributeType;
#[cfg(feature = "with-syntex")]
include!(concat!(env!("OUT_DIR"), "/lib.rs"));
@@ -22,18 +35,20 @@ include!(concat!(env!("OUT_DIR"), "/lib.rs"));
#[cfg(not(feature = "with-syntex"))]
include!("lib.rs.in");
#[cfg(feature = "with-syntex")]
pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
where S: AsRef<Path>,
D: AsRef<Path>,
{
let mut registry = syntex::Registry::new();
register(&mut registry);
registry.expand("", src.as_ref(), dst.as_ref())
}
#[cfg(feature = "with-syntex")]
pub fn register(reg: &mut syntex::Registry) {
use syntax::{ast, fold};
reg.add_attr("feature(custom_derive)");
reg.add_attr("feature(custom_attribute)");
reg.add_decorator("derive_Serialize", ser::expand_derive_serialize);
reg.add_decorator("derive_Deserialize", de::expand_derive_deserialize);
reg.add_post_expansion_pass(strip_attributes);
/// Strip the serde attributes from the crate.
#[cfg(feature = "with-syntex")]
fn strip_attributes(krate: ast::Crate) -> ast::Crate {
@@ -43,7 +58,7 @@ pub fn register(reg: &mut syntex::Registry) {
impl fold::Folder for StripAttributeFolder {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
match attr.node.value.node {
ast::MetaList(ref n, _) if n == &"serde" => { return None; }
ast::MetaItemKind::List(ref n, _) if n == &"serde" => { return None; }
_ => {}
}
@@ -57,10 +72,18 @@ pub fn register(reg: &mut syntex::Registry) {
fold::Folder::fold_crate(&mut StripAttributeFolder, krate)
}
reg.add_attr("feature(custom_derive)");
reg.add_attr("feature(custom_attribute)");
reg.add_decorator("derive_Serialize", ser::expand_derive_serialize);
reg.add_decorator("derive_Deserialize", de::expand_derive_deserialize);
reg.add_post_expansion_pass(strip_attributes);
}
#[cfg(not(feature = "with-syntex"))]
pub fn register(reg: &mut rustc::plugin::Registry) {
pub fn register(reg: &mut rustc_plugin::Registry) {
reg.register_syntax_extension(
syntax::parse::token::intern("derive_Serialize"),
syntax::ext::base::MultiDecorator(
@@ -70,4 +93,6 @@ pub fn register(reg: &mut rustc::plugin::Registry) {
syntax::parse::token::intern("derive_Deserialize"),
syntax::ext::base::MultiDecorator(
Box::new(de::expand_derive_deserialize)));
reg.register_attribute("serde".to_owned(), AttributeType::Normal);
}
+2 -2
View File
@@ -1,4 +1,4 @@
mod attr;
mod bound;
mod de;
mod field;
mod ser;
mod span;
+420 -268
View File
@@ -1,18 +1,14 @@
use aster;
use syntax::ast::{
Ident,
MetaItem,
Item,
Expr,
};
use syntax::ast;
use syntax::ast::{self, Ident, MetaItem};
use syntax::codemap::Span;
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;
use field::struct_field_attrs;
use bound;
use span;
use internals::ast::{Body, Field, Item, Style, Variant};
use internals::{attr, Error};
pub fn expand_derive_serialize(
cx: &mut ExtCtxt,
@@ -26,51 +22,95 @@ pub fn expand_derive_serialize(
_ => {
cx.span_err(
meta_item.span,
"`derive` may only be applied to structs and enums");
"`#[derive(Serialize)]` may only be applied to structs and enums");
return;
}
};
let item = match Item::from_ast(cx, item) {
Ok(item) => item,
Err(Error::UnexpectedItemKind) => {
cx.span_err(item.span,
"`#[derive(Serialize)]` may only be applied to structs and enums");
return;
}
};
let builder = aster::AstBuilder::new().span(span);
let generics = match item.node {
ast::ItemStruct(_, ref generics) => generics,
ast::ItemEnum(_, ref generics) => generics,
_ => cx.bug("expected ItemStruct or ItemEnum in #[derive(Serialize)]")
};
let impl_item = serialize_item(cx, &builder, &item);
push(span::record_expansion(cx, impl_item, "Serialize"))
}
let impl_generics = builder.from_generics(generics.clone())
.add_ty_param_bound(
builder.path().global().ids(&["serde", "ser", "Serialize"]).build()
)
.build();
fn serialize_item(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
item: &Item,
) -> P<ast::Item> {
let impl_generics = build_impl_generics(builder, &item);
let ty = builder.ty().path()
.segment(item.ident).with_generics(impl_generics.clone()).build()
.build();
let body = serialize_body(
cx,
&builder,
&item,
&impl_generics,
ty.clone(),
);
let body = serialize_body(cx,
builder,
&item,
&impl_generics,
ty.clone());
let where_clause = &impl_generics.where_clause;
let impl_item = quote_item!(cx,
#[automatically_derived]
impl $impl_generics ::serde::ser::Serialize for $ty $where_clause {
fn serialize<__S>(&self, serializer: &mut __S) -> ::std::result::Result<(), __S::Error>
where __S: ::serde::ser::Serializer,
{
$body
}
}
).unwrap();
let dummy_const = builder.id(format!("_IMPL_SERIALIZE_FOR_{}", item.ident));
push(Annotatable::Item(impl_item))
quote_item!(cx,
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const $dummy_const: () = {
extern crate serde as _serde;
#[automatically_derived]
impl $impl_generics _serde::ser::Serialize for $ty $where_clause {
fn serialize<__S>(&self, _serializer: &mut __S) -> ::std::result::Result<(), __S::Error>
where __S: _serde::ser::Serializer,
{
$body
}
}
};
).unwrap()
}
// 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(
builder: &aster::AstBuilder,
item: &Item,
) -> ast::Generics {
let generics = bound::without_defaults(item.generics);
let generics = bound::with_where_predicates_from_fields(
builder, item, &generics,
|attrs| attrs.ser_bound());
match item.attrs.ser_bound() {
Some(predicates) => {
bound::with_where_predicates(builder, &generics, predicates)
}
None => {
bound::with_bound(builder, item, &generics,
needs_serialize_bound,
&builder.path().ids(&["_serde", "ser", "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(
@@ -80,81 +120,57 @@ fn serialize_body(
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
) -> P<ast::Expr> {
match item.node {
ast::ItemStruct(ref variant_data, _) => {
serialize_item_struct(
cx,
builder,
item,
impl_generics,
ty,
variant_data,
)
}
ast::ItemEnum(ref enum_def, _) => {
match item.body {
Body::Enum(ref variants) => {
serialize_item_enum(
cx,
builder,
item.ident,
impl_generics,
ty,
enum_def,
)
variants,
&item.attrs)
}
_ => cx.bug("expected ItemStruct or ItemEnum in #[derive(Serialize)]")
}
}
fn serialize_item_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
item: &Item,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
variant_data: &ast::VariantData,
) -> P<ast::Expr> {
match *variant_data {
ast::VariantData::Unit(_) => {
serialize_unit_struct(
cx,
&builder,
item.ident,
)
}
ast::VariantData::Tuple(ref fields, _) if fields.len() == 1 => {
serialize_newtype_struct(
cx,
&builder,
item.ident,
)
}
ast::VariantData::Tuple(ref fields, _) => {
if fields.iter().any(|field| !field.node.kind.is_unnamed()) {
cx.bug("tuple struct has named fields")
}
serialize_tuple_struct(
cx,
&builder,
item.ident,
impl_generics,
ty,
fields.len(),
)
}
ast::VariantData::Struct(ref fields, _) => {
if fields.iter().any(|field| field.node.kind.is_unnamed()) {
cx.bug("struct has unnamed fields")
Body::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) {
cx.span_bug(item.span, "struct has unnamed fields")
}
serialize_struct(
cx,
&builder,
item.ident,
builder,
impl_generics,
ty,
fields,
)
&item.attrs)
}
Body::Struct(Style::Tuple, ref fields) => {
if fields.iter().any(|field| field.ident.is_some()) {
cx.span_bug(item.span, "tuple struct has named fields")
}
serialize_tuple_struct(
cx,
builder,
impl_generics,
ty,
fields,
&item.attrs)
}
Body::Struct(Style::Newtype, ref fields) => {
serialize_newtype_struct(
cx,
builder,
impl_generics,
ty,
&fields[0],
&item.attrs)
}
Body::Struct(Style::Unit, _) => {
serialize_unit_struct(
cx,
builder,
&item.attrs)
}
}
}
@@ -162,30 +178,43 @@ fn serialize_item_struct(
fn serialize_unit_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident
item_attrs: &attr::Item,
) -> P<ast::Expr> {
let type_name = builder.expr().str(type_ident);
let type_name = name_expr(builder, item_attrs.name());
quote_expr!(cx, serializer.visit_unit_struct($type_name))
quote_expr!(cx,
_serializer.serialize_unit_struct($type_name)
)
}
fn serialize_newtype_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident
impl_generics: &ast::Generics,
item_ty: P<ast::Ty>,
field: &Field,
item_attrs: &attr::Item,
) -> P<ast::Expr> {
let type_name = builder.expr().str(type_ident);
let type_name = name_expr(builder, item_attrs.name());
quote_expr!(cx, serializer.visit_newtype_struct($type_name, &self.0))
let mut field_expr = quote_expr!(cx, &self.0);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(cx, builder,
&item_ty, impl_generics, &field.ty, path, field_expr);
}
quote_expr!(cx,
_serializer.serialize_newtype_struct($type_name, $field_expr)
)
}
fn serialize_tuple_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
fields: usize,
fields: &[Field],
item_attrs: &attr::Item,
) -> P<ast::Expr> {
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
cx,
@@ -195,16 +224,18 @@ fn serialize_tuple_struct(
.ref_()
.lifetime("'__a")
.build_ty(ty.clone()),
builder.id("serialize_tuple_struct_elt"),
fields,
impl_generics,
false,
);
let type_name = builder.expr().str(type_ident);
let type_name = name_expr(builder, item_attrs.name());
quote_expr!(cx, {
$visitor_struct
$visitor_impl
serializer.visit_tuple_struct($type_name, Visitor {
_serializer.serialize_tuple_struct($type_name, Visitor {
value: self,
state: 0,
_structure_ty: ::std::marker::PhantomData::<&$ty>,
@@ -215,10 +246,10 @@ fn serialize_tuple_struct(
fn serialize_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
fields: &[ast::StructField],
fields: &[Field],
item_attrs: &attr::Item,
) -> P<ast::Expr> {
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
cx,
@@ -228,20 +259,18 @@ fn serialize_struct(
.ref_()
.lifetime("'__a")
.build_ty(ty.clone()),
builder.id("serialize_struct_elt"),
fields,
impl_generics,
fields.iter().map(|field| {
let name = field.node.ident().expect("struct has unnamed field");
quote_expr!(cx, &self.value.$name)
})
false,
);
let type_name = builder.expr().str(type_ident);
let type_name = name_expr(builder, item_attrs.name());
quote_expr!(cx, {
$visitor_struct
$visitor_impl
serializer.visit_struct($type_name, Visitor {
_serializer.serialize_struct($type_name, Visitor {
value: self,
state: 0,
_structure_ty: ::std::marker::PhantomData::<&$ty>,
@@ -255,22 +284,25 @@ fn serialize_item_enum(
type_ident: Ident,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
enum_def: &ast::EnumDef,
variants: &[Variant],
item_attrs: &attr::Item,
) -> P<ast::Expr> {
let arms: Vec<ast::Arm> = enum_def.variants.iter()
.enumerate()
.map(|(variant_index, variant)| {
serialize_variant(
cx,
builder,
type_ident,
impl_generics,
ty.clone(),
variant,
variant_index,
)
})
.collect();
let arms: Vec<_> =
variants.iter()
.enumerate()
.map(|(variant_index, variant)| {
serialize_variant(
cx,
builder,
type_ident,
impl_generics,
ty.clone(),
variant,
variant_index,
item_attrs,
)
})
.collect();
quote_expr!(cx,
match *self {
@@ -285,23 +317,21 @@ fn serialize_variant(
type_ident: Ident,
generics: &ast::Generics,
ty: P<ast::Ty>,
variant: &ast::Variant,
variant: &Variant,
variant_index: usize,
item_attrs: &attr::Item,
) -> ast::Arm {
let type_name = builder.expr().str(type_ident);
let variant_ident = variant.node.name;
let variant_name = builder.expr().str(variant_ident);
let type_name = name_expr(builder, item_attrs.name());
match variant.node.data {
ast::VariantData::Unit(_) => {
let pat = builder.pat().enum_()
.id(type_ident).id(variant_ident).build()
.build();
let variant_ident = variant.ident;
let variant_name = name_expr(builder, variant.attrs.name());
match variant.style {
Style::Unit => {
quote_arm!(cx,
$pat => {
::serde::ser::Serializer::visit_unit_variant(
serializer,
$type_ident::$variant_ident => {
_serde::ser::Serializer::serialize_unit_variant(
_serializer,
$type_name,
$variant_index,
$variant_name,
@@ -309,27 +339,24 @@ fn serialize_variant(
}
)
},
ast::VariantData::Tuple(ref fields, _) if fields.len() == 1 => {
let field = builder.id("__simple_value");
let field = builder.pat().ref_id(field);
let pat = builder.pat().enum_()
.id(type_ident).id(variant_ident).build()
.with_pats(Some(field).into_iter())
.build();
Style::Newtype => {
let expr = serialize_newtype_variant(
cx,
builder,
type_name,
variant_index,
variant_name,
ty,
generics,
&variant.fields[0],
);
quote_arm!(cx,
$pat => {
::serde::ser::Serializer::visit_newtype_variant(
serializer,
$type_name,
$variant_index,
$variant_name,
__simple_value,
)
}
$type_ident::$variant_ident(ref __simple_value) => { $expr }
)
},
ast::VariantData::Tuple(ref fields, _) => {
let field_names: Vec<ast::Ident> = (0 .. fields.len())
Style::Tuple => {
let field_names: Vec<ast::Ident> = (0 .. variant.fields.len())
.map(|i| builder.id(format!("__field{}", i)))
.collect();
@@ -349,14 +376,16 @@ fn serialize_variant(
variant_name,
generics,
ty,
fields,
&variant.fields,
field_names,
);
quote_arm!(cx, $pat => { $expr })
quote_arm!(cx,
$pat => { $expr }
)
}
ast::VariantData::Struct(ref fields, _) => {
let field_names: Vec<_> = (0 .. fields.len())
Style::Struct => {
let field_names: Vec<_> = (0 .. variant.fields.len())
.map(|i| builder.id(format!("__field{}", i)))
.collect();
@@ -364,12 +393,12 @@ fn serialize_variant(
.id(type_ident).id(variant_ident).build()
.with_pats(
field_names.iter()
.zip(fields.iter())
.zip(variant.fields.iter())
.map(|(id, field)| {
let name = match field.node.kind {
ast::NamedField(name, _) => name,
ast::UnnamedField(_) => {
cx.bug("struct variant has unnamed fields")
let name = match field.ident {
Some(name) => name,
None => {
cx.span_bug(field.span, "struct variant has unnamed fields")
}
};
@@ -381,20 +410,49 @@ fn serialize_variant(
let expr = serialize_struct_variant(
cx,
builder,
type_name,
variant_index,
variant_name,
generics,
ty,
fields,
&variant.fields,
field_names,
item_attrs,
);
quote_arm!(cx, $pat => { $expr })
quote_arm!(cx,
$pat => { $expr }
)
}
}
}
fn serialize_newtype_variant(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_name: P<ast::Expr>,
variant_index: usize,
variant_name: P<ast::Expr>,
item_ty: P<ast::Ty>,
generics: &ast::Generics,
field: &Field,
) -> P<ast::Expr> {
let mut field_expr = quote_expr!(cx, __simple_value);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(cx, builder,
&item_ty, generics, &field.ty, path, field_expr);
}
quote_expr!(cx,
_serde::ser::Serializer::serialize_newtype_variant(
_serializer,
$type_name,
$variant_index,
$variant_name,
$field_expr,
)
)
}
fn serialize_tuple_variant(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
@@ -403,7 +461,7 @@ fn serialize_tuple_variant(
variant_name: P<ast::Expr>,
generics: &ast::Generics,
structure_ty: P<ast::Ty>,
fields: &[ast::StructField],
fields: &[Field],
field_names: Vec<Ident>,
) -> P<ast::Expr> {
let variant_ty = builder.ty().tuple()
@@ -412,7 +470,7 @@ fn serialize_tuple_variant(
builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(field.node.ty.clone())
.build_ty(field.ty.clone())
})
)
.build();
@@ -422,8 +480,10 @@ fn serialize_tuple_variant(
builder,
structure_ty.clone(),
variant_ty,
fields.len(),
builder.id("serialize_tuple_variant_elt"),
fields,
generics,
true,
);
let value_expr = builder.expr().tuple()
@@ -437,7 +497,7 @@ fn serialize_tuple_variant(
quote_expr!(cx, {
$visitor_struct
$visitor_impl
serializer.visit_tuple_variant($type_name, $variant_index, $variant_name, Visitor {
_serializer.serialize_tuple_variant($type_name, $variant_index, $variant_name, Visitor {
value: $value_expr,
state: 0,
_structure_ty: ::std::marker::PhantomData::<&$structure_ty>,
@@ -448,55 +508,88 @@ fn serialize_tuple_variant(
fn serialize_struct_variant(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_name: P<ast::Expr>,
variant_index: usize,
variant_name: P<ast::Expr>,
generics: &ast::Generics,
structure_ty: P<ast::Ty>,
fields: &[ast::StructField],
ty: P<ast::Ty>,
fields: &[Field],
field_names: Vec<Ident>,
item_attrs: &attr::Item,
) -> P<ast::Expr> {
let value_ty = builder.ty().tuple()
.with_tys(
fields.iter().map(|field| {
builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(field.node.ty.clone())
})
)
let variant_generics = builder.generics()
.with(generics.clone())
.add_lifetime_bound("'__serde_variant")
.lifetime_name("'__serde_variant")
.build();
let value_expr = builder.expr().tuple()
.with_exprs(
field_names.iter().map(|field| {
builder.expr().id(field)
let variant_struct = builder.item().struct_("__VariantStruct")
.with_generics(variant_generics.clone())
.with_fields(
fields.iter().map(|field| {
builder.struct_field(field.ident.expect("struct has unnamed fields"))
.ty()
.ref_()
.lifetime("'__serde_variant")
.build_ty(field.ty.clone())
})
)
.field("__serde_container_ty")
.ty().phantom_data().build(ty.clone())
.build();
let variant_expr = builder.expr().struct_id("__VariantStruct")
.with_id_exprs(
fields.iter()
.zip(field_names.iter())
.map(|(field, field_name)| {
(
field.ident.expect("struct has unnamed fields"),
builder.expr().id(field_name),
)
})
)
.field("__serde_container_ty").path()
.global()
.id("std").id("marker")
.segment("PhantomData")
.with_ty(ty.clone())
.build()
.build()
.build();
let variant_ty = builder.ty().path()
.segment("__VariantStruct")
.with_generics(variant_generics.clone())
.build()
.build();
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
cx,
builder,
structure_ty.clone(),
value_ty,
variant_ty.clone(),
variant_ty.clone(),
builder.id("serialize_struct_variant_elt"),
fields,
generics,
(0 .. field_names.len()).map(|i| {
builder.expr()
.tup_field(i)
.field("value").self_()
})
&variant_generics,
true,
);
let item_name = name_expr(builder, item_attrs.name());
quote_expr!(cx, {
$variant_struct
$visitor_struct
$visitor_impl
serializer.visit_struct_variant($type_name, $variant_index, $variant_name, Visitor {
value: $value_expr,
state: 0,
_structure_ty: ::std::marker::PhantomData::<&$structure_ty>,
})
_serializer.serialize_struct_variant(
$item_name,
$variant_index,
$variant_name,
Visitor {
value: $variant_expr,
state: 0,
_structure_ty: ::std::marker::PhantomData,
},
)
})
}
@@ -505,20 +598,32 @@ fn serialize_tuple_struct_visitor(
builder: &aster::AstBuilder,
structure_ty: P<ast::Ty>,
variant_ty: P<ast::Ty>,
fields: usize,
generics: &ast::Generics
serializer_method: ast::Ident,
fields: &[Field],
generics: &ast::Generics,
is_enum: bool,
) -> (P<ast::Item>, P<ast::Item>) {
let arms: Vec<ast::Arm> = (0 .. fields)
.map(|i| {
let expr = builder.expr()
.tup_field(i)
.field("value").self_();
let arms: Vec<_> = fields.iter()
.enumerate()
.map(|(i, field)| {
let mut field_expr = builder.expr().tup_field(i).field("value").self_();
if !is_enum {
field_expr = quote_expr!(cx, &$field_expr);
}
let continue_if_skip = field.attrs.skip_serializing_if()
.map(|path| quote_stmt!(cx, if $path($field_expr) { continue }));
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(cx, builder,
&structure_ty, generics, &field.ty, path, field_expr);
}
quote_arm!(cx,
$i => {
self.state += 1;
let v = try!(serializer.visit_tuple_struct_elt(&$expr));
Ok(Some(v))
$continue_if_skip
Ok(Some(try!(_serializer.$serializer_method($field_expr))))
}
)
})
@@ -535,6 +640,8 @@ fn serialize_tuple_struct_visitor(
.strip_bounds()
.build();
let nfields = fields.len();
(
quote_item!(cx,
struct Visitor $visitor_impl_generics $where_clause {
@@ -545,12 +652,12 @@ fn serialize_tuple_struct_visitor(
).unwrap(),
quote_item!(cx,
impl $visitor_impl_generics ::serde::ser::SeqVisitor
impl $visitor_impl_generics _serde::ser::SeqVisitor
for Visitor $visitor_generics
$where_clause {
#[inline]
fn visit<S>(&mut self, serializer: &mut S) -> ::std::result::Result<Option<()>, S::Error>
where S: ::serde::ser::Serializer
fn visit<__S>(&mut self, _serializer: &mut __S) -> ::std::result::Result<Option<()>, __S::Error>
where __S: _serde::ser::Serializer
{
match self.state {
$arms
@@ -560,58 +667,52 @@ fn serialize_tuple_struct_visitor(
#[inline]
fn len(&self) -> Option<usize> {
Some($fields)
Some($nfields)
}
}
).unwrap(),
)
}
fn serialize_struct_visitor<I>(
fn serialize_struct_visitor(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
structure_ty: P<ast::Ty>,
variant_ty: P<ast::Ty>,
fields: &[ast::StructField],
serializer_method: ast::Ident,
fields: &[Field],
generics: &ast::Generics,
value_exprs: I,
) -> (P<ast::Item>, P<ast::Item>)
where I: Iterator<Item=P<ast::Expr>>,
{
let value_exprs = value_exprs.collect::<Vec<_>>();
let field_attrs = struct_field_attrs(cx, builder, fields);
let arms: Vec<ast::Arm> = field_attrs.iter()
.zip(value_exprs.iter())
.filter(|&(ref field, _)| !field.skip_serializing_field())
is_enum: bool,
) -> (P<ast::Item>, P<ast::Item>) {
let arms: Vec<ast::Arm> = fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.enumerate()
.map(|(i, (ref field, value_expr))| {
let key_expr = field.serializer_key_expr(cx);
.map(|(i, field)| {
let ident = field.ident.expect("struct has unnamed field");
let mut field_expr = quote_expr!(cx, self.value.$ident);
if !is_enum {
field_expr = quote_expr!(cx, &$field_expr);
}
let stmt = if field.skip_serializing_field_if_empty() {
quote_stmt!(cx, if ($value_expr).is_empty() { continue; })
} else if field.skip_serializing_field_if_none() {
quote_stmt!(cx, if ($value_expr).is_none() { continue; })
} else {
quote_stmt!(cx, {})
};
let key_expr = name_expr(builder, field.attrs.name());
let continue_if_skip = field.attrs.skip_serializing_if()
.map(|path| quote_stmt!(cx, if $path($field_expr) { continue }));
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(cx, builder,
&structure_ty, generics, &field.ty, path, field_expr)
}
let expr = quote_expr!(cx,
_serializer.$serializer_method($key_expr, $field_expr)
);
quote_arm!(cx,
$i => {
self.state += 1;
$stmt
return Ok(
Some(
try!(
serializer.visit_struct_elt(
$key_expr,
$value_expr,
)
)
)
);
$continue_if_skip
return Ok(Some(try!($expr)));
}
)
})
@@ -628,17 +729,18 @@ fn serialize_struct_visitor<I>(
.strip_bounds()
.build();
let len = field_attrs.iter()
.zip(value_exprs.iter())
.map(|(field, value_expr)| {
if field.skip_serializing_field() {
quote_expr!(cx, 0)
} else if field.skip_serializing_field_if_empty() {
quote_expr!(cx, if ($value_expr).is_empty() { 0 } else { 1 })
} else if field.skip_serializing_field_if_none() {
quote_expr!(cx, if ($value_expr).is_none() { 0 } else { 1 })
} else {
quote_expr!(cx, 1)
let len = fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.map(|field| {
let ident = field.ident.expect("struct has unnamed fields");
let mut field_expr = quote_expr!(cx, self.value.$ident);
if !is_enum {
field_expr = quote_expr!(cx, &$field_expr);
}
match field.attrs.skip_serializing_if() {
Some(path) => quote_expr!(cx, if $path($field_expr) { 0 } else { 1 }),
None => quote_expr!(cx, 1),
}
})
.fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr));
@@ -654,12 +756,12 @@ fn serialize_struct_visitor<I>(
quote_item!(cx,
impl $visitor_impl_generics
::serde::ser::MapVisitor
_serde::ser::MapVisitor
for Visitor $visitor_generics
$where_clause {
#[inline]
fn visit<S>(&mut self, serializer: &mut S) -> ::std::result::Result<Option<()>, S::Error>
where S: ::serde::ser::Serializer,
fn visit<__S>(&mut self, _serializer: &mut __S) -> ::std::result::Result<Option<()>, __S::Error>
where __S: _serde::ser::Serializer,
{
loop {
match self.state {
@@ -677,3 +779,53 @@ fn serialize_struct_visitor<I>(
).unwrap(),
)
}
fn wrap_serialize_with(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
item_ty: &P<ast::Ty>,
generics: &ast::Generics,
field_ty: &P<ast::Ty>,
path: &ast::Path,
value: P<ast::Expr>,
) -> P<ast::Expr> {
let where_clause = &generics.where_clause;
let wrapper_generics = builder.from_generics(generics.clone())
.add_lifetime_bound("'__a")
.lifetime_name("'__a")
.build();
let wrapper_ty = builder.path()
.segment("__SerializeWith")
.with_generics(wrapper_generics.clone())
.build()
.build();
quote_expr!(cx, {
struct __SerializeWith $wrapper_generics $where_clause {
value: &'__a $field_ty,
phantom: ::std::marker::PhantomData<$item_ty>,
}
impl $wrapper_generics _serde::ser::Serialize for $wrapper_ty $where_clause {
fn serialize<__S>(&self, __s: &mut __S) -> Result<(), __S::Error>
where __S: _serde::ser::Serializer
{
$path(self.value, __s)
}
}
__SerializeWith {
value: $value,
phantom: ::std::marker::PhantomData::<$item_ty>,
}
})
}
fn name_expr(
builder: &aster::AstBuilder,
name: &attr::Name,
) -> P<ast::Expr> {
builder.expr().str(name.serialize_name())
}
+43
View File
@@ -0,0 +1,43 @@
use syntax::ast;
use syntax::codemap::{self, ExpnId, Span};
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::fold::{self, Folder};
use syntax::parse::token::intern;
use syntax::ptr::P;
pub fn record_expansion(
cx: &ExtCtxt,
item: P<ast::Item>,
derive: &str,
) -> Annotatable {
let info = codemap::ExpnInfo {
call_site: codemap::DUMMY_SP,
callee: codemap::NameAndSpan {
format: codemap::MacroAttribute(intern(&format!("derive({})", derive))),
span: None,
allow_internal_unstable: false,
},
};
let expn_id = cx.codemap().record_expansion(info);
let mut respanner = Respanner { expn_id: expn_id };
let item = item.map(|item| respanner.fold_item_simple(item));
Annotatable::Item(item)
}
struct Respanner {
expn_id: ExpnId,
}
impl Folder for Respanner {
fn new_span(&mut self, span: Span) -> Span {
Span {
expn_id: self.expn_id,
.. span
}
}
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
fold::noop_fold_mac(mac, self)
}
}
+20
View File
@@ -0,0 +1,20 @@
[package]
name = "serde_codegen_internals"
version = "0.4.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "AST representation used by Serde codegen. Unstable."
repository = "https://github.com/serde-rs/serde"
documentation = "https://github.com/serde-rs/serde"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[features]
default = ["with-syntex"]
nightly-testing = ["clippy"]
with-syntex = ["syntex_syntax", "syntex_errors"]
[dependencies]
clippy = { version = "^0.*", optional = true }
syntex_syntax = { version = "^0.39.0", optional = true }
syntex_errors = { version = "^0.39.0", optional = true }
+142
View File
@@ -0,0 +1,142 @@
use syntax::ast;
use syntax::codemap;
use syntax::ext::base::ExtCtxt;
use syntax::ptr::P;
use attr;
use Error;
pub struct Item<'a> {
pub ident: ast::Ident,
pub span: codemap::Span,
pub attrs: attr::Item,
pub body: Body<'a>,
pub generics: &'a ast::Generics,
}
pub enum Body<'a> {
Enum(Vec<Variant<'a>>),
Struct(Style, Vec<Field<'a>>),
}
pub struct Variant<'a> {
pub ident: ast::Ident,
pub span: codemap::Span,
pub attrs: attr::Variant,
pub style: Style,
pub fields: Vec<Field<'a>>,
}
pub struct Field<'a> {
pub ident: Option<ast::Ident>,
pub span: codemap::Span,
pub attrs: attr::Field,
pub ty: &'a P<ast::Ty>,
}
pub enum Style {
Struct,
Tuple,
Newtype,
Unit,
}
impl<'a> Item<'a> {
pub fn from_ast(
cx: &ExtCtxt,
item: &'a ast::Item,
) -> Result<Item<'a>, Error> {
let attrs = attr::Item::from_ast(cx, item);
let (body, generics) = match item.node {
ast::ItemKind::Enum(ref enum_def, ref generics) => {
let variants = enum_from_ast(cx, enum_def);
(Body::Enum(variants), generics)
}
ast::ItemKind::Struct(ref variant_data, ref generics) => {
let (style, fields) = struct_from_ast(cx, variant_data);
(Body::Struct(style, fields), generics)
}
_ => {
return Err(Error::UnexpectedItemKind);
}
};
Ok(Item {
ident: item.ident,
span: item.span,
attrs: attrs,
body: body,
generics: generics,
})
}
}
impl<'a> Body<'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())
}
}
}
}
fn enum_from_ast<'a>(
cx: &ExtCtxt,
enum_def: &'a ast::EnumDef,
) -> Vec<Variant<'a>> {
enum_def.variants.iter()
.map(|variant| {
let (style, fields) = struct_from_ast(cx, &variant.node.data);
Variant {
ident: variant.node.name,
span: variant.span,
attrs: attr::Variant::from_ast(cx, variant),
style: style,
fields: fields,
}
})
.collect()
}
fn struct_from_ast<'a>(
cx: &ExtCtxt,
variant_data: &'a ast::VariantData,
) -> (Style, Vec<Field<'a>>) {
match *variant_data {
ast::VariantData::Struct(ref fields, _) => {
(Style::Struct, fields_from_ast(cx, fields))
}
ast::VariantData::Tuple(ref fields, _) if fields.len() == 1 => {
(Style::Newtype, fields_from_ast(cx, fields))
}
ast::VariantData::Tuple(ref fields, _) => {
(Style::Tuple, fields_from_ast(cx, fields))
}
ast::VariantData::Unit(_) => {
(Style::Unit, Vec::new())
}
}
}
fn fields_from_ast<'a>(
cx: &ExtCtxt,
fields: &'a [ast::StructField],
) -> Vec<Field<'a>> {
fields.iter()
.enumerate()
.map(|(i, field)| {
Field {
ident: field.ident,
span: field.span,
attrs: attr::Field::from_ast(cx, i, field),
ty: &field.ty,
}
})
.collect()
}
+638
View File
@@ -0,0 +1,638 @@
use std::rc::Rc;
use syntax::ast;
use syntax::attr::{self, HasAttrs};
use syntax::codemap::{Span, Spanned, respan};
use syntax::ext::base::ExtCtxt;
use syntax::fold::Folder;
use syntax::parse::parser::{Parser, PathStyle};
use syntax::parse::token::{self, InternedString};
use syntax::parse;
use syntax::print::pprust::{lit_to_string, meta_item_to_string};
use syntax::ptr::P;
use syntax::tokenstream::{self, TokenTree};
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
// are `attr::Item::from_ast`, `attr::Variant::from_ast`, and
// `attr::Field::from_ast`. Each returns an instance of the corresponding
// struct. Note that none of them return a Result. Unrecognized, malformed, or
// duplicated attributes result in a span_err but otherwise are ignored. The
// user will see errors simultaneously for all bad attributes in the crate
// rather than just the first.
struct Attr<'a, 'b: 'a, T> {
cx: &'a ExtCtxt<'b>,
name: &'static str,
value: Option<Spanned<T>>,
}
impl<'a, 'b, T> Attr<'a, 'b, T> {
fn none(cx: &'a ExtCtxt<'b>, name: &'static str) -> Self {
Attr {
cx: cx,
name: name,
value: None,
}
}
fn set(&mut self, span: Span, t: T) {
if let Some(Spanned { span: prev_span, .. }) = self.value {
let mut err = self.cx.struct_span_err(
span,
&format!("duplicate serde attribute `{}`", self.name));
err.span_help(prev_span, "previously set here");
err.emit();
} else {
self.value = Some(respan(span, t));
}
}
fn set_opt(&mut self, v: Option<Spanned<T>>) {
if let Some(v) = v {
self.set(v.span, v.node);
}
}
fn set_if_none(&mut self, span: Span, t: T) {
if self.value.is_none() {
self.value = Some(respan(span, t));
}
}
fn get(self) -> Option<T> {
self.value.map(|spanned| spanned.node)
}
fn get_spanned(self) -> Option<Spanned<T>> {
self.value
}
}
struct BoolAttr<'a, 'b: 'a>(Attr<'a, 'b, ()>);
impl<'a, 'b> BoolAttr<'a, 'b> {
fn none(cx: &'a ExtCtxt<'b>, name: &'static str) -> Self {
BoolAttr(Attr::none(cx, name))
}
fn set_true(&mut self, span: Span) {
self.0.set(span, ());
}
fn get(&self) -> bool {
self.0.value.is_some()
}
}
#[derive(Debug)]
pub struct Name {
serialize: InternedString,
deserialize: InternedString,
}
impl Name {
/// Return the container name for the container when serializing.
pub fn serialize_name(&self) -> InternedString {
self.serialize.clone()
}
/// Return the container name for the container when deserializing.
pub fn deserialize_name(&self) -> InternedString {
self.deserialize.clone()
}
}
/// Represents container (e.g. struct) attribute information
#[derive(Debug)]
pub struct Item {
name: Name,
deny_unknown_fields: bool,
ser_bound: Option<Vec<ast::WherePredicate>>,
de_bound: Option<Vec<ast::WherePredicate>>,
}
impl Item {
/// Extract out the `#[serde(...)]` attributes from an item.
pub fn from_ast(cx: &ExtCtxt, item: &ast::Item) -> Self {
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 ser_bound = Attr::none(cx, "bound");
let mut de_bound = Attr::none(cx, "bound");
let ident = item.ident.name.as_str();
for meta_items in item.attrs().iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
let span = meta_item.span;
match meta_item.node {
// Parse `#[serde(rename="foo")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"rename" => {
if let Ok(s) = get_str_from_lit(cx, name, lit) {
ser_name.set(span, s.clone());
de_name.set(span, s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"rename" => {
if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser);
de_name.set_opt(de);
}
}
// Parse `#[serde(deny_unknown_fields)]`
ast::MetaItemKind::Word(ref name) if name == &"deny_unknown_fields" => {
deny_unknown_fields.set_true(span);
}
// Parse `#[serde(bound="D: Serialize")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"bound" => {
if let Ok(where_predicates) = parse_lit_into_where(cx, name, lit) {
ser_bound.set(span, where_predicates.clone());
de_bound.set(span, where_predicates);
}
}
// Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"bound" => {
if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
ser_bound.set_opt(ser);
de_bound.set_opt(de);
}
}
_ => {
cx.span_err(
meta_item.span,
&format!("unknown serde container attribute `{}`",
meta_item_to_string(meta_item)));
}
}
}
}
Item {
name: Name {
serialize: ser_name.get().unwrap_or(ident.clone()),
deserialize: de_name.get().unwrap_or(ident),
},
deny_unknown_fields: deny_unknown_fields.get(),
ser_bound: ser_bound.get(),
de_bound: de_bound.get(),
}
}
pub fn name(&self) -> &Name {
&self.name
}
pub fn deny_unknown_fields(&self) -> bool {
self.deny_unknown_fields
}
pub fn ser_bound(&self) -> Option<&[ast::WherePredicate]> {
self.ser_bound.as_ref().map(|vec| &vec[..])
}
pub fn de_bound(&self) -> Option<&[ast::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
}
/// Represents variant attribute information
#[derive(Debug)]
pub struct Variant {
name: Name,
}
impl Variant {
pub fn from_ast(cx: &ExtCtxt, variant: &ast::Variant) -> Self {
let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename");
let ident = variant.node.name.name.as_str();
for meta_items in variant.node.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
let span = meta_item.span;
match meta_item.node {
// Parse `#[serde(rename="foo")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"rename" => {
if let Ok(s) = get_str_from_lit(cx, name, lit) {
ser_name.set(span, s.clone());
de_name.set(span, s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"rename" => {
if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser);
de_name.set_opt(de);
}
}
_ => {
cx.span_err(
meta_item.span,
&format!("unknown serde variant attribute `{}`",
meta_item_to_string(meta_item)));
}
}
}
}
Variant {
name: Name {
serialize: ser_name.get().unwrap_or(ident.clone()),
deserialize: de_name.get().unwrap_or(ident),
},
}
}
pub fn name(&self) -> &Name {
&self.name
}
}
/// Represents field attribute information
#[derive(Debug)]
pub struct Field {
name: Name,
skip_serializing: bool,
skip_deserializing: bool,
skip_serializing_if: Option<ast::Path>,
default: FieldDefault,
serialize_with: Option<ast::Path>,
deserialize_with: Option<ast::Path>,
ser_bound: Option<Vec<ast::WherePredicate>>,
de_bound: Option<Vec<ast::WherePredicate>>,
}
/// Represents the default to use for a field when deserializing.
#[derive(Debug, PartialEq)]
pub enum FieldDefault {
/// Field must always be specified because it does not have a default.
None,
/// The default is given by `std::default::Default::default()`.
Default,
/// The default is given by this function.
Path(ast::Path),
}
impl Field {
/// Extract out the `#[serde(...)]` attributes from a struct field.
pub fn from_ast(cx: &ExtCtxt,
index: usize,
field: &ast::StructField) -> 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");
let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing");
let mut skip_serializing_if = Attr::none(cx, "skip_serializing_if");
let mut default = Attr::none(cx, "default");
let mut serialize_with = Attr::none(cx, "serialize_with");
let mut deserialize_with = Attr::none(cx, "deserialize_with");
let mut ser_bound = Attr::none(cx, "bound");
let mut de_bound = Attr::none(cx, "bound");
let ident = match field.ident {
Some(ident) => ident.name.as_str(),
None => token::intern_and_get_ident(&index.to_string()),
};
for meta_items in field.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
let span = meta_item.span;
match meta_item.node {
// Parse `#[serde(rename="foo")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"rename" => {
if let Ok(s) = get_str_from_lit(cx, name, lit) {
ser_name.set(span, s.clone());
de_name.set(span, s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"rename" => {
if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser);
de_name.set_opt(de);
}
}
// Parse `#[serde(default)]`
ast::MetaItemKind::Word(ref name) if name == &"default" => {
default.set(span, FieldDefault::Default);
}
// Parse `#[serde(default="...")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"default" => {
if let Ok(path) = parse_lit_into_path(cx, name, lit) {
default.set(span, FieldDefault::Path(path));
}
}
// Parse `#[serde(skip_serializing)]`
ast::MetaItemKind::Word(ref name) if name == &"skip_serializing" => {
skip_serializing.set_true(span);
}
// Parse `#[serde(skip_deserializing)]`
ast::MetaItemKind::Word(ref name) if name == &"skip_deserializing" => {
skip_deserializing.set_true(span);
}
// Parse `#[serde(skip_serializing_if="...")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"skip_serializing_if" => {
if let Ok(path) = parse_lit_into_path(cx, name, lit) {
skip_serializing_if.set(span, path);
}
}
// Parse `#[serde(serialize_with="...")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"serialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, name, lit) {
serialize_with.set(span, path);
}
}
// Parse `#[serde(deserialize_with="...")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"deserialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, name, lit) {
deserialize_with.set(span, path);
}
}
// Parse `#[serde(bound="D: Serialize")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"bound" => {
if let Ok(where_predicates) = parse_lit_into_where(cx, name, lit) {
ser_bound.set(span, where_predicates.clone());
de_bound.set(span, where_predicates);
}
}
// Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"bound" => {
if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
ser_bound.set_opt(ser);
de_bound.set_opt(de);
}
}
_ => {
cx.span_err(
meta_item.span,
&format!("unknown serde field attribute `{}`",
meta_item_to_string(meta_item)));
}
}
}
}
// Is skip_deserializing, initialize the field to Default::default()
// unless a different default is specified by `#[serde(default="...")]`
if let Some(Spanned { span, .. }) = skip_deserializing.0.value {
default.set_if_none(span, FieldDefault::Default);
}
Field {
name: Name {
serialize: ser_name.get().unwrap_or(ident.clone()),
deserialize: de_name.get().unwrap_or(ident),
},
skip_serializing: skip_serializing.get(),
skip_deserializing: skip_deserializing.get(),
skip_serializing_if: skip_serializing_if.get(),
default: default.get().unwrap_or(FieldDefault::None),
serialize_with: serialize_with.get(),
deserialize_with: deserialize_with.get(),
ser_bound: ser_bound.get(),
de_bound: de_bound.get(),
}
}
pub fn name(&self) -> &Name {
&self.name
}
pub fn skip_serializing(&self) -> bool {
self.skip_serializing
}
pub fn skip_deserializing(&self) -> bool {
self.skip_deserializing
}
pub fn skip_serializing_if(&self) -> Option<&ast::Path> {
self.skip_serializing_if.as_ref()
}
pub fn default(&self) -> &FieldDefault {
&self.default
}
pub fn serialize_with(&self) -> Option<&ast::Path> {
self.serialize_with.as_ref()
}
pub fn deserialize_with(&self) -> Option<&ast::Path> {
self.deserialize_with.as_ref()
}
pub fn ser_bound(&self) -> Option<&[ast::WherePredicate]> {
self.ser_bound.as_ref().map(|vec| &vec[..])
}
pub fn de_bound(&self) -> Option<&[ast::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
}
fn get_ser_and_de<T, F>(
cx: &ExtCtxt,
attribute: &'static str,
items: &[P<ast::MetaItem>],
f: F
) -> Result<(Option<Spanned<T>>, Option<Spanned<T>>), ()>
where F: Fn(&ExtCtxt, &str, &ast::Lit) -> Result<T, ()>,
{
let mut ser_item = Attr::none(cx, attribute);
let mut de_item = Attr::none(cx, attribute);
for item in items {
match item.node {
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"serialize" => {
if let Ok(v) = f(cx, name, lit) {
ser_item.set(item.span, v);
}
}
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"deserialize" => {
if let Ok(v) = f(cx, name, lit) {
de_item.set(item.span, v);
}
}
_ => {
cx.span_err(
item.span,
&format!("unknown {} attribute `{}`",
attribute,
meta_item_to_string(item)));
return Err(());
}
}
}
Ok((ser_item.get_spanned(), de_item.get_spanned()))
}
fn get_renames(
cx: &ExtCtxt,
items: &[P<ast::MetaItem>],
) -> Result<(Option<Spanned<InternedString>>, Option<Spanned<InternedString>>), ()> {
get_ser_and_de(cx, "rename", items, get_str_from_lit)
}
fn get_where_predicates(
cx: &ExtCtxt,
items: &[P<ast::MetaItem>],
) -> Result<(Option<Spanned<Vec<ast::WherePredicate>>>, Option<Spanned<Vec<ast::WherePredicate>>>), ()> {
get_ser_and_de(cx, "bound", items, parse_lit_into_where)
}
pub fn get_serde_meta_items(attr: &ast::Attribute) -> Option<&[P<ast::MetaItem>]> {
match attr.node.value.node {
ast::MetaItemKind::List(ref name, ref items) if name == &"serde" => {
attr::mark_used(&attr);
Some(items)
}
_ => None
}
}
/// This syntax folder rewrites tokens to say their spans are coming from a macro context.
struct Respanner<'a, 'b: 'a> {
cx: &'a ExtCtxt<'b>,
}
impl<'a, 'b> Folder for Respanner<'a, 'b> {
fn fold_tt(&mut self, tt: &TokenTree) -> TokenTree {
match *tt {
TokenTree::Token(span, ref tok) => {
TokenTree::Token(
self.new_span(span),
self.fold_token(tok.clone())
)
}
TokenTree::Delimited(span, ref delimed) => {
TokenTree::Delimited(
self.new_span(span),
Rc::new(tokenstream::Delimited {
delim: delimed.delim,
open_span: delimed.open_span,
tts: self.fold_tts(&delimed.tts),
close_span: delimed.close_span,
})
)
}
TokenTree::Sequence(span, ref seq) => {
TokenTree::Sequence(
self.new_span(span),
Rc::new(tokenstream::SequenceRepetition {
tts: self.fold_tts(&seq.tts),
separator: seq.separator.clone().map(|tok| self.fold_token(tok)),
..**seq
})
)
}
}
}
fn new_span(&mut self, span: Span) -> Span {
Span {
lo: span.lo,
hi: span.hi,
expn_id: self.cx.backtrace(),
}
}
}
fn get_str_from_lit(cx: &ExtCtxt, name: &str, lit: &ast::Lit) -> Result<InternedString, ()> {
match lit.node {
ast::LitKind::Str(ref s, _) => Ok(s.clone()),
_ => {
cx.span_err(
lit.span,
&format!("serde annotation `{}` must be a string, not `{}`",
name,
lit_to_string(lit)));
return Err(());
}
}
}
// If we just parse a string literal from an attibute, any syntax errors in the
// source will only have spans that point inside the string and not back to the
// attribute. So to have better error reporting, we'll first parse the string
// into a token tree. Then we'll update those spans to say they're coming from a
// macro context that originally came from the attribnute, and then finally
// parse them into an expression or where-clause.
fn parse_string_via_tts<T, F>(cx: &ExtCtxt, name: &str, string: String, action: F) -> Result<T, ()>
where F: for<'a> Fn(&'a mut Parser) -> parse::PResult<'a, T>,
{
let tts = panictry!(parse::parse_tts_from_source_str(
format!("<serde {} expansion>", name),
string,
cx.cfg(),
cx.parse_sess()));
// Respan the spans to say they are all coming from this macro.
let tts = Respanner { cx: cx }.fold_tts(&tts);
let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts);
let path = match action(&mut parser) {
Ok(path) => path,
Err(mut e) => {
e.emit();
return Err(());
}
};
// Make sure to error out if there are trailing characters in the stream.
match parser.expect(&token::Eof) {
Ok(()) => { }
Err(mut e) => {
e.emit();
return Err(());
}
}
Ok(path)
}
fn parse_lit_into_path(cx: &ExtCtxt, name: &str, lit: &ast::Lit) -> Result<ast::Path, ()> {
let string = try!(get_str_from_lit(cx, name, lit)).to_string();
parse_string_via_tts(cx, name, string, |parser| {
parser.parse_path(PathStyle::Type)
})
}
fn parse_lit_into_where(cx: &ExtCtxt, name: &str, lit: &ast::Lit) -> Result<Vec<ast::WherePredicate>, ()> {
let string = try!(get_str_from_lit(cx, name, lit));
if string.is_empty() {
return Ok(Vec::new());
}
let where_string = format!("where {}", string);
parse_string_via_tts(cx, name, where_string, |parser| {
let where_clause = try!(parser.parse_where_clause());
Ok(where_clause.predicates)
})
}
+19
View File
@@ -0,0 +1,19 @@
use std::error;
use std::fmt;
#[derive(Debug)]
pub enum Error {
UnexpectedItemKind,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "expected a struct or enum")
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"expected a struct or enum"
}
}
+21
View File
@@ -0,0 +1,21 @@
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private, plugin))]
#[cfg(feature = "with-syntex")]
#[macro_use]
extern crate syntex_syntax as syntax;
#[cfg(feature = "with-syntex")]
extern crate syntex_errors as errors;
#[cfg(not(feature = "with-syntex"))]
#[macro_use]
extern crate syntax;
#[cfg(not(feature = "with-syntex"))]
extern crate rustc_errors as errors;
pub mod ast;
pub mod attr;
mod error;
pub use error::Error;
+20 -4
View File
@@ -1,21 +1,37 @@
[package]
name = "serde_macros"
version = "0.6.1"
version = "0.7.15"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
repository = "https://github.com/serde-rs/serde"
documentation = "https://github.com/serde-rs/serde"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[lib]
name = "serde_macros"
plugin = true
[features]
nightly-testing = ["clippy", "serde/nightly-testing", "serde_codegen/nightly-testing"]
[dependencies]
serde_codegen = { version = "*", path = "../serde_codegen", default-features = false, features = ["nightly"] }
clippy = { version = "^0.*", optional = true }
serde_codegen = { version = "^0.7.15", default-features = false, features = ["nightly"] }
[dev-dependencies]
num = "^0.1.27"
clippy = "^0.0.79"
compiletest_rs = "^0.2.0"
fnv = "1.0"
rustc-serialize = "^0.3.16"
serde = { version = "*", path = "../serde", features = ["nightly"] }
serde = "0.7.15"
serde_test = "0.7.15"
[[test]]
name = "test"
path = "tests/test.rs"
[[bench]]
name = "bench"
path = "benches/bench.rs"
+2 -2
View File
@@ -1,9 +1,9 @@
#![feature(custom_attribute, custom_derive, plugin, test)]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![plugin(serde_macros)]
extern crate num;
extern crate rustc_serialize;
extern crate serde;
extern crate test;
include!("../../serde_tests/benches/bench.rs.in");
include!("../../testing/benches/bench.rs.in");
+4 -2
View File
@@ -1,10 +1,12 @@
#![feature(plugin_registrar, rustc_private)]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
extern crate serde_codegen;
extern crate rustc;
extern crate rustc_plugin;
#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut rustc::plugin::Registry) {
pub fn plugin_registrar(reg: &mut rustc_plugin::Registry) {
serde_codegen::register(reg);
}
@@ -0,0 +1,32 @@
#![feature(custom_attribute, custom_derive, plugin)]
#![plugin(serde_macros)]
#[derive(Serialize)]
struct S {
#[serde(rename(serialize="x"))]
#[serde(rename(serialize="y"))] //~ ERROR: duplicate serde attribute `rename`
a: (),
#[serde(rename(serialize="x"))]
#[serde(rename="y")] //~ ERROR: duplicate serde attribute `rename`
b: (),
#[serde(rename(serialize="x"))]
#[serde(rename(deserialize="y"))] // ok
c: (),
#[serde(rename="x")]
#[serde(rename(deserialize="y"))] //~ ERROR: duplicate serde attribute `rename`
d: (),
#[serde(rename(serialize="x", serialize="y"))] //~ ERROR: duplicate serde attribute `rename`
e: (),
#[serde(rename="x", serialize="y")] //~ ERROR: unknown serde field attribute `serialize = "y"`
f: (),
#[serde(rename(serialize="x"), rename(serialize="y"))] //~ ERROR: duplicate serde attribute `rename`
g: (),
}
fn main() {}
@@ -0,0 +1,30 @@
#![feature(custom_attribute, custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
#[derive(Serialize)]
#[serde(abc="xyz")] //~ unknown serde container attribute `abc = "xyz"`
struct Foo {
x: u32,
}
#[derive(Deserialize)]
#[serde(abc="xyz")] //~ unknown serde container attribute `abc = "xyz"`
struct Foo {
x: u32,
}
#[derive(Serialize)]
struct Foo {
#[serde(abc="xyz")] //~ unknown serde field attribute `abc = "xyz"`
x: u32,
}
#[derive(Deserialize)]
struct Foo {
#[serde(abc="xyz")] //~ unknown serde field attribute `abc = "xyz"`
x: u32,
}
fn main() { }
@@ -0,0 +1,9 @@
#![feature(custom_attribute, custom_derive, plugin)]
#![plugin(serde_macros)]
#[derive(Serialize, Deserialize)]
struct Test<'a> {
s: &'a str, //~ ERROR: Serde does not support deserializing fields of type &str
}
fn main() {}
+30
View File
@@ -0,0 +1,30 @@
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");
}
@@ -0,0 +1,12 @@
#![feature(custom_derive, plugin)]
#![plugin(serde_macros, clippy)]
#![deny(identity_op)]
// The derived implementation uses 0+1 to add up the number of fields
// serialized, which Clippy warns about. If the expansion info is registered
// correctly, the Clippy lint is not triggered.
#[derive(Serialize)]
struct A { b: u8 }
fn main() {}
+3 -1
View File
@@ -4,4 +4,6 @@
extern crate serde;
extern crate test;
include!("../../serde_tests/tests/test.rs.in");
include!("../../testing/tests/test.rs.in");
mod compile_tests;
+14
View File
@@ -0,0 +1,14 @@
[package]
name = "serde_test"
version = "0.7.15"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde-rs.github.io/serde/serde/"
readme = "../README.md"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[dependencies]
serde = "0.7.15"
+54
View File
@@ -0,0 +1,54 @@
use serde::{Serialize, Deserialize};
use de::Deserializer;
use error::Error;
use ser::Serializer;
use token::Token;
use std::fmt::Debug;
pub fn assert_tokens<T>(value: &T, tokens: &[Token<'static>])
where T: Serialize + Deserialize + PartialEq + Debug,
{
assert_ser_tokens(value, tokens);
assert_de_tokens(value, tokens);
}
pub fn assert_ser_tokens<T>(value: &T, tokens: &[Token])
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`.
pub fn assert_ser_tokens_error<T>(value: &T, tokens: &[Token], error: Error)
where T: Serialize + PartialEq + Debug,
{
let mut ser = Serializer::new(tokens.iter());
let v: Result<(), Error> = Serialize::serialize(value, &mut ser);
assert_eq!(v.as_ref(), Err(&error));
assert_eq!(ser.next_token(), None);
}
pub fn assert_de_tokens<T>(value: &T, tokens: &[Token<'static>])
where T: Deserialize + PartialEq + Debug,
{
let mut de = Deserializer::new(tokens.to_vec().into_iter());
let v: Result<T, Error> = Deserialize::deserialize(&mut de);
assert_eq!(v.as_ref(), Ok(value));
assert_eq!(de.next_token(), None);
}
/// Expect an error deserializing tokens into a `T`.
pub fn assert_de_tokens_error<T>(tokens: &[Token<'static>], error: Error)
where T: Deserialize + PartialEq + Debug,
{
let mut de = Deserializer::new(tokens.to_vec().into_iter());
let v: Result<T, Error> = Deserialize::deserialize(&mut de);
assert_eq!(v, Err(error));
// There may be one token left if a peek caused the error
de.next_token();
assert_eq!(de.next_token(), None);
}
+854
View File
@@ -0,0 +1,854 @@
use std::iter;
use serde::de::{
self,
Deserialize,
EnumVisitor,
MapVisitor,
SeqVisitor,
VariantVisitor,
Visitor,
};
use error::Error;
use token::Token;
pub struct Deserializer<I>
where I: Iterator<Item=Token<'static>>,
{
tokens: iter::Peekable<I>,
}
impl<I> Deserializer<I>
where I: Iterator<Item=Token<'static>>,
{
pub fn new(tokens: I) -> Deserializer<I> {
Deserializer {
tokens: tokens.peekable(),
}
}
pub fn next_token(&mut self) -> Option<Token<'static>> {
self.tokens.next()
}
fn visit_seq<V>(&mut self, len: Option<usize>, mut visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
visitor.visit_seq(DeserializerSeqVisitor {
de: self,
len: len,
})
}
fn visit_array<V>(&mut self, len: usize, mut visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
visitor.visit_seq(DeserializerArrayVisitor {
de: self,
len: len,
})
}
fn visit_tuple<V>(&mut self, len: usize, mut visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
visitor.visit_seq(DeserializerTupleVisitor {
de: self,
len: len,
})
}
fn visit_tuple_struct<V>(&mut self, len: usize, mut visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
visitor.visit_seq(DeserializerTupleStructVisitor {
de: self,
len: len,
})
}
fn visit_variant_seq<V>(&mut self, len: Option<usize>, mut visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
visitor.visit_seq(DeserializerVariantSeqVisitor {
de: self,
len: len,
})
}
fn visit_map<V>(&mut self, len: Option<usize>, mut visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
visitor.visit_map(DeserializerMapVisitor {
de: self,
len: len,
})
}
fn visit_struct<V>(&mut self, len: Option<usize>, mut visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
visitor.visit_map(DeserializerStructVisitor {
de: self,
len: len,
})
}
fn visit_variant_map<V>(&mut self, len: Option<usize>, mut visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
visitor.visit_map(DeserializerVariantMapVisitor {
de: self,
len: len,
})
}
}
impl<I> de::Deserializer for Deserializer<I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.tokens.next() {
Some(Token::Bool(v)) => visitor.visit_bool(v),
Some(Token::Isize(v)) => visitor.visit_isize(v),
Some(Token::I8(v)) => visitor.visit_i8(v),
Some(Token::I16(v)) => visitor.visit_i16(v),
Some(Token::I32(v)) => visitor.visit_i32(v),
Some(Token::I64(v)) => visitor.visit_i64(v),
Some(Token::Usize(v)) => visitor.visit_usize(v),
Some(Token::U8(v)) => visitor.visit_u8(v),
Some(Token::U16(v)) => visitor.visit_u16(v),
Some(Token::U32(v)) => visitor.visit_u32(v),
Some(Token::U64(v)) => visitor.visit_u64(v),
Some(Token::F32(v)) => visitor.visit_f32(v),
Some(Token::F64(v)) => visitor.visit_f64(v),
Some(Token::Char(v)) => visitor.visit_char(v),
Some(Token::Str(v)) => visitor.visit_str(v),
Some(Token::String(v)) => visitor.visit_string(v),
Some(Token::Bytes(v)) => visitor.visit_bytes(v),
Some(Token::Option(false)) => visitor.visit_none(),
Some(Token::Option(true)) => visitor.visit_some(self),
Some(Token::Unit) => visitor.visit_unit(),
Some(Token::UnitStruct(name)) => visitor.visit_unit_struct(name),
Some(Token::SeqStart(len)) | Some(Token::TupleStructStart(_, len)) => {
self.visit_seq(len, visitor)
}
Some(Token::SeqArrayStart(len)) => {
self.visit_seq(Some(len), visitor)
}
Some(Token::MapStart(len)) | Some(Token::StructStart(_, len)) => {
self.visit_map(len, visitor)
}
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
}
}
/// Hook into `Option` deserializing so we can treat `Unit` as a
/// `None`, or a regular value as `Some(value)`.
fn deserialize_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.tokens.peek() {
Some(&Token::Option(false)) => {
self.tokens.next();
visitor.visit_none()
}
Some(&Token::Option(true)) => {
self.tokens.next();
visitor.visit_some(self)
}
Some(&Token::Unit) => {
self.tokens.next();
visitor.visit_none()
}
Some(_) => visitor.visit_some(self),
None => Err(Error::EndOfStream),
}
}
fn deserialize_enum<V>(&mut self,
name: &str,
_variants: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Error>
where V: EnumVisitor,
{
match self.tokens.peek() {
Some(&Token::EnumStart(n)) if name == n => {
self.tokens.next();
visitor.visit(DeserializerVariantVisitor {
de: self,
})
}
Some(&Token::EnumUnit(n, _))
| Some(&Token::EnumNewType(n, _))
| Some(&Token::EnumSeqStart(n, _, _))
| Some(&Token::EnumMapStart(n, _, _)) if name == n => {
visitor.visit(DeserializerVariantVisitor {
de: self,
})
}
Some(_) => {
let token = self.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => { return Err(Error::EndOfStream); }
}
}
fn deserialize_unit_struct<V>(&mut self, name: &str, mut visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.tokens.peek() {
Some(&Token::UnitStruct(n)) => {
self.tokens.next();
if name == n {
visitor.visit_unit()
} else {
Err(Error::InvalidName(n))
}
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfStream),
}
}
fn deserialize_newtype_struct<V>(&mut self,
name: &str,
mut visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.tokens.peek() {
Some(&Token::StructNewType(n)) => {
self.tokens.next();
if name == n {
visitor.visit_newtype_struct(self)
} else {
Err(Error::InvalidName(n))
}
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfStream),
}
}
fn deserialize_fixed_size_array<V>(&mut self,
len: usize,
visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.tokens.peek() {
Some(&Token::SeqArrayStart(_)) => {
self.tokens.next();
self.visit_array(len, visitor)
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfStream),
}
}
fn deserialize_tuple<V>(&mut self,
len: usize,
mut visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.tokens.peek() {
Some(&Token::Unit) => {
self.tokens.next();
visitor.visit_unit()
}
Some(&Token::UnitStruct(_)) => {
self.tokens.next();
visitor.visit_unit()
}
Some(&Token::SeqStart(_)) => {
self.tokens.next();
self.visit_seq(Some(len), visitor)
}
Some(&Token::SeqArrayStart(_)) => {
self.tokens.next();
self.visit_array(len, visitor)
}
Some(&Token::TupleStart(_)) => {
self.tokens.next();
self.visit_tuple(len, visitor)
}
Some(&Token::TupleStructStart(_, _)) => {
self.tokens.next();
self.visit_tuple_struct(len, visitor)
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfStream),
}
}
fn deserialize_tuple_struct<V>(&mut self,
name: &str,
len: usize,
mut visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.tokens.peek() {
Some(&Token::Unit) => {
self.tokens.next();
visitor.visit_unit()
}
Some(&Token::UnitStruct(n)) => {
self.tokens.next();
if name == n {
visitor.visit_unit()
} else {
Err(Error::InvalidName(n))
}
}
Some(&Token::SeqStart(_)) => {
self.tokens.next();
self.visit_seq(Some(len), visitor)
}
Some(&Token::SeqArrayStart(_)) => {
self.tokens.next();
self.visit_array(len, visitor)
}
Some(&Token::TupleStart(_)) => {
self.tokens.next();
self.visit_tuple(len, visitor)
}
Some(&Token::TupleStructStart(n, _)) => {
self.tokens.next();
if name == n {
self.visit_tuple_struct(len, visitor)
} else {
Err(Error::InvalidName(n))
}
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfStream),
}
}
fn deserialize_struct<V>(&mut self,
name: &str,
fields: &'static [&'static str],
visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.tokens.peek() {
Some(&Token::StructStart(n, _)) => {
self.tokens.next();
if name == n {
self.visit_struct(Some(fields.len()), visitor)
} else {
Err(Error::InvalidName(n))
}
}
Some(&Token::MapStart(_)) => {
self.tokens.next();
self.visit_map(Some(fields.len()), visitor)
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfStream),
}
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerSeqVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: Option<usize>,
}
impl<'a, I> SeqVisitor for DeserializerSeqVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: Deserialize,
{
match self.de.tokens.peek() {
Some(&Token::SeqSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| len - 1);
Ok(Some(try!(Deserialize::deserialize(self.de))))
}
Some(&Token::SeqEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStream),
}
}
fn end(&mut self) -> Result<(), Error> {
//assert_eq!(self.len.unwrap_or(0), 0);
match self.de.tokens.next() {
Some(Token::SeqEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len.unwrap_or(0);
(len, self.len)
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerArrayVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: usize,
}
impl<'a, I> SeqVisitor for DeserializerArrayVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: Deserialize,
{
match self.de.tokens.peek() {
Some(&Token::SeqSep) => {
self.de.tokens.next();
self.len -= 1;
Ok(Some(try!(Deserialize::deserialize(self.de))))
}
Some(&Token::SeqEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStream),
}
}
fn end(&mut self) -> Result<(), Error> {
assert_eq!(self.len, 0);
match self.de.tokens.next() {
Some(Token::SeqEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerTupleVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: usize,
}
impl<'a, I> SeqVisitor for DeserializerTupleVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: Deserialize,
{
match self.de.tokens.peek() {
Some(&Token::TupleSep) => {
self.de.tokens.next();
self.len -= 1;
Ok(Some(try!(Deserialize::deserialize(self.de))))
}
Some(&Token::TupleEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStream),
}
}
fn end(&mut self) -> Result<(), Error> {
assert_eq!(self.len, 0);
match self.de.tokens.next() {
Some(Token::TupleEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerTupleStructVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: usize,
}
impl<'a, I> SeqVisitor for DeserializerTupleStructVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: Deserialize,
{
match self.de.tokens.peek() {
Some(&Token::TupleStructSep) => {
self.de.tokens.next();
self.len -= 1;
Ok(Some(try!(Deserialize::deserialize(self.de))))
}
Some(&Token::TupleStructEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStream),
}
}
fn end(&mut self) -> Result<(), Error> {
assert_eq!(self.len, 0);
match self.de.tokens.next() {
Some(Token::TupleStructEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerVariantSeqVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: Option<usize>,
}
impl<'a, I> SeqVisitor for DeserializerVariantSeqVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: Deserialize,
{
match self.de.tokens.peek() {
Some(&Token::EnumSeqSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| len - 1);
Ok(Some(try!(Deserialize::deserialize(self.de))))
}
Some(&Token::EnumSeqEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStream),
}
}
fn end(&mut self) -> Result<(), Error> {
//assert_eq!(self.len.unwrap_or(0), 0);
match self.de.tokens.next() {
Some(Token::EnumSeqEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len.unwrap_or(0);
(len, self.len)
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerMapVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: Option<usize>,
}
impl<'a, I> MapVisitor for DeserializerMapVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
where K: Deserialize,
{
match self.de.tokens.peek() {
Some(&Token::MapSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| if len > 0 { len - 1} else { 0 });
Ok(Some(try!(Deserialize::deserialize(self.de))))
}
Some(&Token::MapEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStream),
}
}
fn visit_value<V>(&mut self) -> Result<V, Error>
where V: Deserialize,
{
Ok(try!(Deserialize::deserialize(self.de)))
}
fn end(&mut self) -> Result<(), Error> {
//assert_eq!(self.len.unwrap_or(0), 0);
match self.de.tokens.next() {
Some(Token::MapEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len.unwrap_or(0);
(len, self.len)
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerStructVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: Option<usize>,
}
impl<'a, I> MapVisitor for DeserializerStructVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
where K: Deserialize,
{
match self.de.tokens.peek() {
Some(&Token::StructSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| if len > 0 { len - 1} else { 0 });
Ok(Some(try!(Deserialize::deserialize(self.de))))
}
Some(&Token::StructEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStream),
}
}
fn visit_value<V>(&mut self) -> Result<V, Error>
where V: Deserialize,
{
Ok(try!(Deserialize::deserialize(self.de)))
}
fn end(&mut self) -> Result<(), Error> {
//assert_eq!(self.len.unwrap_or(0), 0);
match self.de.tokens.next() {
Some(Token::StructEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len.unwrap_or(0);
(len, self.len)
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerVariantVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
}
impl<'a, I> VariantVisitor for DeserializerVariantVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_variant<V>(&mut self) -> Result<V, Error>
where V: Deserialize,
{
match self.de.tokens.peek() {
Some(&Token::EnumUnit(_, v))
| Some(&Token::EnumNewType(_, v))
| Some(&Token::EnumSeqStart(_, v, _))
| Some(&Token::EnumMapStart(_, v, _)) => {
let mut de = de::value::ValueDeserializer::<Error>::into_deserializer(v);
let value = try!(Deserialize::deserialize(&mut de));
Ok(value)
}
Some(_) => {
Deserialize::deserialize(self.de)
}
None => Err(Error::EndOfStream),
}
}
fn visit_unit(&mut self) -> Result<(), Error> {
match self.de.tokens.peek() {
Some(&Token::EnumUnit(_, _)) => {
self.de.tokens.next();
Ok(())
}
Some(_) => {
Deserialize::deserialize(self.de)
}
None => Err(Error::EndOfStream),
}
}
fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
where T: Deserialize,
{
match self.de.tokens.peek() {
Some(&Token::EnumNewType(_, _)) => {
self.de.tokens.next();
Deserialize::deserialize(self.de)
}
Some(_) => {
Deserialize::deserialize(self.de)
}
None => Err(Error::EndOfStream),
}
}
fn visit_tuple<V>(&mut self,
len: usize,
visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.de.tokens.peek() {
Some(&Token::EnumSeqStart(_, _, Some(enum_len))) => {
let token = self.de.tokens.next().unwrap();
if len == enum_len {
self.de.visit_variant_seq(Some(len), visitor)
} else {
Err(Error::UnexpectedToken(token))
}
}
Some(&Token::SeqStart(Some(enum_len))) => {
let token = self.de.tokens.next().unwrap();
if len == enum_len {
self.de.visit_seq(Some(len), visitor)
} else {
Err(Error::UnexpectedToken(token))
}
}
Some(_) => {
Deserialize::deserialize(self.de)
}
None => Err(Error::EndOfStream),
}
}
fn visit_struct<V>(&mut self,
fields: &'static [&'static str],
visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.de.tokens.peek() {
Some(&Token::EnumMapStart(_, _, Some(enum_len))) => {
let token = self.de.tokens.next().unwrap();
if fields.len() == enum_len {
self.de.visit_variant_map(Some(fields.len()), visitor)
} else {
Err(Error::UnexpectedToken(token))
}
}
Some(&Token::MapStart(Some(enum_len))) => {
let token = self.de.tokens.next().unwrap();
if fields.len() == enum_len {
self.de.visit_map(Some(fields.len()), visitor)
} else {
Err(Error::UnexpectedToken(token))
}
}
Some(_) => {
Deserialize::deserialize(self.de)
}
None => Err(Error::EndOfStream),
}
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerVariantMapVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: Option<usize>,
}
impl<'a, I> MapVisitor for DeserializerVariantMapVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
where K: Deserialize,
{
match self.de.tokens.peek() {
Some(&Token::EnumMapSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| if len > 0 { len - 1} else { 0 });
Ok(Some(try!(Deserialize::deserialize(self.de))))
}
Some(&Token::EnumMapEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStream),
}
}
fn visit_value<V>(&mut self) -> Result<V, Error>
where V: Deserialize,
{
Ok(try!(Deserialize::deserialize(self.de)))
}
fn end(&mut self) -> Result<(), Error> {
//assert_eq!(self.len.unwrap_or(0), 0);
match self.de.tokens.next() {
Some(Token::EnumMapEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len.unwrap_or(0);
(len, self.len)
}
}
+87
View File
@@ -0,0 +1,87 @@
use std::{error, fmt};
use serde::{ser, de};
use token::Token;
#[derive(Clone, PartialEq, Debug)]
pub enum Error {
// Shared
Custom(String),
InvalidValue(String),
// De
EndOfStream,
InvalidType(de::Type),
InvalidLength(usize),
UnknownVariant(String),
UnknownField(String),
MissingField(&'static str),
DuplicateField(&'static str),
InvalidName(&'static str),
UnexpectedToken(Token<'static>),
}
impl ser::Error for Error {
fn custom<T: Into<String>>(msg: T) -> Error {
Error::Custom(msg.into())
}
fn invalid_value(msg: &str) -> Error {
Error::InvalidValue(msg.to_owned())
}
}
impl de::Error for Error {
fn custom<T: Into<String>>(msg: T) -> Error {
Error::Custom(msg.into())
}
fn end_of_stream() -> Error {
Error::EndOfStream
}
fn invalid_type(ty: de::Type) -> Error {
Error::InvalidType(ty)
}
fn invalid_value(msg: &str) -> Error {
Error::InvalidValue(msg.to_owned())
}
fn invalid_length(len: usize) -> Error {
Error::InvalidLength(len)
}
fn unknown_variant(variant: &str) -> Error {
Error::UnknownVariant(variant.to_owned())
}
fn unknown_field(field: &str) -> Error {
Error::UnknownField(field.to_owned())
}
fn missing_field(field: &'static str) -> Error {
Error::MissingField(field)
}
fn duplicate_field(field: &'static str) -> Error {
Error::DuplicateField(field)
}
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(format!("{:?}", self).as_ref())
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Error"
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
+22
View File
@@ -0,0 +1,22 @@
extern crate serde;
mod assert;
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;
mod de;
pub use de::Deserializer;
mod token;
pub use token::Token;
mod error;
pub use error::Error;
+350
View File
@@ -0,0 +1,350 @@
use std::marker::PhantomData;
use serde::ser::{
self,
MapVisitor,
SeqVisitor,
Serialize,
};
use error::Error;
use token::Token;
pub struct Serializer<'a, I>
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>>,
{
pub fn new(tokens: I) -> Serializer<'a, I> {
Serializer {
tokens: tokens,
phantom: PhantomData,
}
}
pub fn next_token(&mut self) -> Option<&'a Token<'a>> {
self.tokens.next()
}
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::SeqEnd));
Ok(())
}
fn visit_map<V>(&mut self, mut visitor: V) -> Result<(), Error>
where V: MapVisitor
{
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::MapEnd));
Ok(())
}
}
impl<'a, I> ser::Serializer for Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
{
type Error = Error;
fn serialize_unit(&mut self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Unit));
Ok(())
}
fn serialize_newtype_variant<T>(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::EnumNewType(name, variant)));
value.serialize(self)
}
fn serialize_unit_struct(&mut self, name: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::UnitStruct(name)));
Ok(())
}
fn serialize_unit_variant(&mut self,
name: &str,
_variant_index: usize,
variant: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumUnit(name, variant)));
Ok(())
}
fn serialize_bool(&mut self, v: bool) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Bool(v)));
Ok(())
}
fn serialize_isize(&mut self, v: isize) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Isize(v)));
Ok(())
}
fn serialize_i8(&mut self, v: i8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I8(v)));
Ok(())
}
fn serialize_i16(&mut self, v: i16) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I16(v)));
Ok(())
}
fn serialize_i32(&mut self, v: i32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I32(v)));
Ok(())
}
fn serialize_i64(&mut self, v: i64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I64(v)));
Ok(())
}
fn serialize_usize(&mut self, v: usize) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Usize(v)));
Ok(())
}
fn serialize_u8(&mut self, v: u8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U8(v)));
Ok(())
}
fn serialize_u16(&mut self, v: u16) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U16(v)));
Ok(())
}
fn serialize_u32(&mut self, v: u32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U32(v)));
Ok(())
}
fn serialize_u64(&mut self, v: u64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U64(v)));
Ok(())
}
fn serialize_f32(&mut self, v: f32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::F32(v)));
Ok(())
}
fn serialize_f64(&mut self, v: f64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::F64(v)));
Ok(())
}
fn serialize_char(&mut self, v: char) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Char(v)));
Ok(())
}
fn serialize_str(&mut self, v: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Str(v)));
Ok(())
}
fn serialize_none(&mut self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Option(false)));
Ok(())
}
fn serialize_some<V>(&mut self, value: V) -> Result<(), Error>
where V: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::Option(true)));
value.serialize(self)
}
fn serialize_seq<V>(&mut self, visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::SeqStart(len)));
self.visit_seq(visitor)
}
fn serialize_fixed_size_array<V>(&mut self, visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
let len = visitor.len().expect("arrays must have a length");
assert_eq!(self.tokens.next(), Some(&Token::SeqArrayStart(len)));
self.visit_seq(visitor)
}
fn serialize_seq_elt<T>(&mut self, value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::SeqSep));
value.serialize(self)
}
fn serialize_tuple<V>(&mut self, mut visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
let len = visitor.len().expect("arrays must have a length");
assert_eq!(self.tokens.next(), Some(&Token::TupleStart(len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::TupleEnd));
Ok(())
}
fn serialize_tuple_elt<T>(&mut self, value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::TupleSep));
value.serialize(self)
}
fn serialize_newtype_struct<T>(&mut self,
name: &'static str,
value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::StructNewType(name)));
value.serialize(self)
}
fn serialize_tuple_struct<V>(&mut self, name: &str, mut visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::TupleStructStart(name, len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::TupleStructEnd));
Ok(())
}
fn serialize_tuple_struct_elt<T>(&mut self, value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::TupleStructSep));
value.serialize(self)
}
fn serialize_tuple_variant<V>(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
mut visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqStart(name, variant, len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqEnd));
Ok(())
}
fn serialize_tuple_variant_elt<T>(&mut self, value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqSep));
value.serialize(self)
}
fn serialize_map<V>(&mut self, visitor: V) -> Result<(), Error>
where V: MapVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::MapStart(len)));
self.visit_map(visitor)
}
fn serialize_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Error>
where K: Serialize,
V: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::MapSep));
try!(key.serialize(self));
value.serialize(self)
}
fn serialize_struct<V>(&mut self, name: &str, mut visitor: V) -> Result<(), Error>
where V: MapVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::StructStart(name, len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::StructEnd));
Ok(())
}
fn serialize_struct_elt<T>(&mut self, key: &'static str, value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::StructSep));
try!(key.serialize(self));
value.serialize(self)
}
fn serialize_struct_variant<V>(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
mut visitor: V) -> Result<(), Error>
where V: MapVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::EnumMapStart(name, variant, len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::EnumMapEnd));
Ok(())
}
fn serialize_struct_variant_elt<T>(&mut self, key: &'static str, value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::EnumMapSep));
try!(key.serialize(self));
value.serialize(self)
}
}
+60
View File
@@ -0,0 +1,60 @@
#[derive(Clone, PartialEq, Debug)]
pub enum Token<'a> {
Bool(bool),
Isize(isize),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
Usize(usize),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
F32(f32),
F64(f64),
Char(char),
Str(&'a str),
String(String),
Bytes(&'a [u8]),
Option(bool),
Unit,
UnitStruct(&'a str),
StructNewType(&'a str),
EnumStart(&'a str),
EnumUnit(&'a str, &'a str),
EnumNewType(&'a str, &'a str),
SeqStart(Option<usize>),
SeqArrayStart(usize),
SeqSep,
SeqEnd,
TupleStart(usize),
TupleSep,
TupleEnd,
TupleStructStart(&'a str, Option<usize>),
TupleStructSep,
TupleStructEnd,
MapStart(Option<usize>),
MapSep,
MapEnd,
StructStart(&'a str, Option<usize>),
StructSep,
StructEnd,
EnumSeqStart(&'a str, &'a str, Option<usize>),
EnumSeqSep,
EnumSeqEnd,
EnumMapStart(&'a str, &'a str, Option<usize>),
EnumMapSep,
EnumMapEnd,
}
-3
View File
@@ -1,3 +0,0 @@
extern crate serde;
include!(concat!(env!("OUT_DIR"), "/test.rs"));
-343
View File
@@ -1,343 +0,0 @@
use std::default;
use token::{Token, assert_tokens, assert_ser_tokens, assert_de_tokens};
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Default {
a1: i32,
#[serde(default)]
a2: i32,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Rename {
a1: i32,
#[serde(rename="a3")]
a2: i32,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FormatRename {
a1: i32,
#[serde(rename(xml= "a4", token="a5"))]
a2: i32,
}
#[derive(Debug, PartialEq, Deserialize, Serialize)]
enum SerEnum<A> {
Map {
a: i8,
#[serde(rename(xml= "c", token="d"))]
b: A,
},
}
#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct SkipSerializingFields<A: default::Default> {
a: i8,
#[serde(skip_serializing, default)]
b: A,
}
#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct SkipSerializingIfEmptyFields<A: default::Default> {
a: i8,
#[serde(skip_serializing_if_empty, default)]
b: Vec<A>,
}
#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct SkipSerializingIfNoneFields<A: default::Default> {
a: i8,
#[serde(skip_serializing_if_none, default)]
b: Option<A>,
}
#[test]
fn test_default() {
assert_de_tokens(
&Default { a1: 1, a2: 2 },
vec![
Token::StructStart("Default", Some(2)),
Token::MapSep,
Token::Str("a1"),
Token::I32(1),
Token::MapSep,
Token::Str("a2"),
Token::I32(2),
Token::MapEnd,
]
);
assert_de_tokens(
&Default { a1: 1, a2: 0 },
vec![
Token::StructStart("Default", Some(1)),
Token::MapSep,
Token::Str("a1"),
Token::I32(1),
Token::MapEnd,
]
);
}
#[test]
fn test_rename() {
assert_tokens(
&Rename { a1: 1, a2: 2 },
vec![
Token::StructStart("Rename", Some(2)),
Token::MapSep,
Token::Str("a1"),
Token::I32(1),
Token::MapSep,
Token::Str("a3"),
Token::I32(2),
Token::MapEnd,
]
);
}
#[test]
fn test_format_rename() {
assert_tokens(
&FormatRename { a1: 1, a2: 2 },
vec![
Token::StructStart("FormatRename", Some(2)),
Token::MapSep,
Token::Str("a1"),
Token::I32(1),
Token::MapSep,
Token::Str("a5"),
Token::I32(2),
Token::MapEnd,
]
);
}
#[test]
fn test_enum_format_rename() {
assert_tokens(
&SerEnum::Map {
a: 0,
b: String::new(),
},
vec![
Token::EnumMapStart("SerEnum", "Map", Some(2)),
Token::MapSep,
Token::Str("a"),
Token::I8(0),
Token::MapSep,
Token::Str("d"),
Token::Str(""),
Token::MapEnd,
]
);
}
#[test]
fn test_skip_serializing_fields() {
assert_ser_tokens(
&SkipSerializingFields {
a: 1,
b: 2,
},
&[
Token::StructStart("SkipSerializingFields", Some(1)),
Token::MapSep,
Token::Str("a"),
Token::I8(1),
Token::MapEnd,
]
);
assert_de_tokens(
&SkipSerializingFields {
a: 1,
b: 0,
},
vec![
Token::StructStart("SkipSerializingFields", Some(1)),
Token::MapSep,
Token::Str("a"),
Token::I8(1),
Token::MapEnd,
]
);
}
#[test]
fn test_skip_serializing_fields_if_empty() {
assert_ser_tokens(
&SkipSerializingIfEmptyFields::<i32> {
a: 1,
b: vec![],
},
&[
Token::StructStart("SkipSerializingIfEmptyFields", Some(1)),
Token::MapSep,
Token::Str("a"),
Token::I8(1),
Token::MapEnd,
]
);
assert_de_tokens(
&SkipSerializingIfEmptyFields::<i32> {
a: 1,
b: vec![],
},
vec![
Token::StructStart("SkipSerializingIfEmptyFields", Some(1)),
Token::MapSep,
Token::Str("a"),
Token::I8(1),
Token::MapEnd,
]
);
assert_ser_tokens(
&SkipSerializingIfEmptyFields {
a: 1,
b: vec![2],
},
&[
Token::StructStart("SkipSerializingIfEmptyFields", Some(2)),
Token::MapSep,
Token::Str("a"),
Token::I8(1),
Token::MapSep,
Token::Str("b"),
Token::SeqStart(Some(1)),
Token::SeqSep,
Token::I32(2),
Token::SeqEnd,
Token::MapEnd,
]
);
assert_de_tokens(
&SkipSerializingIfEmptyFields {
a: 1,
b: vec![2],
},
vec![
Token::StructStart("SkipSerializingIfEmptyFields", Some(2)),
Token::MapSep,
Token::Str("a"),
Token::I8(1),
Token::MapSep,
Token::Str("b"),
Token::SeqStart(Some(1)),
Token::SeqSep,
Token::I32(2),
Token::SeqEnd,
Token::MapEnd,
]
);
}
#[test]
fn test_skip_serializing_fields_if_none() {
assert_ser_tokens(
&SkipSerializingIfNoneFields::<i32> {
a: 1,
b: None,
},
&[
Token::StructStart("SkipSerializingIfNoneFields", Some(1)),
Token::MapSep,
Token::Str("a"),
Token::I8(1),
Token::MapEnd,
]
);
assert_de_tokens(
&SkipSerializingIfNoneFields::<i32> {
a: 1,
b: None,
},
vec![
Token::StructStart("SkipSerializingIfNoneFields", Some(1)),
Token::MapSep,
Token::Str("a"),
Token::I8(1),
Token::MapEnd,
]
);
assert_ser_tokens(
&SkipSerializingIfNoneFields {
a: 1,
b: Some(2),
},
&[
Token::StructStart("SkipSerializingIfNoneFields", Some(2)),
Token::MapSep,
Token::Str("a"),
Token::I8(1),
Token::MapSep,
Token::Str("b"),
Token::Option(true),
Token::I32(2),
Token::MapEnd,
]
);
assert_de_tokens(
&SkipSerializingIfNoneFields {
a: 1,
b: Some(2),
},
vec![
Token::StructStart("SkipSerializingIfNoneFields", Some(2)),
Token::MapSep,
Token::Str("a"),
Token::I8(1),
Token::MapSep,
Token::Str("b"),
Token::Option(true),
Token::I32(2),
Token::MapEnd,
]
);
}
-789
View File
@@ -1,789 +0,0 @@
use std::fmt;
use std::iter;
use serde::{ser, de};
use serde::de::value::{self, ValueDeserializer};
#[derive(Clone, PartialEq, Debug)]
pub enum Token<'a> {
Bool(bool),
Isize(isize),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
Usize(usize),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
F32(f32),
F64(f64),
Char(char),
Str(&'a str),
String(String),
Bytes(&'a [u8]),
Option(bool),
Unit,
UnitStruct(&'a str),
StructNewtype(&'a str),
EnumStart(&'a str),
EnumUnit(&'a str, &'a str),
EnumNewtype(&'a str, &'a str),
EnumSeqStart(&'a str, &'a str, Option<usize>),
EnumMapStart(&'a str, &'a str, Option<usize>),
SeqStart(Option<usize>),
TupleStructStart(&'a str, Option<usize>),
SeqSep,
SeqEnd,
MapStart(Option<usize>),
StructStart(&'a str, Option<usize>),
MapSep,
MapEnd,
}
//////////////////////////////////////////////////////////////////////////////
pub struct Serializer<I> {
tokens: I,
}
impl<'a, I> Serializer<I>
where I: Iterator<Item=&'a Token<'a>>
{
pub fn new(tokens: I) -> Serializer<I> {
Serializer {
tokens: tokens,
}
}
fn visit_sequence<V>(&mut self, mut visitor: V) -> Result<(), ()>
where V: ser::SeqVisitor
{
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::SeqEnd));
Ok(())
}
fn visit_mapping<V>(&mut self, mut visitor: V) -> Result<(), ()>
where V: ser::MapVisitor
{
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::MapEnd));
Ok(())
}
}
impl<'a, I> ser::Serializer for Serializer<I>
where I: Iterator<Item=&'a Token<'a>>,
{
type Error = ();
fn visit_unit(&mut self) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::Unit));
Ok(())
}
fn visit_newtype_variant<T>(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
value: T) -> Result<(), ()>
where T: ser::Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::EnumNewtype(name, variant)));
value.serialize(self)
}
fn visit_unit_struct(&mut self, name: &str) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::UnitStruct(name)));
Ok(())
}
fn visit_unit_variant(&mut self,
name: &str,
_variant_index: usize,
variant: &str) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::EnumUnit(name, variant)));
Ok(())
}
fn visit_bool(&mut self, v: bool) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::Bool(v)));
Ok(())
}
fn visit_isize(&mut self, v: isize) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::Isize(v)));
Ok(())
}
fn visit_i8(&mut self, v: i8) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::I8(v)));
Ok(())
}
fn visit_i16(&mut self, v: i16) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::I16(v)));
Ok(())
}
fn visit_i32(&mut self, v: i32) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::I32(v)));
Ok(())
}
fn visit_i64(&mut self, v: i64) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::I64(v)));
Ok(())
}
fn visit_usize(&mut self, v: usize) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::Usize(v)));
Ok(())
}
fn visit_u8(&mut self, v: u8) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::U8(v)));
Ok(())
}
fn visit_u16(&mut self, v: u16) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::U16(v)));
Ok(())
}
fn visit_u32(&mut self, v: u32) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::U32(v)));
Ok(())
}
fn visit_u64(&mut self, v: u64) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::U64(v)));
Ok(())
}
fn visit_f32(&mut self, v: f32) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::F32(v)));
Ok(())
}
fn visit_f64(&mut self, v: f64) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::F64(v)));
Ok(())
}
fn visit_char(&mut self, v: char) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::Char(v)));
Ok(())
}
fn visit_str(&mut self, v: &str) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::Str(v)));
Ok(())
}
fn visit_none(&mut self) -> Result<(), ()> {
assert_eq!(self.tokens.next(), Some(&Token::Option(false)));
Ok(())
}
fn visit_some<V>(&mut self, value: V) -> Result<(), ()>
where V: ser::Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::Option(true)));
value.serialize(self)
}
fn visit_seq<V>(&mut self, visitor: V) -> Result<(), ()>
where V: ser::SeqVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::SeqStart(len)));
self.visit_sequence(visitor)
}
fn visit_newtype_struct<T>(&mut self,
name: &'static str,
value: T) -> Result<(), ()>
where T: ser::Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::StructNewtype(name)));
value.serialize(self)
}
fn visit_tuple_struct<V>(&mut self, name: &str, visitor: V) -> Result<(), ()>
where V: ser::SeqVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::TupleStructStart(name, len)));
self.visit_sequence(visitor)
}
fn visit_tuple_variant<V>(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
visitor: V) -> Result<(), ()>
where V: ser::SeqVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqStart(name, variant, len)));
self.visit_sequence(visitor)
}
fn visit_seq_elt<T>(&mut self, value: T) -> Result<(), ()>
where T: ser::Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::SeqSep));
value.serialize(self)
}
fn visit_map<V>(&mut self, visitor: V) -> Result<(), ()>
where V: ser::MapVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::MapStart(len)));
self.visit_mapping(visitor)
}
fn visit_struct<V>(&mut self, name: &str, visitor: V) -> Result<(), ()>
where V: ser::MapVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::StructStart(name, len)));
self.visit_mapping(visitor)
}
fn visit_struct_variant<V>(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
visitor: V) -> Result<(), ()>
where V: ser::MapVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::EnumMapStart(name, variant, len)));
self.visit_mapping(visitor)
}
fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), ()>
where K: ser::Serialize,
V: ser::Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::MapSep));
try!(key.serialize(self));
value.serialize(self)
}
fn format() -> &'static str {
"token"
}
}
//////////////////////////////////////////////////////////////////////////////
#[derive(Clone, PartialEq, Debug)]
enum Error {
SyntaxError,
EndOfStreamError,
UnknownFieldError(String),
MissingFieldError(&'static str),
InvalidName(&'static str),
UnexpectedToken(Token<'static>),
ValueError(value::Error),
}
impl de::Error for Error {
fn syntax(_: &str) -> Error { Error::SyntaxError }
fn end_of_stream() -> Error { Error::EndOfStreamError }
fn unknown_field(field: &str) -> Error {
Error::UnknownFieldError(field.to_string())
}
fn missing_field(field: &'static str) -> Error {
Error::MissingFieldError(field)
}
}
impl From<value::Error> for Error {
fn from(error: value::Error) -> Error {
Error::ValueError(error)
}
}
struct Deserializer<I> where I: Iterator<Item=Token<'static>> {
tokens: iter::Peekable<I>,
}
impl<I> Deserializer<I>
where I: Iterator<Item=Token<'static>>
{
fn new(tokens: I) -> Deserializer<I> {
Deserializer {
tokens: tokens.peekable(),
}
}
fn visit_seq<V>(&mut self, len: Option<usize>, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_seq(DeserializerSeqVisitor {
de: self,
len: len,
})
}
fn visit_map<V>(&mut self, len: Option<usize>, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_map(DeserializerMapVisitor {
de: self,
len: len,
})
}
}
impl<I> de::Deserializer for Deserializer<I>
where I: Iterator<Item=Token<'static>>
{
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
println!("visit {:?}", self.tokens.peek());
match self.tokens.next() {
Some(Token::Bool(v)) => visitor.visit_bool(v),
Some(Token::Isize(v)) => visitor.visit_isize(v),
Some(Token::I8(v)) => visitor.visit_i8(v),
Some(Token::I16(v)) => visitor.visit_i16(v),
Some(Token::I32(v)) => visitor.visit_i32(v),
Some(Token::I64(v)) => visitor.visit_i64(v),
Some(Token::Usize(v)) => visitor.visit_usize(v),
Some(Token::U8(v)) => visitor.visit_u8(v),
Some(Token::U16(v)) => visitor.visit_u16(v),
Some(Token::U32(v)) => visitor.visit_u32(v),
Some(Token::U64(v)) => visitor.visit_u64(v),
Some(Token::F32(v)) => visitor.visit_f32(v),
Some(Token::F64(v)) => visitor.visit_f64(v),
Some(Token::Char(v)) => visitor.visit_char(v),
Some(Token::Str(v)) => visitor.visit_str(v),
Some(Token::String(v)) => visitor.visit_string(v),
Some(Token::Bytes(v)) => visitor.visit_bytes(v),
Some(Token::Option(false)) => visitor.visit_none(),
Some(Token::Option(true)) => visitor.visit_some(self),
Some(Token::Unit) => visitor.visit_unit(),
Some(Token::UnitStruct(name)) => visitor.visit_unit_struct(name),
Some(Token::SeqStart(len)) | Some(Token::TupleStructStart(_, len)) => {
self.visit_seq(len, visitor)
}
Some(Token::MapStart(len)) | Some(Token::StructStart(_, len)) => {
self.visit_map(len, visitor)
}
//Some(Token::Name(_)) => self.visit(visitor),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStreamError),
}
}
/// Hook into `Option` deserializing so we can treat `Unit` as a
/// `None`, or a regular value as `Some(value)`.
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.tokens.peek() {
Some(&Token::Option(false)) => {
self.tokens.next();
visitor.visit_none()
}
Some(&Token::Option(true)) => {
self.tokens.next();
visitor.visit_some(self)
}
Some(&Token::Unit) => {
self.tokens.next();
visitor.visit_none()
}
Some(_) => visitor.visit_some(self),
None => Err(Error::EndOfStreamError),
}
}
fn visit_enum<V>(&mut self,
name: &str,
_variants: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Error>
where V: de::EnumVisitor,
{
match self.tokens.peek() {
Some(&Token::EnumStart(n)) if name == n => {
self.tokens.next();
visitor.visit(DeserializerVariantVisitor {
de: self,
})
}
Some(&Token::EnumUnit(n, _))
| Some(&Token::EnumNewtype(n, _))
| Some(&Token::EnumSeqStart(n, _, _))
| Some(&Token::EnumMapStart(n, _, _)) if name == n => {
visitor.visit(DeserializerVariantVisitor {
de: self,
})
}
Some(_) => {
let token = self.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => { return Err(Error::EndOfStreamError); }
}
}
fn visit_unit_struct<V>(&mut self, name: &str, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.tokens.peek() {
Some(&Token::UnitStruct(n)) => {
self.tokens.next();
if name == n {
visitor.visit_unit()
} else {
Err(Error::InvalidName(n))
}
}
Some(_) => self.visit(visitor),
None => Err(Error::EndOfStreamError),
}
}
fn visit_newtype_struct<V>(&mut self,
name: &str,
mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.tokens.peek() {
Some(&Token::StructNewtype(n)) => {
self.tokens.next();
if name == n {
visitor.visit_newtype_struct(self)
} else {
Err(Error::InvalidName(n))
}
}
Some(_) => self.visit(visitor),
None => Err(Error::EndOfStreamError),
}
}
fn visit_tuple_struct<V>(&mut self,
name: &str,
len: usize,
mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.tokens.peek() {
Some(&Token::UnitStruct(n)) => {
self.tokens.next();
if name == n {
visitor.visit_unit()
} else {
Err(Error::InvalidName(n))
}
}
Some(&Token::TupleStructStart(n, _)) => {
self.tokens.next();
if name == n {
self.visit_seq(Some(len), visitor)
} else {
Err(Error::InvalidName(n))
}
}
Some(&Token::SeqStart(_)) => {
self.tokens.next();
self.visit_seq(Some(len), visitor)
}
Some(_) => self.visit(visitor),
None => Err(Error::EndOfStreamError),
}
}
fn visit_struct<V>(&mut self,
name: &str,
fields: &'static [&'static str],
visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.tokens.peek() {
Some(&Token::StructStart(n, _)) => {
self.tokens.next();
if name == n {
self.visit_map(Some(fields.len()), visitor)
} else {
Err(Error::InvalidName(n))
}
}
Some(&Token::MapStart(_)) => {
self.tokens.next();
self.visit_map(Some(fields.len()), visitor)
}
Some(_) => self.visit(visitor),
None => Err(Error::EndOfStreamError),
}
}
fn format() -> &'static str {
"token"
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerSeqVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: Option<usize>,
}
impl<'a, I> de::SeqVisitor for DeserializerSeqVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: de::Deserialize,
{
match self.de.tokens.peek() {
Some(&Token::SeqSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| len - 1);
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
Some(&Token::SeqEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStreamError),
}
}
fn end(&mut self) -> Result<(), Error> {
//assert_eq!(self.len.unwrap_or(0), 0);
match self.de.tokens.next() {
Some(Token::SeqEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStreamError),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len.unwrap_or(0);
(len, self.len)
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerMapVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: Option<usize>,
}
impl<'a, I> de::MapVisitor for DeserializerMapVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
where K: de::Deserialize,
{
match self.de.tokens.peek() {
Some(&Token::MapSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| len - 1);
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
Some(&Token::MapEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStreamError),
}
}
fn visit_value<V>(&mut self) -> Result<V, Error>
where V: de::Deserialize,
{
Ok(try!(de::Deserialize::deserialize(self.de)))
}
fn end(&mut self) -> Result<(), Error> {
//assert_eq!(self.len.unwrap_or(0), 0);
match self.de.tokens.next() {
Some(Token::MapEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStreamError),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len.unwrap_or(0);
(len, self.len)
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerVariantVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
}
impl<'a, I> de::VariantVisitor for DeserializerVariantVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_variant<V>(&mut self) -> Result<V, Error>
where V: de::Deserialize,
{
match self.de.tokens.peek() {
Some(&Token::EnumUnit(_, v))
| Some(&Token::EnumNewtype(_, v))
| Some(&Token::EnumSeqStart(_, v, _))
| Some(&Token::EnumMapStart(_, v, _)) => {
let value = try!(de::Deserialize::deserialize(&mut v.into_deserializer()));
Ok(value)
}
Some(_) => {
de::Deserialize::deserialize(self.de)
}
None => Err(Error::EndOfStreamError),
}
}
fn visit_unit(&mut self) -> Result<(), Error> {
match self.de.tokens.peek() {
Some(&Token::EnumUnit(_, _)) => {
self.de.tokens.next();
Ok(())
}
Some(_) => {
de::Deserialize::deserialize(self.de)
}
None => Err(Error::EndOfStreamError),
}
}
fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
where T: de::Deserialize,
{
match self.de.tokens.peek() {
Some(&Token::EnumNewtype(_, _)) => {
self.de.tokens.next();
de::Deserialize::deserialize(self.de)
}
Some(_) => {
de::Deserialize::deserialize(self.de)
}
None => Err(Error::EndOfStreamError),
}
}
fn visit_tuple<V>(&mut self,
len: usize,
visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.de.tokens.peek() {
Some(&Token::EnumSeqStart(_, _, Some(enum_len))) => {
let token = self.de.tokens.next().unwrap();
if len == enum_len {
self.de.visit_seq(Some(len), visitor)
} else {
Err(Error::UnexpectedToken(token))
}
}
Some(_) => {
de::Deserialize::deserialize(self.de)
}
None => Err(Error::EndOfStreamError),
}
}
fn visit_struct<V>(&mut self,
fields: &'static [&'static str],
visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.de.tokens.peek() {
Some(&Token::EnumMapStart(_, _, Some(enum_len))) => {
let token = self.de.tokens.next().unwrap();
if fields.len() == enum_len {
self.de.visit_map(Some(fields.len()), visitor)
} else {
Err(Error::UnexpectedToken(token))
}
}
Some(_) => {
de::Deserialize::deserialize(self.de)
}
None => Err(Error::EndOfStreamError),
}
}
}
//////////////////////////////////////////////////////////////////////////////
pub fn assert_ser_tokens<T>(value: &T, tokens: &[Token])
where T: ser::Serialize,
{
let mut ser = Serializer::new(tokens.iter());
assert_eq!(ser::Serialize::serialize(value, &mut ser), Ok(()));
assert_eq!(ser.tokens.next(), None);
}
pub fn assert_de_tokens<T>(value: &T, tokens: Vec<Token<'static>>)
where T: de::Deserialize + PartialEq + fmt::Debug,
{
let mut de = Deserializer::new(tokens.into_iter());
let v: Result<T, Error> = de::Deserialize::deserialize(&mut de);
assert_eq!(v.as_ref(), Ok(value));
assert_eq!(de.tokens.next(), None);
}
pub fn assert_tokens<T>(value: &T, tokens: Vec<Token<'static>>)
where T: ser::Serialize + de::Deserialize + PartialEq + fmt::Debug,
{
assert_ser_tokens(value, &tokens[..]);
assert_de_tokens(value, tokens);
}
+12 -8
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_tests"
version = "0.6.2"
name = "serde_testing"
version = "0.7.15"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
@@ -10,16 +10,20 @@ readme = "README.md"
keywords = ["serialization"]
build = "build.rs"
[features]
nightly-testing = ["clippy", "serde/nightly-testing", "serde_codegen/nightly-testing"]
[build-dependencies]
syntex = { version = "^0.22.0" }
syntex_syntax = { version = "^0.22.0" }
serde_codegen = { version = "*", path = "../serde_codegen", features = ["with-syntex"] }
serde_codegen = { version = "*", features = ["with-syntex"] }
[dev-dependencies]
num = "^0.1.27"
fnv = "1.0"
rustc-serialize = "^0.3.16"
serde = { version = "*", path = "../serde" }
syntex = "^0.22.0"
serde = "*"
serde_test = "*"
[dependencies]
clippy = { version = "^0.*", optional = true }
[[test]]
name = "test"
@@ -1,6 +1,7 @@
#![feature(test)]
#![cfg_attr(feature = "nightly", feature(plugin))]
#![cfg_attr(feature = "nightly", plugin(clippy))]
extern crate num;
extern crate rustc_serialize;
extern crate serde;
extern crate test;
@@ -1,7 +1,9 @@
use test::Bencher;
use rustc_serialize::{Decoder, Decodable};
use std::error;
use std::fmt;
use rustc_serialize::Decodable;
use serde;
use serde::de::{Deserializer, Deserialize};
use serde::de::Deserialize;
//////////////////////////////////////////////////////////////////////////////
@@ -15,18 +17,34 @@ pub enum Animal {
#[derive(Debug)]
pub enum Error {
EndOfStreamError,
SyntaxError,
EndOfStream,
Syntax,
}
impl serde::de::Error for Error {
fn syntax(_: &str) -> Error { Error::SyntaxError }
fn custom<T: Into<String>>(_: T) -> Error { Error::Syntax }
fn end_of_stream() -> Error { Error::EndOfStreamError }
fn end_of_stream() -> Error { Error::EndOfStream }
fn unknown_field(_: &str) -> Error { Error::SyntaxError }
fn unknown_field(_: &str) -> Error { Error::Syntax }
fn missing_field(_: &'static str) -> Error { Error::SyntaxError }
fn missing_field(_: &'static str) -> Error { Error::Syntax }
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(format!("{:?}", self).as_ref())
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Deserialization Error"
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
//////////////////////////////////////////////////////////////////////////////
@@ -36,12 +54,11 @@ mod decoder {
use super::{Animal, Error};
use super::Animal::{Dog, Frog};
use self::State::{AnimalState, IsizeState, StringState};
enum State {
AnimalState(Animal),
IsizeState(isize),
StringState(String),
Animal(Animal),
Isize(isize),
String(String),
}
pub struct AnimalDecoder {
@@ -53,7 +70,7 @@ mod decoder {
#[inline]
pub fn new(animal: Animal) -> AnimalDecoder {
AnimalDecoder {
stack: vec!(AnimalState(animal)),
stack: vec!(State::Animal(animal)),
}
}
}
@@ -61,35 +78,35 @@ mod decoder {
impl Decoder for AnimalDecoder {
type Error = Error;
fn error(&mut self, _: &str) -> Error { Error::SyntaxError }
fn error(&mut self, _: &str) -> Error { Error::Syntax }
// Primitive types:
fn read_nil(&mut self) -> Result<(), Error> { Err(Error::SyntaxError) }
fn read_usize(&mut self) -> Result<usize, Error> { Err(Error::SyntaxError) }
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::SyntaxError) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::SyntaxError) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::SyntaxError) }
fn read_u8(&mut self) -> Result<u8, Error> { Err(Error::SyntaxError) }
fn read_nil(&mut self) -> Result<(), Error> { Err(Error::Syntax) }
fn read_usize(&mut self) -> Result<usize, Error> { Err(Error::Syntax) }
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::Syntax) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::Syntax) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::Syntax) }
fn read_u8(&mut self) -> Result<u8, Error> { Err(Error::Syntax) }
#[inline]
fn read_isize(&mut self) -> Result<isize, Error> {
match self.stack.pop() {
Some(IsizeState(x)) => Ok(x),
_ => Err(Error::SyntaxError),
Some(State::Isize(x)) => Ok(x),
_ => Err(Error::Syntax),
}
}
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::SyntaxError) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::SyntaxError) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::SyntaxError) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::SyntaxError) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::SyntaxError) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::SyntaxError) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::SyntaxError) }
fn read_char(&mut self) -> Result<char, Error> { Err(Error::SyntaxError) }
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::Syntax) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::Syntax) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::Syntax) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::Syntax) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::Syntax) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::Syntax) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::Syntax) }
fn read_char(&mut self) -> Result<char, Error> { Err(Error::Syntax) }
#[inline]
fn read_str(&mut self) -> Result<String, Error> {
match self.stack.pop() {
Some(StringState(x)) => Ok(x),
_ => Err(Error::SyntaxError),
Some(State::String(x)) => Ok(x),
_ => Err(Error::Syntax),
}
}
@@ -99,15 +116,15 @@ mod decoder {
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
match self.stack.pop() {
Some(AnimalState(animal)) => {
self.stack.push(AnimalState(animal));
Some(State::Animal(animal)) => {
self.stack.push(State::Animal(animal));
if name == "Animal" {
f(self)
} else {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
_ => Err(Error::SyntaxError)
_ => Err(Error::Syntax)
}
}
@@ -116,18 +133,18 @@ mod decoder {
F: FnOnce(&mut AnimalDecoder, usize) -> Result<T, Error>,
{
let name = match self.stack.pop() {
Some(AnimalState(Dog)) => "Dog",
Some(AnimalState(Frog(x0, x1))) => {
self.stack.push(IsizeState(x1));
self.stack.push(StringState(x0));
Some(State::Animal(Dog)) => "Dog",
Some(State::Animal(Frog(x0, x1))) => {
self.stack.push(State::Isize(x1));
self.stack.push(State::String(x0));
"Frog"
}
_ => { return Err(Error::SyntaxError); }
_ => { return Err(Error::Syntax); }
};
let idx = match names.iter().position(|n| *n == name) {
Some(idx) => idx,
None => { return Err(Error::SyntaxError); }
None => { return Err(Error::Syntax); }
};
f(self, idx)
@@ -143,56 +160,56 @@ mod decoder {
fn read_enum_struct_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_struct_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple<T, F>(&mut self, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
// Specialized types:
fn read_option<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder, bool) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
#[inline]
@@ -212,19 +229,19 @@ mod decoder {
fn read_map<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_map_elt_key<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_map_elt_val<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
}
@@ -238,10 +255,10 @@ mod deserializer {
#[derive(Debug)]
enum State {
AnimalState(Animal),
IsizeState(isize),
StrState(&'static str),
StringState(String),
Animal(Animal),
Isize(isize),
Str(&'static str),
String(String),
UnitState,
}
@@ -253,7 +270,7 @@ mod deserializer {
#[inline]
pub fn new(animal: Animal) -> AnimalDeserializer {
AnimalDeserializer {
stack: vec!(State::AnimalState(animal)),
stack: vec!(State::Animal(animal)),
}
}
}
@@ -262,60 +279,60 @@ mod deserializer {
type Error = Error;
#[inline]
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.stack.pop() {
Some(State::IsizeState(value)) => {
Some(State::Isize(value)) => {
visitor.visit_isize(value)
}
Some(State::StringState(value)) => {
Some(State::String(value)) => {
visitor.visit_string(value)
}
Some(State::StrState(value)) => {
Some(State::Str(value)) => {
visitor.visit_str(value)
}
Some(State::UnitState) => {
visitor.visit_unit()
}
Some(_) => {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
None => {
Err(Error::EndOfStreamError)
Err(Error::EndOfStream)
}
}
}
#[inline]
fn visit_enum<V>(&mut self,
fn deserialize_enum<V>(&mut self,
_name: &str,
_variants: &[&str],
mut visitor: V) -> Result<V::Value, Error>
where V: de::EnumVisitor,
{
match self.stack.pop() {
Some(State::AnimalState(Animal::Dog)) => {
Some(State::Animal(Animal::Dog)) => {
self.stack.push(State::UnitState);
self.stack.push(State::StrState("Dog"));
self.stack.push(State::Str("Dog"));
visitor.visit(DogVisitor {
de: self,
})
}
Some(State::AnimalState(Animal::Frog(x0, x1))) => {
self.stack.push(State::IsizeState(x1));
self.stack.push(State::StringState(x0));
self.stack.push(State::StrState("Frog"));
Some(State::Animal(Animal::Frog(x0, x1))) => {
self.stack.push(State::Isize(x1));
self.stack.push(State::String(x0));
self.stack.push(State::Str("Frog"));
visitor.visit(FrogVisitor {
de: self,
state: 0,
})
}
Some(_) => {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
None => {
Err(Error::EndOfStreamError)
Err(Error::EndOfStream)
}
}
}
@@ -387,7 +404,7 @@ mod deserializer {
if self.state == 2 {
Ok(())
} else {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
@@ -415,7 +432,7 @@ fn bench_decoder_dog(b: &mut Bencher) {
#[bench]
fn bench_decoder_frog(b: &mut Bencher) {
b.iter(|| {
let animal = Animal::Frog("Henry".to_string(), 349);
let animal = Animal::Frog("Henry".to_owned(), 349);
let mut d = decoder::AnimalDecoder::new(animal.clone());
let value: Animal = Decodable::decode(&mut d).unwrap();
@@ -439,7 +456,7 @@ fn bench_deserializer_dog(b: &mut Bencher) {
#[bench]
fn bench_deserializer_frog(b: &mut Bencher) {
b.iter(|| {
let animal = Animal::Frog("Henry".to_string(), 349);
let animal = Animal::Frog("Henry".to_owned(), 349);
let mut d = deserializer::AnimalDeserializer::new(animal.clone());
let value: Animal = Deserialize::deserialize(&mut d).unwrap();
@@ -1,4 +1,6 @@
use std::fmt::Debug;
use std::fmt;
use std::error;
use std::collections::HashMap;
use test::Bencher;
@@ -12,22 +14,37 @@ use serde::de::{Deserializer, Deserialize};
#[derive(PartialEq, Debug)]
pub enum Error {
EndOfStream,
SyntaxError,
Syntax,
MissingField,
}
impl serde::de::Error for Error {
fn syntax(_: &str) -> Error { Error::SyntaxError }
fn custom<T: Into<String>>(_: T) -> Error { Error::Syntax }
fn end_of_stream() -> Error { Error::EndOfStream }
fn unknown_field(_: &str) -> Error { Error::SyntaxError }
fn unknown_field(_: &str) -> Error { Error::Syntax }
fn missing_field(_: &'static str) -> Error {
Error::MissingField
}
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(format!("{:?}", self).as_ref())
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Deserialization Error"
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
//////////////////////////////////////////////////////////////////////////////
mod decoder {
@@ -36,11 +53,10 @@ mod decoder {
use rustc_serialize;
use super::Error;
use self::Value::{StringValue, IsizeValue};
enum Value {
StringValue(String),
IsizeValue(isize),
String(String),
Isize(isize),
}
pub struct IsizeDecoder {
@@ -64,37 +80,37 @@ mod decoder {
type Error = Error;
fn error(&mut self, _msg: &str) -> Error {
Error::SyntaxError
Error::Syntax
}
// Primitive types:
fn read_nil(&mut self) -> Result<(), Error> { Err(Error::SyntaxError) }
fn read_usize(&mut self) -> Result<usize, Error> { Err(Error::SyntaxError) }
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::SyntaxError) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::SyntaxError) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::SyntaxError) }
fn read_u8(&mut self) -> Result<u8, Error> { Err(Error::SyntaxError) }
fn read_nil(&mut self) -> Result<(), Error> { Err(Error::Syntax) }
fn read_usize(&mut self) -> Result<usize, Error> { Err(Error::Syntax) }
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::Syntax) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::Syntax) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::Syntax) }
fn read_u8(&mut self) -> Result<u8, Error> { Err(Error::Syntax) }
#[inline]
fn read_isize(&mut self) -> Result<isize, Error> {
match self.stack.pop() {
Some(IsizeValue(x)) => Ok(x),
Some(_) => Err(Error::SyntaxError),
Some(Value::Isize(x)) => Ok(x),
Some(_) => Err(Error::Syntax),
None => Err(Error::EndOfStream),
}
}
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::SyntaxError) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::SyntaxError) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::SyntaxError) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::SyntaxError) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::SyntaxError) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::SyntaxError) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::SyntaxError) }
fn read_char(&mut self) -> Result<char, Error> { Err(Error::SyntaxError) }
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::Syntax) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::Syntax) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::Syntax) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::Syntax) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::Syntax) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::Syntax) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::Syntax) }
fn read_char(&mut self) -> Result<char, Error> { Err(Error::Syntax) }
#[inline]
fn read_str(&mut self) -> Result<String, Error> {
match self.stack.pop() {
Some(StringValue(x)) => Ok(x),
Some(_) => Err(Error::SyntaxError),
Some(Value::String(x)) => Ok(x),
Some(_) => Err(Error::Syntax),
None => Err(Error::EndOfStream),
}
}
@@ -103,86 +119,86 @@ mod decoder {
fn read_enum<T, F>(&mut self, _name: &str, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_struct_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_struct_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple<T, F>(&mut self, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
// Specialized types:
fn read_option<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder, bool) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_seq<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_seq_elt<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
#[inline]
@@ -198,12 +214,12 @@ mod decoder {
{
match self.iter.next() {
Some((key, value)) => {
self.stack.push(IsizeValue(value));
self.stack.push(StringValue(key));
self.stack.push(Value::Isize(value));
self.stack.push(Value::String(key));
f(self)
}
None => {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
}
@@ -230,8 +246,8 @@ mod deserializer {
#[derive(PartialEq, Debug)]
enum State {
StartState,
KeyState(String),
ValueState(isize),
Key(String),
Value(isize),
}
pub struct IsizeDeserializer {
@@ -252,17 +268,17 @@ mod deserializer {
impl de::Deserializer for IsizeDeserializer {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.stack.pop() {
Some(State::StartState) => {
visitor.visit_map(self)
}
Some(State::KeyState(key)) => {
Some(State::Key(key)) => {
visitor.visit_string(key)
}
Some(State::ValueState(value)) => {
Some(State::Value(value)) => {
visitor.visit_isize(value)
}
None => {
@@ -280,8 +296,8 @@ mod deserializer {
{
match self.iter.next() {
Some((key, value)) => {
self.stack.push(State::ValueState(value));
self.stack.push(State::KeyState(key));
self.stack.push(State::Value(value));
self.stack.push(State::Key(key));
Ok(Some(try!(de::Deserialize::deserialize(self))))
}
None => {
@@ -298,7 +314,7 @@ mod deserializer {
fn end(&mut self) -> Result<(), Error> {
match self.iter.next() {
Some(_) => Err(Error::SyntaxError),
Some(_) => Err(Error::Syntax),
None => Ok(()),
}
}
@@ -315,14 +331,14 @@ mod deserializer {
#[inline]
fn next(&mut self) -> Option<Result<de::Token, Error>> {
match self.stack.pop() {
Some(StartState) => {
Some(State::StartState) => {
self.stack.push(KeyOrEndState);
Some(Ok(de::Token::MapStart(self.len)))
}
Some(KeyOrEndState) => {
Some(State::KeyOrEndState) => {
match self.iter.next() {
Some((key, value)) => {
self.stack.push(ValueState(value));
self.stack.push(Value(value));
Some(Ok(de::Token::String(key)))
}
None => {
@@ -331,7 +347,7 @@ mod deserializer {
}
}
}
Some(ValueState(x)) => {
Some(State::Value(x)) => {
self.stack.push(KeyOrEndState);
Some(Ok(de::Token::Isize(x)))
}
@@ -353,24 +369,24 @@ mod deserializer {
#[inline]
fn syntax(&mut self, _token: de::Token, _expected: &[de::TokenKind]) -> Error {
SyntaxError
Syntax
}
#[inline]
fn unexpected_name(&mut self, _token: de::Token) -> Error {
SyntaxError
Syntax
}
#[inline]
fn conversion_error(&mut self, _token: de::Token) -> Error {
SyntaxError
Syntax
}
#[inline]
fn missing_field<
T: de::Deserialize<IsizeDeserializer, Error>
>(&mut self, _field: &'static str) -> Result<T, Error> {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
*/
@@ -399,7 +415,7 @@ fn bench_decoder_000(b: &mut Bencher) {
fn bench_decoder_003(b: &mut Bencher) {
b.iter(|| {
let mut m: HashMap<String, isize> = HashMap::new();
for i in (0 .. 3) {
for i in 0 .. 3 {
m.insert(i.to_string(), i);
}
run_decoder(decoder::IsizeDecoder::new(m.clone()), m)
@@ -410,7 +426,7 @@ fn bench_decoder_003(b: &mut Bencher) {
fn bench_decoder_100(b: &mut Bencher) {
b.iter(|| {
let mut m: HashMap<String, isize> = HashMap::new();
for i in (0 .. 100) {
for i in 0 .. 100 {
m.insert(i.to_string(), i);
}
run_decoder(decoder::IsizeDecoder::new(m.clone()), m)
@@ -439,7 +455,7 @@ fn bench_deserializer_000(b: &mut Bencher) {
fn bench_deserializer_003(b: &mut Bencher) {
b.iter(|| {
let mut m: HashMap<String, isize> = HashMap::new();
for i in (0 .. 3) {
for i in 0 .. 3 {
m.insert(i.to_string(), i);
}
run_deserializer(deserializer::IsizeDeserializer::new(m.clone()), m)
@@ -450,7 +466,7 @@ fn bench_deserializer_003(b: &mut Bencher) {
fn bench_deserializer_100(b: &mut Bencher) {
b.iter(|| {
let mut m: HashMap<String, isize> = HashMap::new();
for i in (0 .. 100) {
for i in 0 .. 100 {
m.insert(i.to_string(), i);
}
run_deserializer(deserializer::IsizeDeserializer::new(m.clone()), m)
@@ -1,10 +1,12 @@
use std::collections::HashMap;
use test::Bencher;
use std::fmt;
use std::error;
use rustc_serialize::{Decoder, Decodable};
use rustc_serialize::Decodable;
use serde;
use serde::de::{Deserializer, Deserialize};
use serde::de::Deserialize;
//////////////////////////////////////////////////////////////////////////////
@@ -27,54 +29,57 @@ pub struct Outer {
#[derive(Debug, PartialEq)]
pub enum Error {
EndOfStream,
SyntaxError,
Syntax,
MissingField,
OtherError,
}
impl serde::de::Error for Error {
fn syntax(_: &str) -> Error { Error::SyntaxError }
fn custom<T: Into<String>>(_: T) -> Error { Error::Syntax }
fn end_of_stream() -> Error { Error::EndOfStream }
fn unknown_field(_: &str) -> Error { Error::SyntaxError }
fn unknown_field(_: &str) -> Error { Error::Syntax }
fn missing_field(_: &'static str) -> Error {
Error::MissingField
}
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(format!("{:?}", self).as_ref())
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Deserialization Error"
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
mod decoder {
use std::collections::HashMap;
use rustc_serialize::Decoder;
use super::{Outer, Inner, Error};
use self::State::{
OuterState,
InnerState,
NullState,
UsizeState,
CharState,
StringState,
FieldState,
VecState,
MapState,
OptionState,
};
#[derive(Debug)]
enum State {
OuterState(Outer),
InnerState(Inner),
NullState,
UsizeState(usize),
CharState(char),
StringState(String),
FieldState(&'static str),
VecState(Vec<Inner>),
MapState(HashMap<String, Option<char>>),
OptionState(bool),
Outer(Outer),
Inner(Inner),
Null,
Usize(usize),
Char(char),
String(String),
Field(&'static str),
Vec(Vec<Inner>),
Map(HashMap<String, Option<char>>),
Option(bool),
}
pub struct OuterDecoder {
@@ -86,7 +91,7 @@ mod decoder {
#[inline]
pub fn new(animal: Outer) -> OuterDecoder {
OuterDecoder {
stack: vec!(OuterState(animal)),
stack: vec!(State::Outer(animal)),
}
}
}
@@ -102,41 +107,41 @@ mod decoder {
#[inline]
fn read_nil(&mut self) -> Result<(), Error> {
match self.stack.pop() {
Some(NullState) => Ok(()),
_ => Err(Error::SyntaxError),
Some(State::Null) => Ok(()),
_ => Err(Error::Syntax),
}
}
#[inline]
fn read_usize(&mut self) -> Result<usize, Error> {
match self.stack.pop() {
Some(UsizeState(value)) => Ok(value),
_ => Err(Error::SyntaxError),
Some(State::Usize(value)) => Ok(value),
_ => Err(Error::Syntax),
}
}
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::SyntaxError) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::SyntaxError) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::SyntaxError) }
fn read_u8(&mut self) -> Result<u8, Error> { Err(Error::SyntaxError) }
fn read_isize(&mut self) -> Result<isize, Error> { Err(Error::SyntaxError) }
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::SyntaxError) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::SyntaxError) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::SyntaxError) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::SyntaxError) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::SyntaxError) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::SyntaxError) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::SyntaxError) }
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::Syntax) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::Syntax) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::Syntax) }
fn read_u8(&mut self) -> Result<u8, Error> { Err(Error::Syntax) }
fn read_isize(&mut self) -> Result<isize, Error> { Err(Error::Syntax) }
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::Syntax) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::Syntax) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::Syntax) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::Syntax) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::Syntax) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::Syntax) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::Syntax) }
#[inline]
fn read_char(&mut self) -> Result<char, Error> {
match self.stack.pop() {
Some(CharState(c)) => Ok(c),
_ => Err(Error::SyntaxError),
Some(State::Char(c)) => Ok(c),
_ => Err(Error::Syntax),
}
}
#[inline]
fn read_str(&mut self) -> Result<String, Error> {
match self.stack.pop() {
Some(StringState(value)) => Ok(value),
_ => Err(Error::SyntaxError),
Some(State::String(value)) => Ok(value),
_ => Err(Error::Syntax),
}
}
@@ -144,31 +149,31 @@ mod decoder {
fn read_enum<T, F>(&mut self, _name: &str, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_struct_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
#[inline]
@@ -176,31 +181,31 @@ mod decoder {
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
match self.stack.pop() {
Some(OuterState(Outer { inner })) => {
Some(State::Outer(Outer { inner })) => {
if s_name == "Outer" {
self.stack.push(VecState(inner));
self.stack.push(FieldState("inner"));
self.stack.push(State::Vec(inner));
self.stack.push(State::Field("inner"));
f(self)
} else {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
Some(InnerState(Inner { a: (), b, c })) => {
Some(State::Inner(Inner { a: (), b, c })) => {
if s_name == "Inner" {
self.stack.push(MapState(c));
self.stack.push(FieldState("c"));
self.stack.push(State::Map(c));
self.stack.push(State::Field("c"));
self.stack.push(UsizeState(b));
self.stack.push(FieldState("b"));
self.stack.push(State::Usize(b));
self.stack.push(State::Field("b"));
self.stack.push(NullState);
self.stack.push(FieldState("a"));
self.stack.push(State::Null);
self.stack.push(State::Field("a"));
f(self)
} else {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
_ => Err(Error::SyntaxError),
_ => Err(Error::Syntax),
}
}
#[inline]
@@ -208,39 +213,39 @@ mod decoder {
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
match self.stack.pop() {
Some(FieldState(name)) => {
Some(State::Field(name)) => {
if f_name == name {
f(self)
} else {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
_ => Err(Error::SyntaxError)
_ => Err(Error::Syntax)
}
}
fn read_tuple<T, F>(&mut self, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
// Specialized types:
@@ -249,8 +254,8 @@ mod decoder {
F: FnOnce(&mut OuterDecoder, bool) -> Result<T, Error>,
{
match self.stack.pop() {
Some(OptionState(b)) => f(self, b),
_ => Err(Error::SyntaxError),
Some(State::Option(b)) => f(self, b),
_ => Err(Error::Syntax),
}
}
@@ -259,14 +264,14 @@ mod decoder {
F: FnOnce(&mut OuterDecoder, usize) -> Result<T, Error>,
{
match self.stack.pop() {
Some(VecState(value)) => {
Some(State::Vec(value)) => {
let len = value.len();
for inner in value.into_iter().rev() {
self.stack.push(InnerState(inner));
self.stack.push(State::Inner(inner));
}
f(self, len)
}
_ => Err(Error::SyntaxError)
_ => Err(Error::Syntax)
}
}
#[inline]
@@ -281,23 +286,23 @@ mod decoder {
F: FnOnce(&mut OuterDecoder, usize) -> Result<T, Error>,
{
match self.stack.pop() {
Some(MapState(map)) => {
Some(State::Map(map)) => {
let len = map.len();
for (key, value) in map {
match value {
Some(c) => {
self.stack.push(CharState(c));
self.stack.push(OptionState(true));
self.stack.push(State::Char(c));
self.stack.push(State::Option(true));
}
None => {
self.stack.push(OptionState(false));
self.stack.push(State::Option(false));
}
}
self.stack.push(StringState(key));
self.stack.push(State::String(key));
}
f(self, len)
}
_ => Err(Error::SyntaxError),
_ => Err(Error::Syntax),
}
}
#[inline]
@@ -328,16 +333,16 @@ mod deserializer {
#[derive(Debug)]
enum State {
OuterState(Outer),
InnerState(Inner),
StrState(&'static str),
NullState,
UsizeState(usize),
CharState(char),
StringState(String),
OptionState(bool),
VecState(Vec<Inner>),
MapState(HashMap<String, Option<char>>),
Outer(Outer),
Inner(Inner),
Str(&'static str),
Null,
Usize(usize),
Char(char),
String(String),
Option(bool),
Vec(Vec<Inner>),
Map(HashMap<String, Option<char>>),
}
pub struct OuterDeserializer {
@@ -348,7 +353,7 @@ mod deserializer {
#[inline]
pub fn new(outer: Outer) -> OuterDeserializer {
OuterDeserializer {
stack: vec!(State::OuterState(outer)),
stack: vec!(State::Outer(outer)),
}
}
}
@@ -356,81 +361,81 @@ mod deserializer {
impl de::Deserializer for OuterDeserializer {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.stack.pop() {
Some(State::VecState(value)) => {
Some(State::Vec(value)) => {
visitor.visit_seq(OuterSeqVisitor {
de: self,
iter: value.into_iter(),
})
}
Some(State::MapState(value)) => {
Some(State::Map(value)) => {
visitor.visit_map(MapVisitor {
de: self,
iter: value.into_iter(),
})
}
Some(State::NullState) => {
Some(State::Null) => {
visitor.visit_unit()
}
Some(State::UsizeState(x)) => {
Some(State::Usize(x)) => {
visitor.visit_usize(x)
}
Some(State::CharState(x)) => {
Some(State::Char(x)) => {
visitor.visit_char(x)
}
Some(State::StrState(x)) => {
Some(State::Str(x)) => {
visitor.visit_str(x)
}
Some(State::StringState(x)) => {
Some(State::String(x)) => {
visitor.visit_string(x)
}
Some(State::OptionState(false)) => {
Some(State::Option(false)) => {
visitor.visit_none()
}
Some(State::OptionState(true)) => {
Some(State::Option(true)) => {
visitor.visit_some(self)
}
Some(_) => Err(Error::SyntaxError),
Some(_) => Err(Error::Syntax),
None => Err(Error::EndOfStream),
}
}
fn visit_struct<V>(&mut self,
fn deserialize_struct<V>(&mut self,
name: &str,
_fields: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.stack.pop() {
Some(State::OuterState(Outer { inner })) => {
Some(State::Outer(Outer { inner })) => {
if name != "Outer" {
return Err(Error::SyntaxError);
return Err(Error::Syntax);
}
self.stack.push(State::VecState(inner));
self.stack.push(State::StrState("inner"));
self.stack.push(State::Vec(inner));
self.stack.push(State::Str("inner"));
visitor.visit_map(OuterMapVisitor {
de: self,
state: 0,
})
}
Some(State::InnerState(Inner { a: (), b, c })) => {
Some(State::Inner(Inner { a: (), b, c })) => {
if name != "Inner" {
return Err(Error::SyntaxError);
return Err(Error::Syntax);
}
self.stack.push(State::MapState(c));
self.stack.push(State::StrState("c"));
self.stack.push(State::Map(c));
self.stack.push(State::Str("c"));
self.stack.push(State::UsizeState(b));
self.stack.push(State::StrState("b"));
self.stack.push(State::Usize(b));
self.stack.push(State::Str("b"));
self.stack.push(State::NullState);
self.stack.push(State::StrState("a"));
self.stack.push(State::Null);
self.stack.push(State::Str("a"));
visitor.visit_map(InnerMapVisitor {
de: self,
@@ -438,7 +443,7 @@ mod deserializer {
})
}
_ => {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
}
@@ -476,7 +481,7 @@ mod deserializer {
if self.state == 1 {
Ok(())
} else {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
@@ -499,7 +504,7 @@ mod deserializer {
{
match self.iter.next() {
Some(value) => {
self.de.stack.push(State::InnerState(value));
self.de.stack.push(State::Inner(value));
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
None => {
@@ -510,7 +515,7 @@ mod deserializer {
fn end(&mut self) -> Result<(), Error> {
match self.iter.next() {
Some(_) => Err(Error::SyntaxError),
Some(_) => Err(Error::Syntax),
None => Ok(()),
}
}
@@ -552,7 +557,7 @@ mod deserializer {
if self.state == 3 {
Ok(())
} else {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
@@ -575,14 +580,14 @@ mod deserializer {
{
match self.iter.next() {
Some((key, Some(value))) => {
self.de.stack.push(State::CharState(value));
self.de.stack.push(State::OptionState(true));
self.de.stack.push(State::StringState(key));
self.de.stack.push(State::Char(value));
self.de.stack.push(State::Option(true));
self.de.stack.push(State::String(key));
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
Some((key, None)) => {
self.de.stack.push(State::OptionState(false));
self.de.stack.push(State::StringState(key));
self.de.stack.push(State::Option(false));
self.de.stack.push(State::String(key));
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
None => {
@@ -599,7 +604,7 @@ mod deserializer {
fn end(&mut self) -> Result<(), Error> {
match self.iter.next() {
Some(_) => Err(Error::SyntaxError),
Some(_) => Err(Error::Syntax),
None => Ok(()),
}
}
@@ -614,7 +619,7 @@ mod deserializer {
fn bench_decoder_0_0(b: &mut Bencher) {
b.iter(|| {
let mut map = HashMap::new();
map.insert("abc".to_string(), Some('c'));
map.insert("abc".to_owned(), Some('c'));
let outer = Outer {
inner: vec!(),
@@ -653,11 +658,11 @@ fn bench_decoder_1_0(b: &mut Bencher) {
fn bench_decoder_1_5(b: &mut Bencher) {
b.iter(|| {
let mut map = HashMap::new();
map.insert("1".to_string(), Some('a'));
map.insert("2".to_string(), None);
map.insert("3".to_string(), Some('b'));
map.insert("4".to_string(), None);
map.insert("5".to_string(), Some('c'));
map.insert("1".to_owned(), Some('a'));
map.insert("2".to_owned(), None);
map.insert("3".to_owned(), Some('b'));
map.insert("4".to_owned(), None);
map.insert("5".to_owned(), Some('c'));
let outer = Outer {
inner: vec!(
@@ -716,11 +721,11 @@ fn bench_deserializer_1_0(b: &mut Bencher) {
fn bench_deserializer_1_5(b: &mut Bencher) {
b.iter(|| {
let mut map = HashMap::new();
map.insert("1".to_string(), Some('a'));
map.insert("2".to_string(), None);
map.insert("3".to_string(), Some('b'));
map.insert("4".to_string(), None);
map.insert("5".to_string(), Some('c'));
map.insert("1".to_owned(), Some('a'));
map.insert("2".to_owned(), None);
map.insert("3".to_owned(), Some('b'));
map.insert("4".to_owned(), None);
map.insert("5".to_owned(), Some('c'));
let outer = Outer {
inner: vec!(
@@ -1,4 +1,6 @@
use std::fmt::Debug;
use std::fmt;
use std::error;
use test::Bencher;
use rustc_serialize::{Decoder, Decodable};
@@ -10,20 +12,35 @@ use serde::de::{Deserializer, Deserialize};
#[derive(PartialEq, Debug)]
pub enum Error {
EndOfStreamError,
SyntaxError,
EndOfStream,
Syntax,
}
impl serde::de::Error for Error {
fn syntax(_: &str) -> Error { Error::SyntaxError }
fn custom<T: Into<String>>(_: T) -> Error { Error::Syntax }
fn end_of_stream() -> Error { Error::EndOfStreamError }
fn end_of_stream() -> Error { Error::EndOfStream }
fn unknown_field(_: &str) -> Error { Error::SyntaxError }
fn unknown_field(_: &str) -> Error { Error::Syntax }
fn missing_field(_: &'static str) -> Error { Error::SyntaxError }
fn missing_field(_: &'static str) -> Error { Error::Syntax }
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(format!("{:?}", self).as_ref())
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Deserialization Error"
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
//////////////////////////////////////////////////////////////////////////////
mod decoder {
@@ -50,104 +67,104 @@ mod decoder {
impl rustc_serialize::Decoder for UsizeDecoder {
type Error = Error;
fn error(&mut self, _: &str) -> Error { Error::SyntaxError }
fn error(&mut self, _: &str) -> Error { Error::Syntax }
// Primitive types:
fn read_nil(&mut self) -> Result<(), Error> { Err(Error::SyntaxError) }
fn read_nil(&mut self) -> Result<(), Error> { Err(Error::Syntax) }
#[inline]
fn read_usize(&mut self) -> Result<usize, Error> {
match self.iter.next() {
Some(value) => Ok(value),
None => Err(Error::EndOfStreamError),
None => Err(Error::EndOfStream),
}
}
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::SyntaxError) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::SyntaxError) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::SyntaxError) }
fn read_u8(&mut self) -> Result<u8, Error> { Err(Error::SyntaxError) }
fn read_isize(&mut self) -> Result<isize, Error> { Err(Error::SyntaxError) }
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::SyntaxError) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::SyntaxError) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::SyntaxError) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::SyntaxError) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::SyntaxError) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::SyntaxError) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::SyntaxError) }
fn read_char(&mut self) -> Result<char, Error> { Err(Error::SyntaxError) }
fn read_str(&mut self) -> Result<String, Error> { Err(Error::SyntaxError) }
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::Syntax) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::Syntax) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::Syntax) }
fn read_u8(&mut self) -> Result<u8, Error> { Err(Error::Syntax) }
fn read_isize(&mut self) -> Result<isize, Error> { Err(Error::Syntax) }
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::Syntax) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::Syntax) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::Syntax) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::Syntax) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::Syntax) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::Syntax) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::Syntax) }
fn read_char(&mut self) -> Result<char, Error> { Err(Error::Syntax) }
fn read_str(&mut self) -> Result<String, Error> { Err(Error::Syntax) }
// Compound types:
fn read_enum<T, F>(&mut self, _name: &str, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_struct_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_struct_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple<T, F>(&mut self, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
// Specialized types:
fn read_option<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder, bool) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
#[inline]
@@ -167,19 +184,19 @@ mod decoder {
fn read_map<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_map_elt_key<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_map_elt_val<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
@@ -202,105 +219,105 @@ mod decoder {
impl rustc_serialize::Decoder for U8Decoder {
type Error = Error;
fn error(&mut self, _: &str) -> Error { Error::SyntaxError }
fn error(&mut self, _: &str) -> Error { Error::Syntax }
// Primitive types:
fn read_nil(&mut self) -> Result<(), Error> { Err(Error::SyntaxError) }
fn read_usize(&mut self) -> Result<usize, Error> { Err(Error::SyntaxError) }
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::SyntaxError) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::SyntaxError) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::SyntaxError) }
fn read_nil(&mut self) -> Result<(), Error> { Err(Error::Syntax) }
fn read_usize(&mut self) -> Result<usize, Error> { Err(Error::Syntax) }
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::Syntax) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::Syntax) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::Syntax) }
#[inline]
fn read_u8(&mut self) -> Result<u8, Error> {
match self.iter.next() {
Some(value) => Ok(value),
None => Err(Error::EndOfStreamError),
None => Err(Error::EndOfStream),
}
}
#[inline]
fn read_isize(&mut self) -> Result<isize, Error> { Err(Error::SyntaxError) }
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::SyntaxError) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::SyntaxError) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::SyntaxError) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::SyntaxError) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::SyntaxError) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::SyntaxError) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::SyntaxError) }
fn read_char(&mut self) -> Result<char, Error> { Err(Error::SyntaxError) }
fn read_str(&mut self) -> Result<String, Error> { Err(Error::SyntaxError) }
fn read_isize(&mut self) -> Result<isize, Error> { Err(Error::Syntax) }
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::Syntax) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::Syntax) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::Syntax) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::Syntax) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::Syntax) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::Syntax) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::Syntax) }
fn read_char(&mut self) -> Result<char, Error> { Err(Error::Syntax) }
fn read_str(&mut self) -> Result<String, Error> { Err(Error::Syntax) }
// Compound types:
fn read_enum<T, F>(&mut self, _name: &str, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_struct_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_struct_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple<T, F>(&mut self, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
// Specialized types:
fn read_option<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder, bool) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
#[inline]
@@ -320,19 +337,19 @@ mod decoder {
fn read_map<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_map_elt_key<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_map_elt_val<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
}
@@ -349,9 +366,9 @@ mod deserializer {
#[derive(PartialEq, Debug)]
enum State {
StartState,
SepOrEndState,
EndState,
Start,
SepOrEnd,
End,
}
pub struct Deserializer<A> {
@@ -366,7 +383,7 @@ mod deserializer {
pub fn new(values: Vec<A>) -> Deserializer<A> {
let len = values.len();
Deserializer {
state: State::StartState,
state: State::Start,
iter: values.into_iter(),
len: len,
value: None,
@@ -378,19 +395,19 @@ mod deserializer {
type Error = Error;
#[inline]
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.state {
State::StartState => {
self.state = State::SepOrEndState;
State::Start => {
self.state = State::SepOrEnd;
visitor.visit_seq(self)
}
State::SepOrEndState => {
State::SepOrEnd => {
visitor.visit_usize(self.value.take().unwrap())
}
State::EndState => {
Err(Error::EndOfStreamError)
State::End => {
Err(Error::EndOfStream)
}
}
}
@@ -410,7 +427,7 @@ mod deserializer {
Ok(Some(try!(de::Deserialize::deserialize(self))))
}
None => {
self.state = State::EndState;
self.state = State::End;
Ok(None)
}
}
@@ -419,9 +436,9 @@ mod deserializer {
#[inline]
fn end(&mut self) -> Result<(), Error> {
match self.iter.next() {
Some(_) => Err(Error::SyntaxError),
Some(_) => Err(Error::Syntax),
None => {
self.state = State::EndState;
self.state = State::End;
Ok(())
}
}
@@ -437,19 +454,19 @@ mod deserializer {
type Error = Error;
#[inline]
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.state {
State::StartState => {
self.state = State::SepOrEndState;
State::Start => {
self.state = State::SepOrEnd;
visitor.visit_seq(self)
}
State::SepOrEndState => {
State::SepOrEnd => {
visitor.visit_u8(self.value.take().unwrap())
}
State::EndState => {
Err(Error::EndOfStreamError)
State::End => {
Err(Error::EndOfStream)
}
}
}
@@ -469,7 +486,7 @@ mod deserializer {
Ok(Some(try!(de::Deserialize::deserialize(self))))
}
None => {
self.state = State::EndState;
self.state = State::End;
Ok(None)
}
}
@@ -478,9 +495,9 @@ mod deserializer {
#[inline]
fn end(&mut self) -> Result<(), Error> {
match self.iter.next() {
Some(_) => Err(Error::SyntaxError),
Some(_) => Err(Error::Syntax),
None => {
self.state = State::EndState;
self.state = State::End;
Ok(())
}
}
+1 -6
View File
@@ -1,4 +1,3 @@
extern crate syntex;
extern crate serde_codegen;
use std::env;
@@ -13,10 +12,6 @@ fn main() {
] {
let src = Path::new(src);
let dst = Path::new(&out_dir).join(dst);
let mut registry = syntex::Registry::new();
serde_codegen::register(&mut registry);
registry.expand("", &src, &dst).unwrap();
serde_codegen::expand(&src, &dst).unwrap();
}
}
@@ -5,7 +5,7 @@ macro_rules! declare_ser_tests {
#[test]
fn $name() {
$(
::token::assert_ser_tokens(&$value, $tokens);
assert_ser_tokens(&$value, $tokens);
)+
}
)+
@@ -62,6 +62,14 @@ macro_rules! hashset {
$(set.insert($value);)+
set
}
};
($hasher:ident @ $($value:expr),+) => {
{
use std::hash::BuildHasherDefault;
let mut set = HashSet::with_hasher(BuildHasherDefault::<$hasher>::default());
$(set.insert($value);)+
set
}
}
}
@@ -75,5 +83,13 @@ macro_rules! hashmap {
$(map.insert($key, $value);)+
map
}
};
($hasher:ident @ $($key:expr => $value:expr),+) => {
{
use std::hash::BuildHasherDefault;
let mut map = HashMap::with_hasher(BuildHasherDefault::<$hasher>::default());
$(map.insert($key, $value);)+
map
}
}
}
+4
View File
@@ -0,0 +1,4 @@
#![cfg_attr(feature = "nightly", feature(plugin))]
#![cfg_attr(feature = "nightly", plugin(clippy))]
include!(concat!(env!("OUT_DIR"), "/test.rs"));
@@ -1,10 +1,9 @@
#[macro_use]
mod macros;
mod token;
mod test_annotations;
mod test_bytes;
mod test_de;
mod test_gen;
mod test_macros;
mod test_ser;
+976
View File
@@ -0,0 +1,976 @@
extern crate serde;
use self::serde::{Serialize, Serializer, Deserialize, Deserializer};
extern crate serde_test;
use self::serde_test::{
Error,
Token,
assert_tokens,
assert_ser_tokens,
assert_de_tokens,
assert_de_tokens_error
};
trait MyDefault: Sized {
fn my_default() -> Self;
}
trait ShouldSkip: Sized {
fn should_skip(&self) -> bool;
}
trait SerializeWith: Sized {
fn serialize_with<S>(&self, ser: &mut S) -> Result<(), S::Error>
where S: Serializer;
}
trait DeserializeWith: Sized {
fn deserialize_with<D>(de: &mut D) -> Result<Self, D::Error>
where D: Deserializer;
}
impl MyDefault for i32 {
fn my_default() -> Self { 123 }
}
impl ShouldSkip for i32 {
fn should_skip(&self) -> bool { *self == 123 }
}
impl SerializeWith for i32 {
fn serialize_with<S>(&self, ser: &mut S) -> Result<(), S::Error>
where S: Serializer
{
if *self == 123 {
true.serialize(ser)
} else {
false.serialize(ser)
}
}
}
impl DeserializeWith for i32 {
fn deserialize_with<D>(de: &mut D) -> Result<Self, D::Error>
where D: Deserializer
{
if try!(Deserialize::deserialize(de)) {
Ok(123)
} else {
Ok(2)
}
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct DefaultStruct<A, B, C, D, E>
where C: MyDefault,
E: MyDefault,
{
a1: A,
#[serde(default)]
a2: B,
#[serde(default="MyDefault::my_default")]
a3: C,
#[serde(skip_deserializing)]
a4: D,
#[serde(skip_deserializing, default="MyDefault::my_default")]
a5: E,
}
#[test]
fn test_default_struct() {
assert_de_tokens(
&DefaultStruct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 },
&[
Token::StructStart("DefaultStruct", Some(3)),
Token::StructSep,
Token::Str("a1"),
Token::I32(1),
Token::StructSep,
Token::Str("a2"),
Token::I32(2),
Token::StructSep,
Token::Str("a3"),
Token::I32(3),
Token::StructSep,
Token::Str("a4"),
Token::I32(4),
Token::StructSep,
Token::Str("a5"),
Token::I32(5),
Token::StructEnd,
]
);
assert_de_tokens(
&DefaultStruct { a1: 1, a2: 0, a3: 123, a4: 0, a5: 123 },
&[
Token::StructStart("DefaultStruct", Some(1)),
Token::StructSep,
Token::Str("a1"),
Token::I32(1),
Token::StructEnd,
]
);
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum DefaultEnum<A, B, C, D, E>
where C: MyDefault,
E: MyDefault
{
Struct {
a1: A,
#[serde(default)]
a2: B,
#[serde(default="MyDefault::my_default")]
a3: C,
#[serde(skip_deserializing)]
a4: D,
#[serde(skip_deserializing, default="MyDefault::my_default")]
a5: E,
}
}
#[test]
fn test_default_enum() {
assert_de_tokens(
&DefaultEnum::Struct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 },
&[
Token::EnumMapStart("DefaultEnum", "Struct", Some(5)),
Token::EnumMapSep,
Token::Str("a1"),
Token::I32(1),
Token::EnumMapSep,
Token::Str("a2"),
Token::I32(2),
Token::EnumMapSep,
Token::Str("a3"),
Token::I32(3),
Token::EnumMapSep,
Token::Str("a4"),
Token::I32(4),
Token::EnumMapSep,
Token::Str("a5"),
Token::I32(5),
Token::EnumMapEnd,
]
);
assert_de_tokens(
&DefaultEnum::Struct { a1: 1, a2: 0, a3: 123, a4: 0, a5: 123 },
&[
Token::EnumMapStart("DefaultEnum", "Struct", Some(5)),
Token::EnumMapSep,
Token::Str("a1"),
Token::I32(1),
Token::EnumMapEnd,
]
);
}
// Does not implement std::default::Default.
#[derive(Debug, PartialEq, Deserialize)]
struct NoStdDefault(i8);
impl MyDefault for NoStdDefault {
fn my_default() -> Self {
NoStdDefault(123)
}
}
#[derive(Debug, PartialEq, Deserialize)]
struct ContainsNoStdDefault<A: MyDefault> {
#[serde(default="MyDefault::my_default")]
a: A,
}
// Tests that a struct field does not need to implement std::default::Default if
// it is annotated with `default=...`.
#[test]
fn test_no_std_default() {
assert_de_tokens(
&ContainsNoStdDefault { a: NoStdDefault(123) },
&[
Token::StructStart("ContainsNoStdDefault", Some(1)),
Token::StructEnd,
]
);
assert_de_tokens(
&ContainsNoStdDefault { a: NoStdDefault(8) },
&[
Token::StructStart("ContainsNoStdDefault", Some(1)),
Token::StructSep,
Token::Str("a"),
Token::StructNewType("NoStdDefault"),
Token::I8(8),
Token::StructEnd,
]
);
}
// Does not implement Deserialize.
#[derive(Debug, PartialEq)]
struct NotDeserializeStruct(i8);
impl Default for NotDeserializeStruct {
fn default() -> Self {
NotDeserializeStruct(123)
}
}
impl DeserializeWith for NotDeserializeStruct {
fn deserialize_with<D>(_: &mut D) -> Result<Self, D::Error>
where D: Deserializer
{
panic!()
}
}
// Does not implement Deserialize.
#[derive(Debug, PartialEq)]
enum NotDeserializeEnum { Trouble }
impl MyDefault for NotDeserializeEnum {
fn my_default() -> Self {
NotDeserializeEnum::Trouble
}
}
#[derive(Debug, PartialEq, Deserialize)]
struct ContainsNotDeserialize<A, B, C: DeserializeWith, E: MyDefault> {
#[serde(skip_deserializing)]
a: A,
#[serde(skip_deserializing, default)]
b: B,
#[serde(deserialize_with="DeserializeWith::deserialize_with", default)]
c: C,
#[serde(skip_deserializing, default="MyDefault::my_default")]
e: E,
}
// Tests that a struct field does not need to implement Deserialize if it is
// annotated with skip_deserializing, whether using the std Default or a
// custom default.
#[test]
fn test_elt_not_deserialize() {
assert_de_tokens(
&ContainsNotDeserialize {
a: NotDeserializeStruct(123),
b: NotDeserializeStruct(123),
c: NotDeserializeStruct(123),
e: NotDeserializeEnum::Trouble,
},
&[
Token::StructStart("ContainsNotDeserialize", Some(3)),
Token::StructEnd,
]
);
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct DenyUnknown {
a1: i32,
}
#[test]
fn test_ignore_unknown() {
// 'Default' allows unknown. Basic smoke test of ignore...
assert_de_tokens(
&DefaultStruct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 },
&[
Token::StructStart("DefaultStruct", Some(5)),
Token::StructSep,
Token::Str("whoops1"),
Token::I32(2),
Token::StructSep,
Token::Str("a1"),
Token::I32(1),
Token::StructSep,
Token::Str("whoops2"),
Token::SeqStart(Some(1)),
Token::SeqSep,
Token::I32(2),
Token::SeqEnd,
Token::StructSep,
Token::Str("a2"),
Token::I32(2),
Token::StructSep,
Token::Str("whoops3"),
Token::I32(2),
Token::StructSep,
Token::Str("a3"),
Token::I32(3),
Token::StructEnd,
]
);
assert_de_tokens_error::<DenyUnknown>(
&[
Token::StructStart("DenyUnknown", Some(2)),
Token::StructSep,
Token::Str("a1"),
Token::I32(1),
Token::StructSep,
Token::Str("whoops"),
],
Error::UnknownField("whoops".to_owned())
);
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename="Superhero")]
struct RenameStruct {
a1: i32,
#[serde(rename="a3")]
a2: i32,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename(serialize="SuperheroSer", deserialize="SuperheroDe"))]
struct RenameStructSerializeDeserialize {
a1: i32,
#[serde(rename(serialize="a4", deserialize="a5"))]
a2: i32,
}
#[test]
fn test_rename_struct() {
assert_tokens(
&RenameStruct { a1: 1, a2: 2 },
&[
Token::StructStart("Superhero", Some(2)),
Token::StructSep,
Token::Str("a1"),
Token::I32(1),
Token::StructSep,
Token::Str("a3"),
Token::I32(2),
Token::StructEnd,
]
);
assert_ser_tokens(
&RenameStructSerializeDeserialize { a1: 1, a2: 2 },
&[
Token::StructStart("SuperheroSer", Some(2)),
Token::StructSep,
Token::Str("a1"),
Token::I32(1),
Token::StructSep,
Token::Str("a4"),
Token::I32(2),
Token::StructEnd,
]
);
assert_de_tokens(
&RenameStructSerializeDeserialize { a1: 1, a2: 2 },
&[
Token::StructStart("SuperheroDe", Some(2)),
Token::StructSep,
Token::Str("a1"),
Token::I32(1),
Token::StructSep,
Token::Str("a5"),
Token::I32(2),
Token::StructEnd,
]
);
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename="Superhero")]
enum RenameEnum {
#[serde(rename="bruce_wayne")]
Batman,
#[serde(rename="clark_kent")]
Superman(i8),
#[serde(rename="diana_prince")]
WonderWoman(i8, i8),
#[serde(rename="barry_allan")]
Flash {
#[serde(rename="b")]
a: i32,
},
}
#[derive(Debug, PartialEq, Deserialize, Serialize)]
#[serde(rename(serialize="SuperheroSer", deserialize="SuperheroDe"))]
enum RenameEnumSerializeDeserialize<A> {
#[serde(rename(serialize="dick_grayson", deserialize="jason_todd"))]
Robin {
a: i8,
#[serde(rename(serialize="c"))]
#[serde(rename(deserialize="d"))]
b: A,
},
}
#[test]
fn test_rename_enum() {
assert_tokens(
&RenameEnum::Batman,
&[
Token::EnumUnit("Superhero", "bruce_wayne"),
]
);
assert_tokens(
&RenameEnum::Superman(0),
&[
Token::EnumNewType("Superhero", "clark_kent"),
Token::I8(0),
]
);
assert_tokens(
&RenameEnum::WonderWoman(0, 1),
&[
Token::EnumSeqStart("Superhero", "diana_prince", Some(2)),
Token::EnumSeqSep,
Token::I8(0),
Token::EnumSeqSep,
Token::I8(1),
Token::EnumSeqEnd,
]
);
assert_tokens(
&RenameEnum::Flash { a: 1 },
&[
Token::EnumMapStart("Superhero", "barry_allan", Some(1)),
Token::EnumMapSep,
Token::Str("b"),
Token::I32(1),
Token::EnumMapEnd,
]
);
assert_ser_tokens(
&RenameEnumSerializeDeserialize::Robin {
a: 0,
b: String::new(),
},
&[
Token::EnumMapStart("SuperheroSer", "dick_grayson", Some(2)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(0),
Token::EnumMapSep,
Token::Str("c"),
Token::Str(""),
Token::EnumMapEnd,
]
);
assert_de_tokens(
&RenameEnumSerializeDeserialize::Robin {
a: 0,
b: String::new(),
},
&[
Token::EnumMapStart("SuperheroDe", "jason_todd", Some(2)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(0),
Token::EnumMapSep,
Token::Str("d"),
Token::Str(""),
Token::EnumMapEnd,
]
);
}
#[derive(Debug, PartialEq, Serialize)]
struct SkipSerializingStruct<'a, B, C> where C: ShouldSkip {
a: &'a i8,
#[serde(skip_serializing)]
b: B,
#[serde(skip_serializing_if="ShouldSkip::should_skip")]
c: C,
}
#[test]
fn test_skip_serializing_struct() {
let a = 1;
assert_ser_tokens(
&SkipSerializingStruct {
a: &a,
b: 2,
c: 3,
},
&[
Token::StructStart("SkipSerializingStruct", Some(2)),
Token::StructSep,
Token::Str("a"),
Token::I8(1),
Token::StructSep,
Token::Str("c"),
Token::I32(3),
Token::StructEnd,
]
);
assert_ser_tokens(
&SkipSerializingStruct {
a: &a,
b: 2,
c: 123,
},
&[
Token::StructStart("SkipSerializingStruct", Some(1)),
Token::StructSep,
Token::Str("a"),
Token::I8(1),
Token::StructEnd,
]
);
}
#[derive(Debug, PartialEq, Serialize)]
enum SkipSerializingEnum<'a, B, C> where C: ShouldSkip {
Struct {
a: &'a i8,
#[serde(skip_serializing)]
_b: B,
#[serde(skip_serializing_if="ShouldSkip::should_skip")]
c: C,
}
}
#[test]
fn test_skip_serializing_enum() {
let a = 1;
assert_ser_tokens(
&SkipSerializingEnum::Struct {
a: &a,
_b: 2,
c: 3,
},
&[
Token::EnumMapStart("SkipSerializingEnum", "Struct", Some(2)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::EnumMapSep,
Token::Str("c"),
Token::I32(3),
Token::EnumMapEnd,
]
);
assert_ser_tokens(
&SkipSerializingEnum::Struct {
a: &a,
_b: 2,
c: 123,
},
&[
Token::EnumMapStart("SkipSerializingEnum", "Struct", Some(1)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::EnumMapEnd,
]
);
}
#[derive(Debug, PartialEq)]
struct NotSerializeStruct(i8);
#[derive(Debug, PartialEq)]
enum NotSerializeEnum { Trouble }
impl SerializeWith for NotSerializeEnum {
fn serialize_with<S>(&self, ser: &mut S) -> Result<(), S::Error>
where S: Serializer
{
"trouble".serialize(ser)
}
}
#[derive(Debug, PartialEq, Serialize)]
struct ContainsNotSerialize<'a, B, C, D> where B: 'a, D: SerializeWith {
a: &'a Option<i8>,
#[serde(skip_serializing)]
b: &'a B,
#[serde(skip_serializing)]
c: Option<C>,
#[serde(serialize_with="SerializeWith::serialize_with")]
d: D,
}
#[test]
fn test_elt_not_serialize() {
let a = 1;
assert_ser_tokens(
&ContainsNotSerialize {
a: &Some(a),
b: &NotSerializeStruct(2),
c: Some(NotSerializeEnum::Trouble),
d: NotSerializeEnum::Trouble,
},
&[
Token::StructStart("ContainsNotSerialize", Some(2)),
Token::StructSep,
Token::Str("a"),
Token::Option(true),
Token::I8(1),
Token::StructSep,
Token::Str("d"),
Token::Str("trouble"),
Token::StructEnd,
]
);
}
#[derive(Debug, PartialEq, Serialize)]
struct SerializeWithStruct<'a, B> where B: SerializeWith {
a: &'a i8,
#[serde(serialize_with="SerializeWith::serialize_with")]
b: B,
}
#[test]
fn test_serialize_with_struct() {
let a = 1;
assert_ser_tokens(
&SerializeWithStruct {
a: &a,
b: 2,
},
&[
Token::StructStart("SerializeWithStruct", Some(2)),
Token::StructSep,
Token::Str("a"),
Token::I8(1),
Token::StructSep,
Token::Str("b"),
Token::Bool(false),
Token::StructEnd,
]
);
assert_ser_tokens(
&SerializeWithStruct {
a: &a,
b: 123,
},
&[
Token::StructStart("SerializeWithStruct", Some(2)),
Token::StructSep,
Token::Str("a"),
Token::I8(1),
Token::StructSep,
Token::Str("b"),
Token::Bool(true),
Token::StructEnd,
]
);
}
#[derive(Debug, PartialEq, Serialize)]
enum SerializeWithEnum<'a, B> where B: SerializeWith {
Struct {
a: &'a i8,
#[serde(serialize_with="SerializeWith::serialize_with")]
b: B,
}
}
#[test]
fn test_serialize_with_enum() {
let a = 1;
assert_ser_tokens(
&SerializeWithEnum::Struct {
a: &a,
b: 2,
},
&[
Token::EnumMapStart("SerializeWithEnum", "Struct", Some(2)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::EnumMapSep,
Token::Str("b"),
Token::Bool(false),
Token::EnumMapEnd,
]
);
assert_ser_tokens(
&SerializeWithEnum::Struct {
a: &a,
b: 123,
},
&[
Token::EnumMapStart("SerializeWithEnum", "Struct", Some(2)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::EnumMapSep,
Token::Str("b"),
Token::Bool(true),
Token::EnumMapEnd,
]
);
}
#[derive(Debug, PartialEq, Deserialize)]
struct DeserializeWithStruct<B> where B: DeserializeWith {
a: i8,
#[serde(deserialize_with="DeserializeWith::deserialize_with")]
b: B,
}
#[test]
fn test_deserialize_with_struct() {
assert_de_tokens(
&DeserializeWithStruct {
a: 1,
b: 2,
},
&[
Token::StructStart("DeserializeWithStruct", Some(2)),
Token::StructSep,
Token::Str("a"),
Token::I8(1),
Token::StructSep,
Token::Str("b"),
Token::Bool(false),
Token::StructEnd,
]
);
assert_de_tokens(
&DeserializeWithStruct {
a: 1,
b: 123,
},
&[
Token::StructStart("DeserializeWithStruct", Some(2)),
Token::StructSep,
Token::Str("a"),
Token::I8(1),
Token::StructSep,
Token::Str("b"),
Token::Bool(true),
Token::StructEnd,
]
);
}
#[derive(Debug, PartialEq, Deserialize)]
enum DeserializeWithEnum<B> where B: DeserializeWith {
Struct {
a: i8,
#[serde(deserialize_with="DeserializeWith::deserialize_with")]
b: B,
}
}
#[test]
fn test_deserialize_with_enum() {
assert_de_tokens(
&DeserializeWithEnum::Struct {
a: 1,
b: 2,
},
&[
Token::EnumMapStart("DeserializeWithEnum", "Struct", Some(2)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::EnumMapSep,
Token::Str("b"),
Token::Bool(false),
Token::EnumMapEnd,
]
);
assert_de_tokens(
&DeserializeWithEnum::Struct {
a: 1,
b: 123,
},
&[
Token::EnumMapStart("DeserializeWithEnum", "Struct", Some(2)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::EnumMapSep,
Token::Str("b"),
Token::Bool(true),
Token::EnumMapEnd,
]
);
}
#[test]
fn test_missing_renamed_field_struct() {
assert_de_tokens_error::<RenameStruct>(
&[
Token::StructStart("Superhero", Some(2)),
Token::StructSep,
Token::Str("a1"),
Token::I32(1),
Token::StructEnd,
],
Error::MissingField("a3"),
);
assert_de_tokens_error::<RenameStructSerializeDeserialize>(
&[
Token::StructStart("SuperheroDe", Some(2)),
Token::StructSep,
Token::Str("a1"),
Token::I32(1),
Token::StructEnd,
],
Error::MissingField("a5"),
);
}
#[test]
fn test_missing_renamed_field_enum() {
assert_de_tokens_error::<RenameEnum>(
&[
Token::EnumMapStart("Superhero", "barry_allan", Some(1)),
Token::EnumMapEnd,
],
Error::MissingField("b"),
);
assert_de_tokens_error::<RenameEnumSerializeDeserialize<i8>>(
&[
Token::EnumMapStart("SuperheroDe", "jason_todd", Some(2)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(0),
Token::EnumMapEnd,
],
Error::MissingField("d"),
);
}
#[derive(Debug, PartialEq, Deserialize)]
enum InvalidLengthEnum {
A(i32, i32, i32),
B(#[serde(skip_deserializing)] i32, i32, i32),
}
#[test]
fn test_invalid_length_enum() {
assert_de_tokens_error::<InvalidLengthEnum>(
&[
Token::EnumSeqStart("InvalidLengthEnum", "A", Some(3)),
Token::EnumSeqSep,
Token::I32(1),
Token::EnumSeqEnd,
],
Error::InvalidLength(1),
);
assert_de_tokens_error::<InvalidLengthEnum>(
&[
Token::EnumSeqStart("InvalidLengthEnum", "B", Some(3)),
Token::EnumSeqSep,
Token::I32(1),
Token::EnumSeqEnd,
],
Error::InvalidLength(1),
);
}
@@ -1,20 +1,39 @@
use serde;
use serde::Serialize;
use serde::bytes::{ByteBuf, Bytes};
use std::fmt;
use std::error;
extern crate serde;
use self::serde::Serialize;
use self::serde::bytes::{ByteBuf, Bytes};
///////////////////////////////////////////////////////////////////////////////
#[derive(Debug, PartialEq)]
struct Error;
impl serde::ser::Error for Error {
fn custom<T: Into<String>>(_: T) -> Error { Error }
}
impl serde::de::Error for Error {
fn syntax(_: &str) -> Error { Error }
fn custom<T: Into<String>>(_: T) -> Error { Error }
fn end_of_stream() -> Error { Error }
}
fn unknown_field(_field: &str) -> Error { Error }
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(format!("{:?}", self).as_ref())
}
}
fn missing_field(_field: &'static str) -> Error { Error }
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Deserialization Error"
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -34,74 +53,74 @@ impl BytesSerializer {
impl serde::Serializer for BytesSerializer {
type Error = Error;
fn visit_unit(&mut self) -> Result<(), Error> {
fn serialize_unit(&mut self) -> Result<(), Error> {
Err(Error)
}
fn visit_bool(&mut self, _v: bool) -> Result<(), Error> {
fn serialize_bool(&mut self, _v: bool) -> Result<(), Error> {
Err(Error)
}
fn visit_i64(&mut self, _v: i64) -> Result<(), Error> {
fn serialize_i64(&mut self, _v: i64) -> Result<(), Error> {
Err(Error)
}
fn visit_u64(&mut self, _v: u64) -> Result<(), Error> {
fn serialize_u64(&mut self, _v: u64) -> Result<(), Error> {
Err(Error)
}
fn visit_f32(&mut self, _v: f32) -> Result<(), Error> {
fn serialize_f32(&mut self, _v: f32) -> Result<(), Error> {
Err(Error)
}
fn visit_f64(&mut self, _v: f64) -> Result<(), Error> {
fn serialize_f64(&mut self, _v: f64) -> Result<(), Error> {
Err(Error)
}
fn visit_char(&mut self, _v: char) -> Result<(), Error> {
fn serialize_char(&mut self, _v: char) -> Result<(), Error> {
Err(Error)
}
fn visit_str(&mut self, _v: &str) -> Result<(), Error> {
fn serialize_str(&mut self, _v: &str) -> Result<(), Error> {
Err(Error)
}
fn visit_none(&mut self) -> Result<(), Error> {
fn serialize_none(&mut self) -> Result<(), Error> {
Err(Error)
}
fn visit_some<V>(&mut self, _value: V) -> Result<(), Error>
fn serialize_some<V>(&mut self, _value: V) -> Result<(), Error>
where V: serde::Serialize,
{
Err(Error)
}
fn visit_seq<V>(&mut self, _visitor: V) -> Result<(), Error>
fn serialize_seq<V>(&mut self, _visitor: V) -> Result<(), Error>
where V: serde::ser::SeqVisitor,
{
Err(Error)
}
fn visit_seq_elt<T>(&mut self, _value: T) -> Result<(), Error>
fn serialize_seq_elt<T>(&mut self, _value: T) -> Result<(), Error>
where T: serde::Serialize
{
Err(Error)
}
fn visit_map<V>(&mut self, _visitor: V) -> Result<(), Error>
fn serialize_map<V>(&mut self, _visitor: V) -> Result<(), Error>
where V: serde::ser::MapVisitor,
{
Err(Error)
}
fn visit_map_elt<K, V>(&mut self, _key: K, _value: V) -> Result<(), Error>
fn serialize_map_elt<K, V>(&mut self, _key: K, _value: V) -> Result<(), Error>
where K: serde::Serialize,
V: serde::Serialize,
{
Err(Error)
}
fn visit_bytes(&mut self, bytes: &[u8]) -> Result<(), Error> {
fn serialize_bytes(&mut self, bytes: &[u8]) -> Result<(), Error> {
assert_eq!(self.bytes, bytes);
Ok(())
}
@@ -124,13 +143,13 @@ impl BytesDeserializer {
impl serde::Deserializer for BytesDeserializer {
type Error = Error;
fn visit<V>(&mut self, _visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, _visitor: V) -> Result<V::Value, Error>
where V: serde::de::Visitor,
{
Err(Error)
}
fn visit_bytes<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize_bytes<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: serde::de::Visitor,
{
visitor.visit_byte_buf(self.bytes.take().unwrap())
@@ -1,8 +1,20 @@
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::net;
use std::path::PathBuf;
use serde::de::{Deserializer, Visitor};
extern crate serde;
use self::serde::Deserialize;
use token::{Token, assert_de_tokens};
extern crate fnv;
use self::fnv::FnvHasher;
extern crate serde_test;
use self::serde_test::{
Error,
Token,
assert_de_tokens,
assert_de_tokens_error,
};
//////////////////////////////////////////////////////////////////////////
@@ -16,6 +28,7 @@ struct TupleStruct(i32, i32, i32);
struct Struct {
a: i32,
b: i32,
#[serde(skip_deserializing)]
c: i32,
}
@@ -34,7 +47,11 @@ macro_rules! declare_test {
#[test]
fn $name() {
$(
// Test ser/de roundtripping
assert_de_tokens(&$value, $tokens);
// Test that the tokens are ignorable
assert_de_tokens_ignore($tokens);
)+
}
}
@@ -48,107 +65,158 @@ macro_rules! declare_tests {
}
}
macro_rules! declare_error_tests {
($($name:ident<$target:ident> { $tokens:expr, $expected:expr, })+) => {
$(
#[test]
fn $name() {
assert_de_tokens_error::<$target>($tokens, $expected);
}
)+
}
}
fn assert_de_tokens_ignore(ignorable_tokens: &[Token<'static>]) {
#[derive(PartialEq, Debug, Deserialize)]
struct IgnoreBase {
a: i32,
}
let expected = IgnoreBase{a: 1};
// Embed the tokens to be ignored in the normal token
// stream for an IgnoreBase type
let concated_tokens : Vec<Token<'static>> = vec![
Token::MapStart(Some(2)),
Token::MapSep,
Token::Str("a"),
Token::I32(1),
Token::MapSep,
Token::Str("ignored")
]
.into_iter()
.chain(ignorable_tokens.to_vec().into_iter())
.chain(vec![
Token::MapEnd,
].into_iter())
.collect();
let mut de = serde_test::Deserializer::new(concated_tokens.into_iter());
let v: Result<IgnoreBase, Error> = Deserialize::deserialize(&mut de);
// We run this test on every token stream for convenience, but
// some token streams don't make sense embedded as a map value,
// so we ignore those. SyntaxError is the real sign of trouble.
if let Err(Error::UnexpectedToken(_)) = v {
return;
}
assert_eq!(v.as_ref(), Ok(&expected));
assert_eq!(de.next_token(), None);
}
//////////////////////////////////////////////////////////////////////////
declare_tests! {
test_bool {
true => vec![Token::Bool(true)],
false => vec![Token::Bool(false)],
true => &[Token::Bool(true)],
false => &[Token::Bool(false)],
}
test_isize {
0isize => vec![Token::Isize(0)],
0isize => vec![Token::I8(0)],
0isize => vec![Token::I16(0)],
0isize => vec![Token::I32(0)],
0isize => vec![Token::I64(0)],
0isize => vec![Token::Usize(0)],
0isize => vec![Token::U8(0)],
0isize => vec![Token::U16(0)],
0isize => vec![Token::U32(0)],
0isize => vec![Token::U64(0)],
0isize => vec![Token::F32(0.)],
0isize => vec![Token::F64(0.)],
0isize => &[Token::Isize(0)],
0isize => &[Token::I8(0)],
0isize => &[Token::I16(0)],
0isize => &[Token::I32(0)],
0isize => &[Token::I64(0)],
0isize => &[Token::Usize(0)],
0isize => &[Token::U8(0)],
0isize => &[Token::U16(0)],
0isize => &[Token::U32(0)],
0isize => &[Token::U64(0)],
0isize => &[Token::F32(0.)],
0isize => &[Token::F64(0.)],
}
test_ints {
0isize => vec![Token::Isize(0)],
0i8 => vec![Token::I8(0)],
0i16 => vec![Token::I16(0)],
0i32 => vec![Token::I32(0)],
0i64 => vec![Token::I64(0)],
0isize => &[Token::Isize(0)],
0i8 => &[Token::I8(0)],
0i16 => &[Token::I16(0)],
0i32 => &[Token::I32(0)],
0i64 => &[Token::I64(0)],
}
test_uints {
0usize => vec![Token::Usize(0)],
0u8 => vec![Token::U8(0)],
0u16 => vec![Token::U16(0)],
0u32 => vec![Token::U32(0)],
0u64 => vec![Token::U64(0)],
0usize => &[Token::Usize(0)],
0u8 => &[Token::U8(0)],
0u16 => &[Token::U16(0)],
0u32 => &[Token::U32(0)],
0u64 => &[Token::U64(0)],
}
test_floats {
0f32 => vec![Token::F32(0.)],
0f64 => vec![Token::F64(0.)],
0f32 => &[Token::F32(0.)],
0f64 => &[Token::F64(0.)],
}
test_char {
'a' => vec![Token::Char('a')],
'a' => vec![Token::Str("a")],
'a' => vec![Token::String("a".to_string())],
'a' => &[Token::Char('a')],
'a' => &[Token::Str("a")],
'a' => &[Token::String("a".to_owned())],
}
test_string {
"abc".to_string() => vec![Token::Str("abc")],
"abc".to_string() => vec![Token::String("abc".to_string())],
"a".to_string() => vec![Token::Char('a')],
"abc".to_owned() => &[Token::Str("abc")],
"abc".to_owned() => &[Token::String("abc".to_owned())],
"a".to_owned() => &[Token::Char('a')],
}
test_option {
None::<i32> => vec![Token::Unit],
None::<i32> => vec![Token::Option(false)],
Some(1) => vec![Token::I32(1)],
Some(1) => vec![
None::<i32> => &[Token::Unit],
None::<i32> => &[Token::Option(false)],
Some(1) => &[Token::I32(1)],
Some(1) => &[
Token::Option(true),
Token::I32(1),
],
}
test_result {
Ok::<i32, i32>(0) => vec![
Ok::<i32, i32>(0) => &[
Token::EnumStart("Result"),
Token::Str("Ok"),
Token::I32(0),
],
Err::<i32, i32>(1) => vec![
Err::<i32, i32>(1) => &[
Token::EnumStart("Result"),
Token::Str("Err"),
Token::I32(1),
],
}
test_unit {
() => vec![Token::Unit],
() => vec![
() => &[Token::Unit],
() => &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
],
() => vec![
() => &[
Token::SeqStart(None),
Token::SeqEnd,
],
() => vec![
() => &[
Token::TupleStructStart("Anything", Some(0)),
Token::SeqEnd,
],
}
test_unit_struct {
UnitStruct => vec![Token::Unit],
UnitStruct => vec![
UnitStruct => &[Token::Unit],
UnitStruct => &[
Token::UnitStruct("UnitStruct"),
],
UnitStruct => vec![
UnitStruct => &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
],
UnitStruct => vec![
UnitStruct => &[
Token::SeqStart(None),
Token::SeqEnd,
],
}
test_tuple_struct {
TupleStruct(1, 2, 3) => vec![
TupleStruct(1, 2, 3) => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(1),
@@ -160,7 +228,7 @@ declare_tests! {
Token::I32(3),
Token::SeqEnd,
],
TupleStruct(1, 2, 3) => vec![
TupleStruct(1, 2, 3) => &[
Token::SeqStart(None),
Token::SeqSep,
Token::I32(1),
@@ -172,40 +240,40 @@ declare_tests! {
Token::I32(3),
Token::SeqEnd,
],
TupleStruct(1, 2, 3) => vec![
TupleStruct(1, 2, 3) => &[
Token::TupleStructStart("TupleStruct", Some(3)),
Token::SeqSep,
Token::TupleStructSep,
Token::I32(1),
Token::SeqSep,
Token::TupleStructSep,
Token::I32(2),
Token::SeqSep,
Token::TupleStructSep,
Token::I32(3),
Token::SeqEnd,
Token::TupleStructEnd,
],
TupleStruct(1, 2, 3) => vec![
TupleStruct(1, 2, 3) => &[
Token::TupleStructStart("TupleStruct", None),
Token::SeqSep,
Token::TupleStructSep,
Token::I32(1),
Token::SeqSep,
Token::TupleStructSep,
Token::I32(2),
Token::SeqSep,
Token::TupleStructSep,
Token::I32(3),
Token::SeqEnd,
Token::TupleStructEnd,
],
}
test_btreeset {
BTreeSet::<isize>::new() => vec![
BTreeSet::<isize>::new() => &[
Token::Unit,
],
BTreeSet::<isize>::new() => vec![
BTreeSet::<isize>::new() => &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
],
btreeset![btreeset![], btreeset![1], btreeset![2, 3]] => vec![
btreeset![btreeset![], btreeset![1], btreeset![2, 3]] => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::SeqStart(Some(0)),
@@ -227,23 +295,23 @@ declare_tests! {
Token::SeqEnd,
Token::SeqEnd,
],
BTreeSet::<isize>::new() => vec![
BTreeSet::<isize>::new() => &[
Token::UnitStruct("Anything"),
],
BTreeSet::<isize>::new() => vec![
BTreeSet::<isize>::new() => &[
Token::TupleStructStart("Anything", Some(0)),
Token::SeqEnd,
],
}
test_hashset {
HashSet::<isize>::new() => vec![
HashSet::<isize>::new() => &[
Token::Unit,
],
HashSet::<isize>::new() => vec![
HashSet::<isize>::new() => &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
],
hashset![1, 2, 3] => vec![
hashset![1, 2, 3] => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(1),
@@ -255,23 +323,35 @@ declare_tests! {
Token::I32(3),
Token::SeqEnd,
],
HashSet::<isize>::new() => vec![
HashSet::<isize>::new() => &[
Token::UnitStruct("Anything"),
],
HashSet::<isize>::new() => vec![
HashSet::<isize>::new() => &[
Token::TupleStructStart("Anything", Some(0)),
Token::SeqEnd,
],
hashset![FnvHasher @ 1, 2, 3] => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(1),
Token::SeqSep,
Token::I32(2),
Token::SeqSep,
Token::I32(3),
Token::SeqEnd,
],
}
test_vec {
Vec::<isize>::new() => vec![
Vec::<isize>::new() => &[
Token::Unit,
],
Vec::<isize>::new() => vec![
Vec::<isize>::new() => &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
],
vec![vec![], vec![1], vec![2, 3]] => vec![
vec![vec![], vec![1], vec![2, 3]] => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::SeqStart(Some(0)),
@@ -293,23 +373,27 @@ declare_tests! {
Token::SeqEnd,
Token::SeqEnd,
],
Vec::<isize>::new() => vec![
Vec::<isize>::new() => &[
Token::UnitStruct("Anything"),
],
Vec::<isize>::new() => vec![
Vec::<isize>::new() => &[
Token::TupleStructStart("Anything", Some(0)),
Token::SeqEnd,
],
}
test_array {
[0; 0] => vec![
[0; 0] => &[
Token::Unit,
],
[0; 0] => vec![
[0; 0] => &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
],
([0; 0], [1], [2, 3]) => vec![
[0; 0] => &[
Token::SeqArrayStart(0),
Token::SeqEnd,
],
([0; 0], [1], [2, 3]) => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::SeqStart(Some(0)),
@@ -331,22 +415,44 @@ declare_tests! {
Token::SeqEnd,
Token::SeqEnd,
],
[0; 0] => vec![
([0; 0], [1], [2, 3]) => &[
Token::SeqArrayStart(3),
Token::SeqSep,
Token::SeqArrayStart(0),
Token::SeqEnd,
Token::SeqSep,
Token::SeqArrayStart(1),
Token::SeqSep,
Token::I32(1),
Token::SeqEnd,
Token::SeqSep,
Token::SeqArrayStart(2),
Token::SeqSep,
Token::I32(2),
Token::SeqSep,
Token::I32(3),
Token::SeqEnd,
Token::SeqEnd,
],
[0; 0] => &[
Token::UnitStruct("Anything"),
],
[0; 0] => vec![
[0; 0] => &[
Token::TupleStructStart("Anything", Some(0)),
Token::SeqEnd,
],
}
test_tuple {
(1,) => vec![
(1,) => &[
Token::SeqStart(Some(1)),
Token::SeqSep,
Token::I32(1),
Token::SeqEnd,
],
(1, 2, 3) => vec![
(1, 2, 3) => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(1),
@@ -358,23 +464,41 @@ declare_tests! {
Token::I32(3),
Token::SeqEnd,
],
(1,) => &[
Token::TupleStart(1),
Token::TupleSep,
Token::I32(1),
Token::TupleEnd,
],
(1, 2, 3) => &[
Token::TupleStart(3),
Token::TupleSep,
Token::I32(1),
Token::TupleSep,
Token::I32(2),
Token::TupleSep,
Token::I32(3),
Token::TupleEnd,
],
}
test_btreemap {
BTreeMap::<isize, isize>::new() => vec![
BTreeMap::<isize, isize>::new() => &[
Token::Unit,
],
BTreeMap::<isize, isize>::new() => vec![
BTreeMap::<isize, isize>::new() => &[
Token::MapStart(Some(0)),
Token::MapEnd,
],
btreemap![1 => 2] => vec![
btreemap![1 => 2] => &[
Token::MapStart(Some(1)),
Token::MapSep,
Token::I32(1),
Token::I32(2),
Token::MapEnd,
],
btreemap![1 => 2, 3 => 4] => vec![
btreemap![1 => 2, 3 => 4] => &[
Token::MapStart(Some(2)),
Token::MapSep,
Token::I32(1),
@@ -385,7 +509,7 @@ declare_tests! {
Token::I32(4),
Token::MapEnd,
],
btreemap![1 => btreemap![], 2 => btreemap![3 => 4, 5 => 6]] => vec![
btreemap![1 => btreemap![], 2 => btreemap![3 => 4, 5 => 6]] => &[
Token::MapStart(Some(2)),
Token::MapSep,
Token::I32(1),
@@ -405,30 +529,30 @@ declare_tests! {
Token::MapEnd,
Token::MapEnd,
],
BTreeMap::<isize, isize>::new() => vec![
BTreeMap::<isize, isize>::new() => &[
Token::UnitStruct("Anything"),
],
BTreeMap::<isize, isize>::new() => vec![
BTreeMap::<isize, isize>::new() => &[
Token::StructStart("Anything", Some(0)),
Token::MapEnd,
],
}
test_hashmap {
HashMap::<isize, isize>::new() => vec![
HashMap::<isize, isize>::new() => &[
Token::Unit,
],
HashMap::<isize, isize>::new() => vec![
HashMap::<isize, isize>::new() => &[
Token::MapStart(Some(0)),
Token::MapEnd,
],
hashmap![1 => 2] => vec![
hashmap![1 => 2] => &[
Token::MapStart(Some(1)),
Token::MapSep,
Token::I32(1),
Token::I32(2),
Token::MapEnd,
],
hashmap![1 => 2, 3 => 4] => vec![
hashmap![1 => 2, 3 => 4] => &[
Token::MapStart(Some(2)),
Token::MapSep,
Token::I32(1),
@@ -439,7 +563,7 @@ declare_tests! {
Token::I32(4),
Token::MapEnd,
],
hashmap![1 => hashmap![], 2 => hashmap![3 => 4, 5 => 6]] => vec![
hashmap![1 => hashmap![], 2 => hashmap![3 => 4, 5 => 6]] => &[
Token::MapStart(Some(2)),
Token::MapSep,
Token::I32(1),
@@ -459,16 +583,60 @@ declare_tests! {
Token::MapEnd,
Token::MapEnd,
],
HashMap::<isize, isize>::new() => vec![
HashMap::<isize, isize>::new() => &[
Token::UnitStruct("Anything"),
],
HashMap::<isize, isize>::new() => vec![
HashMap::<isize, isize>::new() => &[
Token::StructStart("Anything", Some(0)),
Token::MapEnd,
],
hashmap![FnvHasher @ 1 => 2, 3 => 4] => &[
Token::MapStart(Some(2)),
Token::MapSep,
Token::I32(1),
Token::I32(2),
Token::MapSep,
Token::I32(3),
Token::I32(4),
Token::MapEnd,
],
}
test_struct {
Struct { a: 1, b: 2, c: 3 } => vec![
Struct { a: 1, b: 2, c: 0 } => &[
Token::MapStart(Some(3)),
Token::MapSep,
Token::Str("a"),
Token::I32(1),
Token::MapSep,
Token::Str("b"),
Token::I32(2),
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::StructStart("Struct", Some(3)),
Token::StructSep,
Token::Str("a"),
Token::I32(1),
Token::StructSep,
Token::Str("b"),
Token::I32(2),
Token::StructEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(1),
Token::SeqSep,
Token::I32(2),
Token::SeqEnd,
],
}
test_struct_with_skip {
Struct { a: 1, b: 2, c: 0 } => &[
Token::MapStart(Some(3)),
Token::MapSep,
Token::Str("a"),
@@ -481,78 +649,168 @@ declare_tests! {
Token::MapSep,
Token::Str("c"),
Token::I32(3),
Token::MapSep,
Token::Str("d"),
Token::I32(4),
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 3 } => vec![
Struct { a: 1, b: 2, c: 0 } => &[
Token::StructStart("Struct", Some(3)),
Token::MapSep,
Token::StructSep,
Token::Str("a"),
Token::I32(1),
Token::MapSep,
Token::StructSep,
Token::Str("b"),
Token::I32(2),
Token::MapSep,
Token::StructSep,
Token::Str("c"),
Token::I32(3),
Token::MapEnd,
Token::StructSep,
Token::Str("d"),
Token::I32(4),
Token::StructEnd,
],
}
test_enum_unit {
Enum::Unit => vec![
Enum::Unit => &[
Token::EnumUnit("Enum", "Unit"),
],
}
test_enum_simple {
Enum::Simple(1) => vec![
Token::EnumNewtype("Enum", "Simple"),
Enum::Simple(1) => &[
Token::EnumNewType("Enum", "Simple"),
Token::I32(1),
],
}
test_enum_seq {
Enum::Seq(1, 2, 3) => vec![
Enum::Seq(1, 2, 3) => &[
Token::EnumSeqStart("Enum", "Seq", Some(3)),
Token::SeqSep,
Token::EnumSeqSep,
Token::I32(1),
Token::SeqSep,
Token::EnumSeqSep,
Token::I32(2),
Token::SeqSep,
Token::EnumSeqSep,
Token::I32(3),
Token::SeqEnd,
Token::EnumSeqEnd,
],
}
test_enum_map {
Enum::Map { a: 1, b: 2, c: 3 } => vec![
Enum::Map { a: 1, b: 2, c: 3 } => &[
Token::EnumMapStart("Enum", "Map", Some(3)),
Token::MapSep,
Token::EnumMapSep,
Token::Str("a"),
Token::I32(1),
Token::MapSep,
Token::EnumMapSep,
Token::Str("b"),
Token::I32(2),
Token::MapSep,
Token::EnumMapSep,
Token::Str("c"),
Token::I32(3),
Token::MapEnd,
Token::EnumMapEnd,
],
}
test_enum_unit_usize {
Enum::Unit => vec![
Enum::Unit => &[
Token::EnumStart("Enum"),
Token::Usize(0),
Token::Unit,
],
}
test_enum_unit_bytes {
Enum::Unit => vec![
Enum::Unit => &[
Token::EnumStart("Enum"),
Token::Bytes(b"Unit"),
Token::Unit,
],
}
test_box {
Box::new(0i32) => &[Token::I32(0)],
}
test_boxed_slice {
Box::new([0, 1, 2]) => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(0),
Token::SeqSep,
Token::I32(1),
Token::SeqSep,
Token::I32(2),
Token::SeqEnd,
],
}
test_net_ipv4addr {
"1.2.3.4".parse::<net::Ipv4Addr>().unwrap() => &[Token::Str("1.2.3.4")],
}
test_net_ipv6addr {
"::1".parse::<net::Ipv6Addr>().unwrap() => &[Token::Str("::1")],
}
test_net_socketaddr {
"1.2.3.4:1234".parse::<net::SocketAddr>().unwrap() => &[Token::Str("1.2.3.4:1234")],
"1.2.3.4:1234".parse::<net::SocketAddrV4>().unwrap() => &[Token::Str("1.2.3.4:1234")],
"[::1]:1234".parse::<net::SocketAddrV6>().unwrap() => &[Token::Str("[::1]:1234")],
}
test_path_buf {
PathBuf::from("/usr/local/lib") => &[
Token::String("/usr/local/lib".to_owned()),
],
}
}
#[cfg(feature = "nightly")]
#[test]
fn test_net_ipaddr() {
assert_de_tokens(
"1.2.3.4".parse::<net::IpAddr>().unwrap(),
&[Token::Str("1.2.3.4")],
);
}
declare_error_tests! {
test_unknown_variant<Enum> {
&[
Token::EnumUnit("Enum", "Foo"),
],
Error::UnknownVariant("Foo".to_owned()),
}
test_struct_seq_too_long<Struct> {
&[
Token::SeqStart(Some(4)),
Token::SeqSep, Token::I32(1),
Token::SeqSep, Token::I32(2),
Token::SeqSep, Token::I32(3),
],
Error::UnexpectedToken(Token::SeqSep),
}
test_duplicate_field_struct<Struct> {
&[
Token::MapStart(Some(3)),
Token::MapSep,
Token::Str("a"),
Token::I32(1),
Token::MapSep,
Token::Str("a"),
],
Error::DuplicateField("a"),
}
test_duplicate_field_enum<Enum> {
&[
Token::EnumMapStart("Enum", "Map", Some(3)),
Token::EnumMapSep,
Token::Str("a"),
Token::I32(1),
Token::EnumMapSep,
Token::Str("a"),
],
Error::DuplicateField("a"),
}
}
+134
View File
@@ -0,0 +1,134 @@
// These just test that serde_codegen is able to produce code that compiles
// successfully when there are a variety of generics and non-(de)serializable
// types involved.
extern crate serde;
use self::serde::ser::{Serialize, Serializer};
use self::serde::de::{Deserialize, Deserializer};
//////////////////////////////////////////////////////////////////////////
#[derive(Serialize, Deserialize)]
struct With<T> {
t: T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
x: X,
}
#[derive(Serialize, Deserialize)]
struct WithRef<'a, T: 'a> {
#[serde(skip_deserializing)]
t: Option<&'a T>,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
x: X,
}
#[derive(Serialize, Deserialize)]
struct Bounds<T: Serialize + Deserialize> {
t: T,
option: Option<T>,
boxed: Box<T>,
option_boxed: Option<Box<T>>,
}
#[derive(Serialize, Deserialize)]
struct NoBounds<T> {
t: T,
option: Option<T>,
boxed: Box<T>,
option_boxed: Option<Box<T>>,
}
#[derive(Serialize, Deserialize)]
enum EnumWith<T> {
Unit,
Newtype(
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X),
Tuple(
T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X),
Struct {
t: T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
x: X },
}
#[derive(Serialize)]
struct MultipleRef<'a, 'b, 'c, T> where T: 'c, 'c: 'b, 'b: 'a {
t: T,
rrrt: &'a &'b &'c T,
}
#[derive(Serialize, Deserialize)]
struct Newtype(
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X
);
#[derive(Serialize, Deserialize)]
struct Tuple<T>(
T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X,
);
#[derive(Serialize, Deserialize)]
enum TreeNode<D> {
Split {
left: Box<TreeNode<D>>,
right: Box<TreeNode<D>>,
},
Leaf {
data: D,
},
}
#[derive(Serialize, Deserialize)]
struct ListNode<D> {
data: D,
next: Box<ListNode<D>>,
}
#[derive(Serialize, Deserialize)]
#[serde(bound="D: SerializeWith + DeserializeWith")]
struct WithTraits1<D, E> {
#[serde(serialize_with="SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with")]
d: D,
#[serde(serialize_with="SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with",
bound="E: SerializeWith + DeserializeWith")]
e: E,
}
#[derive(Serialize, Deserialize)]
#[serde(bound(serialize="D: SerializeWith",
deserialize="D: DeserializeWith"))]
struct WithTraits2<D, E> {
#[serde(serialize_with="SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with")]
d: D,
#[serde(serialize_with="SerializeWith::serialize_with",
bound(serialize="E: SerializeWith"))]
#[serde(deserialize_with="DeserializeWith::deserialize_with",
bound(deserialize="E: DeserializeWith"))]
e: E,
}
//////////////////////////////////////////////////////////////////////////
trait SerializeWith {
fn serialize_with<S: Serializer>(_: &Self, _: &mut S) -> Result<(), S::Error>;
}
trait DeserializeWith: Sized {
fn deserialize_with<D: Deserializer>(_: &mut D) -> Result<Self, D::Error>;
}
// Implements neither Serialize nor Deserialize
struct X;
fn ser_x<S: Serializer>(_: &X, _: &mut S) -> Result<(), S::Error> { panic!() }
fn de_x<D: Deserializer>(_: &mut D) -> Result<X, D::Error> { panic!() }
@@ -1,10 +1,19 @@
use token::{Token, assert_tokens, assert_ser_tokens, assert_de_tokens};
extern crate serde_test;
use self::serde_test::{
Token,
assert_tokens,
assert_ser_tokens,
assert_de_tokens,
};
/*
trait Trait {
type Type;
}
*/
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;
@@ -123,7 +132,7 @@ pub struct GenericStruct<T> {
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct GenericNewtypeStruct<T>(T);
pub struct GenericNewTypeStruct<T>(T);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct GenericTupleStruct<T, U>(T, U);
@@ -131,16 +140,29 @@ pub struct GenericTupleStruct<T, U>(T, U);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub enum GenericEnum<T, U> {
Unit,
Newtype(T),
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,
vec![Token::UnitStruct("NamedUnit")]
&[Token::UnitStruct("NamedUnit")]
);
}
@@ -153,16 +175,16 @@ fn test_ser_named_tuple() {
&SerNamedTuple(&a, &mut b, c),
&[
Token::TupleStructStart("SerNamedTuple", Some(3)),
Token::SeqSep,
Token::TupleStructSep,
Token::I32(5),
Token::SeqSep,
Token::TupleStructSep,
Token::I32(6),
Token::SeqSep,
Token::TupleStructSep,
Token::I32(7),
Token::SeqEnd,
Token::TupleStructEnd,
],
);
}
@@ -171,8 +193,8 @@ fn test_ser_named_tuple() {
fn test_de_named_tuple() {
assert_de_tokens(
&DeNamedTuple(5, 6, 7),
vec![
Token::TupleStructStart("DeNamedTuple", Some(3)),
&[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(5),
@@ -185,6 +207,23 @@ fn test_de_named_tuple() {
Token::SeqEnd,
]
);
assert_de_tokens(
&DeNamedTuple(5, 6, 7),
&[
Token::TupleStructStart("DeNamedTuple", Some(3)),
Token::TupleStructSep,
Token::I32(5),
Token::TupleStructSep,
Token::I32(6),
Token::TupleStructSep,
Token::I32(7),
Token::TupleStructEnd,
]
);
}
#[test]
@@ -202,19 +241,19 @@ fn test_ser_named_map() {
&[
Token::StructStart("SerNamedMap", Some(3)),
Token::MapSep,
Token::StructSep,
Token::Str("a"),
Token::I32(5),
Token::MapSep,
Token::StructSep,
Token::Str("b"),
Token::I32(6),
Token::MapSep,
Token::StructSep,
Token::Str("c"),
Token::I32(7),
Token::MapEnd,
Token::StructEnd,
]
);
}
@@ -227,22 +266,22 @@ fn test_de_named_map() {
b: 6,
c: 7,
},
vec![
&[
Token::StructStart("DeNamedMap", Some(3)),
Token::MapSep,
Token::StructSep,
Token::Str("a"),
Token::I32(5),
Token::MapSep,
Token::StructSep,
Token::Str("b"),
Token::I32(6),
Token::MapSep,
Token::StructSep,
Token::Str("c"),
Token::I32(7),
Token::MapEnd,
Token::StructEnd,
]
);
}
@@ -278,19 +317,19 @@ fn test_ser_enum_seq() {
&[
Token::EnumSeqStart("SerEnum", "Seq", Some(4)),
Token::SeqSep,
Token::EnumSeqSep,
Token::I8(1),
Token::SeqSep,
Token::EnumSeqSep,
Token::I32(2),
Token::SeqSep,
Token::EnumSeqSep,
Token::I32(3),
Token::SeqSep,
Token::EnumSeqSep,
Token::I32(5),
Token::SeqEnd,
Token::EnumSeqEnd,
],
);
}
@@ -316,23 +355,23 @@ fn test_ser_enum_map() {
&[
Token::EnumMapStart("SerEnum", "Map", Some(4)),
Token::MapSep,
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::MapSep,
Token::EnumMapSep,
Token::Str("b"),
Token::I32(2),
Token::MapSep,
Token::EnumMapSep,
Token::Str("c"),
Token::I32(3),
Token::MapSep,
Token::EnumMapSep,
Token::Str("e"),
Token::I32(5),
Token::MapEnd,
Token::EnumMapEnd,
],
);
}
@@ -341,7 +380,7 @@ fn test_ser_enum_map() {
fn test_de_enum_unit() {
assert_tokens(
&DeEnum::Unit::<u32, u32, u32>,
vec![
&[
Token::EnumUnit("DeEnum", "Unit"),
],
);
@@ -365,22 +404,22 @@ fn test_de_enum_seq() {
e,
//f,
),
vec![
&[
Token::EnumSeqStart("DeEnum", "Seq", Some(4)),
Token::SeqSep,
Token::EnumSeqSep,
Token::I8(1),
Token::SeqSep,
Token::EnumSeqSep,
Token::I32(2),
Token::SeqSep,
Token::EnumSeqSep,
Token::I32(3),
Token::SeqSep,
Token::EnumSeqSep,
Token::I32(5),
Token::SeqEnd,
Token::EnumSeqEnd,
],
);
}
@@ -403,26 +442,26 @@ fn test_de_enum_map() {
e: e,
//f: f,
},
vec![
&[
Token::EnumMapStart("DeEnum", "Map", Some(4)),
Token::MapSep,
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::MapSep,
Token::EnumMapSep,
Token::Str("b"),
Token::I32(2),
Token::MapSep,
Token::EnumMapSep,
Token::Str("c"),
Token::I32(3),
Token::MapSep,
Token::EnumMapSep,
Token::Str("e"),
Token::I32(5),
Token::MapEnd,
Token::EnumMapEnd,
],
);
}
@@ -434,7 +473,7 @@ fn test_lifetimes() {
assert_ser_tokens(
&Lifetimes::LifetimeSeq(&value),
&[
Token::EnumNewtype("Lifetimes", "LifetimeSeq"),
Token::EnumNewType("Lifetimes", "LifetimeSeq"),
Token::I32(5),
]
);
@@ -442,7 +481,7 @@ fn test_lifetimes() {
assert_ser_tokens(
&Lifetimes::NoLifetimeSeq(5),
&[
Token::EnumNewtype("Lifetimes", "NoLifetimeSeq"),
Token::EnumNewType("Lifetimes", "NoLifetimeSeq"),
Token::I32(5),
]
);
@@ -452,11 +491,11 @@ fn test_lifetimes() {
&[
Token::EnumMapStart("Lifetimes", "LifetimeMap", Some(1)),
Token::MapSep,
Token::EnumMapSep,
Token::Str("a"),
Token::I32(5),
Token::MapEnd,
Token::EnumMapEnd,
]
);
@@ -465,11 +504,11 @@ fn test_lifetimes() {
&[
Token::EnumMapStart("Lifetimes", "NoLifetimeMap", Some(1)),
Token::MapSep,
Token::EnumMapSep,
Token::Str("a"),
Token::I32(5),
Token::MapEnd,
Token::EnumMapEnd,
]
);
}
@@ -478,14 +517,14 @@ fn test_lifetimes() {
fn test_generic_struct() {
assert_tokens(
&GenericStruct { x: 5u32 },
vec![
&[
Token::StructStart("GenericStruct", Some(1)),
Token::MapSep,
Token::StructSep,
Token::Str("x"),
Token::U32(5),
Token::MapEnd,
Token::StructEnd,
]
);
}
@@ -493,9 +532,9 @@ fn test_generic_struct() {
#[test]
fn test_generic_newtype_struct() {
assert_tokens(
&GenericNewtypeStruct(5u32),
vec![
Token::StructNewtype("GenericNewtypeStruct"),
&GenericNewTypeStruct(5u32),
&[
Token::StructNewType("GenericNewTypeStruct"),
Token::U32(5),
]
);
@@ -505,16 +544,16 @@ fn test_generic_newtype_struct() {
fn test_generic_tuple_struct() {
assert_tokens(
&GenericTupleStruct(5u32, 6u32),
vec![
&[
Token::TupleStructStart("GenericTupleStruct", Some(2)),
Token::SeqSep,
Token::TupleStructSep,
Token::U32(5),
Token::SeqSep,
Token::TupleStructSep,
Token::U32(6),
Token::SeqEnd,
Token::TupleStructEnd,
]
);
}
@@ -523,7 +562,7 @@ fn test_generic_tuple_struct() {
fn test_generic_enum_unit() {
assert_tokens(
&GenericEnum::Unit::<u32, u32>,
vec![
&[
Token::EnumUnit("GenericEnum", "Unit"),
]
);
@@ -532,9 +571,9 @@ fn test_generic_enum_unit() {
#[test]
fn test_generic_enum_newtype() {
assert_tokens(
&GenericEnum::Newtype::<u32, u32>(5),
vec![
Token::EnumNewtype("GenericEnum", "Newtype"),
&GenericEnum::NewType::<u32, u32>(5),
&[
Token::EnumNewType("GenericEnum", "NewType"),
Token::U32(5),
]
);
@@ -544,16 +583,16 @@ fn test_generic_enum_newtype() {
fn test_generic_enum_seq() {
assert_tokens(
&GenericEnum::Seq::<u32, u32>(5, 6),
vec![
&[
Token::EnumSeqStart("GenericEnum", "Seq", Some(2)),
Token::SeqSep,
Token::EnumSeqSep,
Token::U32(5),
Token::SeqSep,
Token::EnumSeqSep,
Token::U32(6),
Token::SeqEnd,
Token::EnumSeqEnd,
]
);
}
@@ -562,18 +601,34 @@ fn test_generic_enum_seq() {
fn test_generic_enum_map() {
assert_tokens(
&GenericEnum::Map::<u32, u32> { x: 5, y: 6 },
vec![
&[
Token::EnumMapStart("GenericEnum", "Map", Some(2)),
Token::MapSep,
Token::EnumMapSep,
Token::Str("x"),
Token::U32(5),
Token::MapSep,
Token::EnumMapSep,
Token::Str("y"),
Token::U32(6),
Token::MapEnd,
Token::EnumMapEnd,
]
);
}
#[test]
fn test_default_ty_param() {
assert_tokens(
&DefaultTyParam::<i32> { phantom: PhantomData },
&[
Token::StructStart("DefaultTyParam", Some(1)),
Token::StructSep,
Token::Str("phantom"),
Token::UnitStruct("PhantomData"),
Token::StructEnd,
]
);
}
@@ -1,6 +1,18 @@
use std::collections::BTreeMap;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::net;
use std::path::{Path, PathBuf};
use std::str;
use token::Token;
extern crate serde_test;
use self::serde_test::{
Error,
Token,
assert_ser_tokens,
assert_ser_tokens_error,
};
extern crate fnv;
use self::fnv::FnvHasher;
//////////////////////////////////////////////////////////////////////////
@@ -58,7 +70,7 @@ declare_ser_tests! {
}
test_str {
"abc" => &[Token::Str("abc")],
"abc".to_string() => &[Token::Str("abc")],
"abc".to_owned() => &[Token::Str("abc")],
}
test_option {
None::<i32> => &[Token::Option(false)],
@@ -69,11 +81,11 @@ declare_ser_tests! {
}
test_result {
Ok::<i32, i32>(0) => &[
Token::EnumNewtype("Result", "Ok"),
Token::EnumNewType("Result", "Ok"),
Token::I32(0),
],
Err::<i32, i32>(1) => &[
Token::EnumNewtype("Result", "Err"),
Token::EnumNewType("Result", "Err"),
Token::I32(1),
],
}
@@ -97,11 +109,11 @@ declare_ser_tests! {
}
test_array {
[0; 0] => &[
Token::SeqStart(Some(0)),
Token::SeqArrayStart(0),
Token::SeqEnd,
],
[1, 2, 3] => &[
Token::SeqStart(Some(3)),
Token::SeqArrayStart(3),
Token::SeqSep,
Token::I32(1),
@@ -141,24 +153,42 @@ declare_ser_tests! {
Token::SeqEnd,
],
}
test_tuple {
(1,) => &[
test_hashset {
HashSet::<isize>::new() => &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
],
hashset![1] => &[
Token::SeqStart(Some(1)),
Token::SeqSep,
Token::I32(1),
Token::SeqEnd,
],
(1, 2, 3) => &[
Token::SeqStart(Some(3)),
hashset![FnvHasher @ 1] => &[
Token::SeqStart(Some(1)),
Token::SeqSep,
Token::I32(1),
Token::SeqEnd,
],
}
test_tuple {
(1,) => &[
Token::TupleStart(1),
Token::TupleSep,
Token::I32(1),
Token::TupleEnd,
],
(1, 2, 3) => &[
Token::TupleStart(3),
Token::TupleSep,
Token::I32(1),
Token::SeqSep,
Token::TupleSep,
Token::I32(2),
Token::SeqSep,
Token::TupleSep,
Token::I32(3),
Token::SeqEnd,
Token::TupleEnd,
],
}
test_btreemap {
@@ -201,62 +231,146 @@ declare_ser_tests! {
Token::MapEnd,
],
}
test_hashmap {
HashMap::<isize, isize>::new() => &[
Token::MapStart(Some(0)),
Token::MapEnd,
],
hashmap![1 => 2] => &[
Token::MapStart(Some(1)),
Token::MapSep,
Token::I32(1),
Token::I32(2),
Token::MapEnd,
],
hashmap![FnvHasher @ 1 => 2] => &[
Token::MapStart(Some(1)),
Token::MapSep,
Token::I32(1),
Token::I32(2),
Token::MapEnd,
],
}
test_unit_struct {
UnitStruct => &[Token::UnitStruct("UnitStruct")],
}
test_tuple_struct {
TupleStruct(1, 2, 3) => &[
Token::TupleStructStart("TupleStruct", Some(3)),
Token::SeqSep,
Token::TupleStructSep,
Token::I32(1),
Token::SeqSep,
Token::TupleStructSep,
Token::I32(2),
Token::SeqSep,
Token::TupleStructSep,
Token::I32(3),
Token::SeqEnd,
Token::TupleStructEnd,
],
}
test_struct {
Struct { a: 1, b: 2, c: 3 } => &[
Token::StructStart("Struct", Some(3)),
Token::MapSep,
Token::StructSep,
Token::Str("a"),
Token::I32(1),
Token::MapSep,
Token::StructSep,
Token::Str("b"),
Token::I32(2),
Token::MapSep,
Token::StructSep,
Token::Str("c"),
Token::I32(3),
Token::MapEnd,
Token::StructEnd,
],
}
test_enum {
Enum::Unit => &[Token::EnumUnit("Enum", "Unit")],
Enum::One(42) => &[Token::EnumNewtype("Enum", "One"), Token::I32(42)],
Enum::One(42) => &[Token::EnumNewType("Enum", "One"), Token::I32(42)],
Enum::Seq(1, 2) => &[
Token::EnumSeqStart("Enum", "Seq", Some(2)),
Token::SeqSep,
Token::EnumSeqSep,
Token::I32(1),
Token::SeqSep,
Token::EnumSeqSep,
Token::I32(2),
Token::SeqEnd,
Token::EnumSeqEnd,
],
Enum::Map { a: 1, b: 2 } => &[
Token::EnumMapStart("Enum", "Map", Some(2)),
Token::MapSep,
Token::EnumMapSep,
Token::Str("a"),
Token::I32(1),
Token::MapSep,
Token::EnumMapSep,
Token::Str("b"),
Token::I32(2),
Token::MapEnd,
Token::EnumMapEnd,
],
}
test_box {
Box::new(0i32) => &[Token::I32(0)],
}
test_boxed_slice {
Box::new([0, 1, 2]) => &[
Token::SeqArrayStart(3),
Token::SeqSep,
Token::I32(0),
Token::SeqSep,
Token::I32(1),
Token::SeqSep,
Token::I32(2),
Token::SeqEnd,
],
}
test_net_ipv4addr {
"1.2.3.4".parse::<net::Ipv4Addr>().unwrap() => &[Token::Str("1.2.3.4")],
}
test_net_ipv6addr {
"::1".parse::<net::Ipv6Addr>().unwrap() => &[Token::Str("::1")],
}
test_net_socketaddr {
"1.2.3.4:1234".parse::<net::SocketAddr>().unwrap() => &[Token::Str("1.2.3.4:1234")],
"1.2.3.4:1234".parse::<net::SocketAddrV4>().unwrap() => &[Token::Str("1.2.3.4:1234")],
"[::1]:1234".parse::<net::SocketAddrV6>().unwrap() => &[Token::Str("[::1]:1234")],
}
test_path {
Path::new("/usr/local/lib") => &[
Token::Str("/usr/local/lib"),
],
}
test_path_buf {
PathBuf::from("/usr/local/lib") => &[
Token::Str("/usr/local/lib"),
],
}
}
#[cfg(feature = "nightly")]
#[test]
fn test_net_ipaddr() {
assert_ser_tokens(
"1.2.3.4".parse::<net::IpAddr>().unwrap(),
&[Token::Str("1.2.3.4")],
);
}
#[test]
fn test_cannot_serialize_paths() {
let path = unsafe {
str::from_utf8_unchecked(b"Hello \xF0\x90\x80World")
};
assert_ser_tokens_error(
&Path::new(path),
&[],
Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned()));
let mut path_buf = PathBuf::new();
path_buf.push(path);
assert_ser_tokens_error(
&path_buf,
&[],
Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned()));
}