Compare commits

...

247 Commits

Author SHA1 Message Date
David Tolnay 9338c4f1b9 Release 0.8.21 2016-12-24 13:10:24 -05:00
David Tolnay 28d67f4172 Format variant-skip message only if variant is skipped 2016-12-24 13:10:06 -05:00
David Tolnay 2401ae61a8 Update to syntex 0.52 2016-12-24 12:42:23 -05:00
David Tolnay 57d3fce0c6 Further simplify variant serialization patterns 2016-12-24 12:28:46 -05:00
David Tolnay a020cceed8 Simplify variant serialize patterns 2016-12-24 12:22:45 -05:00
David Tolnay 49e985eb90 Update message for skipped enum variant 2016-12-24 12:16:28 -05:00
David Tolnay 63def96c66 Merge pull request #653 from shinglyu/skip_se
Implement skip_serializing for enum variant
2016-12-24 11:40:21 -05:00
Shing Lyu 2fea8c9c28 Implement skip_serializing for enum variant 2016-12-24 22:34:22 +08:00
David Tolnay 2c984980a0 Link to release notes from readme 2016-12-22 21:52:37 -05:00
David Tolnay 36f07912b8 Remove no-longer-necessary cfg
This was fixed in Rust, allowing proc macro crates to be tested.
2016-12-17 17:32:11 -08:00
David Tolnay 7222cf7514 Ignore warning from unused enum variant 2016-12-17 17:31:11 -08:00
David Tolnay 08c59a2e0e Release 0.8.20 2016-12-16 07:58:52 -08:00
David Tolnay 4a0bf4de65 Merge pull request #641 from shinglyu/deser_enum
Implemented skip_deserializing for enum
2016-12-16 07:53:34 -08:00
Shing Lyu 95ffca9bbe Implemented skip_deserializing for enum 2016-12-16 20:29:21 +08:00
David Tolnay 5e47c87ba0 Add test for deserializing unit to string 2016-12-01 04:46:29 -08:00
David Tolnay c6d5d9be14 Merge pull request #635 from serde-rs/oli-obk-patch-1
Enable deserializing an empty `String` from a unit value
2016-12-01 07:46:07 -05:00
Oliver Schneider d63d09f4db Enable deserializing an empty String from a unit value 2016-12-01 11:23:12 +01:00
David Tolnay de6d00c306 Merge pull request #628 from serde-rs/str
Do not copy tokens to String after expanding
2016-11-24 17:33:19 -05:00
David Tolnay 5bda95ba81 Do not copy tokens to String after expanding 2016-11-24 13:07:47 -08:00
David Tolnay 36641e7b81 Release 0.8.19 2016-11-23 09:14:03 -08:00
David Tolnay 6eca34c45c Drop libsyntax 2016-11-23 09:13:21 -08:00
David Tolnay 7efa0153b0 Drop testing on rust 1.10 2016-11-19 15:24:40 -08:00
David Tolnay 8dba87661b Bump serde_codegen_internals because it failed to publish somehow 2016-11-19 11:47:19 -08:00
David Tolnay 17fb4cb503 Release 0.8.18 2016-11-19 11:40:00 -08:00
David Tolnay 5bd0386b8e Merge pull request #618 from serde-rs/up
Ask proc_macro_derive to ignore serde attributes
2016-11-19 14:19:15 -05:00
David Tolnay 8b484c9703 Hide the serde_codegen functions from docs 2016-11-15 21:37:19 -05:00
David Tolnay a16f07858b Ask proc_macro_derive to ignore serde attributes 2016-11-15 21:29:34 -05:00
David Tolnay 133d117bf4 Bump post-expansion dependency 2016-11-07 11:16:14 -08:00
David Tolnay e7f3a80867 Update serde codegen to syn 0.10 2016-11-02 22:58:55 -07:00
David Tolnay f8c3d225a3 Shorten the syn meta item matches 2016-11-02 22:56:27 -07:00
David Tolnay 6d40d9e8ec Update codegen internals to syn 0.10 2016-11-02 22:52:20 -07:00
David Tolnay c91fca19e1 Release 0.8.17 2016-11-02 09:26:04 -07:00
David Tolnay f13a805530 Merge pull request #605 from serde-rs/up
Bump syntex to 0.48
2016-11-02 09:24:55 -07:00
David Tolnay 54802983b8 Bump syntex to 0.48 2016-11-02 09:12:22 -07:00
David Tolnay f430d9d1c8 Remove unneeded type ascription 2016-10-23 21:06:50 -07:00
David Tolnay c9612a2f57 Release 0.8.16 2016-10-22 00:07:27 -07:00
David Tolnay 7ffea5a716 Bump syntex to 0.46 2016-10-21 23:38:27 -07:00
David Tolnay c8c9f7d96c Merge pull request #599 from TheCatPlusPlus/master
Explictly discard result of visiting IgnoredAny
2016-10-21 23:36:57 -07:00
Cat Plus Plus f75d286b90 Explictly discard result of visiting IgnoredAny
Makes the code generated by `derive(Deserialize)` compile cleanly when
`unused_results` lint is enabled.
2016-10-22 08:00:44 +02:00
David Tolnay 9acb17ab54 Release 0.8.15 2016-10-20 08:42:40 -07:00
David Tolnay f15ff1868e Merge pull request #597 from serde-rs/cov
Drop coveralls
2016-10-20 00:44:19 -07:00
David Tolnay 86f0d0382f Drop coveralls
Has not been uploading for months.
2016-10-20 00:33:03 -07:00
David Tolnay 8595b25763 Merge pull request #592 from serde-rs/post
Use post-expansion crate to let other custom derives see serde attrs
2016-10-20 00:18:23 -07:00
David Tolnay 49aca521f1 Bump post-expansion dependency 2016-10-20 00:01:14 -07:00
David Tolnay 4c38bd0180 Merge branch origin/master into origin/post 2016-10-19 23:59:53 -07:00
Homu 02c4ff7b7e Auto merge of #594 - serde-rs:expr, r=oli-obk
No longer need `e!`

This compiles all the way back to Rust 1.7.0, and 1.6.0 fails for other reasons so I think we are clear here. The referenced issue https://github.com/rust-lang/rust/issues/19630 is still open so they must have fixed it some other way.
2016-10-19 18:07:10 +09:00
David Tolnay a8d1c0253a Merge pull request #593 from serde-rs/rmbench
Remove benchmarks
2016-10-19 00:48:05 -07:00
David Tolnay bb5370b746 No longer need e! 2016-10-19 00:30:23 -07:00
David Tolnay 536e78a146 Remove benchmarks
Nobody noticed these did not compile for 3 months, so I am guessing nobody
cares. The JSON benchmarks at https://github.com/serde-rs/json-benchmark are
much more relevant.
2016-10-18 22:19:10 -07:00
David Tolnay 21c9446890 Update benchmarks to serde 0.8 2016-10-18 22:15:54 -07:00
David Tolnay 1b42f3f594 Release 0.8.14 2016-10-18 21:42:39 -07:00
David Tolnay cafa02d9b4 Merge pull request #591 from serde-rs/sess
Not safe to share Spans from one ParseSess to another
2016-10-18 21:41:05 -07:00
David Tolnay a9b6cbb8b3 Use post-expansion crate to let other custom derives see serde attrs 2016-10-18 09:00:33 -07:00
David Tolnay 1d719b542c Not safe to share Spans from one ParseSess to another
Spans in the AST returned by `parse_item_from_source_str` and other parsing
functions contain byte offsets into the source code they were parsed from. The
pretty printer uses these Spans [here][1] to preserve the representation of
literals when parsing and printing back out unmodified.

In this bug, the byte offset of a string in the input to
`parse_item_from_source_str` coincidentally matched the byte offset of a totally
different string in the input to `parse_crate_from_file` called [here][2] by
Syntex. The Span from the former triggered the pretty printer to write out the
content of the latter.

By using the same ParseSess, Spans from the two `parse_*` calls never collide.

[1]: https://github.com/rust-lang/rust/blob/1.12.0/src/libsyntax/print/pprust.rs#L628
[2]: https://github.com/serde-rs/syntex/blob/v0.45.0/syntex/src/registry.rs#L134
2016-10-17 23:12:32 -07:00
David Tolnay 532b950971 Release 0.8.13 2016-10-16 10:34:26 -07:00
Erick Tryzelaar f93b4e91e6 Version bump serde_derive to 0.8.13 2016-10-15 15:24:37 -07:00
Erick Tryzelaar 94e2ccc94e Merge pull request #588 from erickt/master
Drop support for rust 1.8.0 and 1.9.0.
2016-10-15 15:12:56 -07:00
Erick Tryzelaar cbe6b4c97c Drop support for rust 1.8.0 and 1.9.0. 2016-10-15 14:43:30 -07:00
Erick Tryzelaar a46a4e27dd Merge pull request #587 from erickt/master
Update syntex version to 0.45.0
2016-10-15 14:43:13 -07:00
Erick Tryzelaar 4919a3184d Update syntex version to 0.45.0 2016-10-15 14:01:14 -07:00
David Tolnay 0b19608d85 Merge pull request #584 from serde-rs/array-tuple
Array and tuple deserialization cleanup
2016-10-14 08:43:08 -07:00
David Tolnay 99bddddd8e Array and tuple deserialization cleanup 2016-10-14 00:15:24 -07:00
David Tolnay 85c95040b3 Release 0.8.12 2016-10-08 15:38:29 -07:00
David Tolnay 339c0f5493 Remove unneeded test feature 2016-10-08 15:36:46 -07:00
David Tolnay b4d5c26f4e Update to latest syn and quote 2016-10-08 15:36:02 -07:00
David Tolnay f4e1ffa2cb Merge pull request #578 from mjroghelia/rename_rustc_macro
Rename rustc_macro to proc_macro
2016-10-08 15:35:15 -07:00
Mark Roghelia ef5d09e144 Rename rustc_macro to proc_macro
Fixes #575
2016-10-08 18:29:36 -04:00
David Tolnay e547a06639 Simplify deserialize_field_visitor 2016-10-03 13:45:11 -07:00
David Tolnay c61b20cceb Release 0.8.11 2016-10-03 13:38:52 -07:00
David Tolnay 42987a5b24 Fix break in quote 0.2.2 2016-10-03 13:37:46 -07:00
David Tolnay 3f28a93240 Update readme to serde_derive 2016-09-29 09:21:01 -07:00
David Tolnay 9970084550 Merge pull request #568 from tbu-/pr_ipaddr_stable
Allow the use of `IpAddr` implementations on stable
2016-09-29 08:58:33 -07:00
Tobias Bucher 3920993370 Allow the use of IpAddr implementations on stable
Also use the same strategy for serialization as for deserialization of
`IpAddr`.

Fixes #551.
2016-09-29 15:48:59 +02:00
David Tolnay 22690cedc2 Merge pull request #566 from serde-rs/del
Delete serde_macros
2016-09-28 13:32:02 -07:00
David Tolnay b27039d34d Compiletest error messages 2016-09-28 12:46:54 -07:00
David Tolnay 1b6fd5a362 Delete serde_macros 2016-09-28 11:59:25 -07:00
David Tolnay 8b7b886036 Test serde_derive instead of serde_macros 2016-09-28 11:19:27 -07:00
David Tolnay 2a2c098eeb Release 0.8.10 2016-09-28 09:56:15 -07:00
David Tolnay f68f32d3ee Merge pull request #564 from serde-rs/cleanup
Clean up syn workarounds
2016-09-28 09:48:45 -07:00
David Tolnay 6ccb6c9130 Clean up syn workarounds 2016-09-28 09:29:12 -07:00
David Tolnay 49d24a1377 Merge pull request #548 from serde-rs/syn
No more syntex for serde_derive
2016-09-28 09:28:48 -07:00
David Tolnay b0eee50947 Merge branch origin/master into origin/syn
Conflicts:
    serde_macros/tests/compile-fail/reject-unknown-attributes.rs
2016-09-28 09:27:04 -07:00
David Tolnay 554b81d636 Fix compiletest error in newest nightly 2016-09-28 09:25:19 -07:00
David Tolnay 9fe16767c5 Use iter::repeat to build phantom exprs 2016-09-28 08:57:53 -07:00
David Tolnay 3a3777a2fb Merge branch origin/master into origin/syn
Conflicts:
    serde_codegen/Cargo.toml
2016-09-27 09:59:36 -07:00
David Tolnay effa298871 Fix differences in the generated code 2016-09-27 09:56:35 -07:00
David Tolnay 9a86e6818f Use push_str to support old compilers 2016-09-27 00:47:54 -07:00
David Tolnay 7d09b1475c Fix clippy lints in serde_codegen 2016-09-27 00:46:03 -07:00
David Tolnay 7e441e5110 Handle various attribute parsing error cases 2016-09-27 00:40:37 -07:00
David Tolnay 40b874214a Update tests to new location of errors 2016-09-27 00:17:00 -07:00
David Tolnay 0c18c151e2 Revamp serde_codegen_internals error handling 2016-09-27 00:11:37 -07:00
David Tolnay 4ad6c4fd56 Include unknown attribute name in error message 2016-09-27 00:02:15 -07:00
David Tolnay 8ee8c07090 Mark all serde attributes as used 2016-09-26 23:17:43 -07:00
David Tolnay 8e77960e3a Remove with-libsyntax feature 2016-09-26 23:17:33 -07:00
David Tolnay 819d47fea2 Merge pull request #560 from serde-rs/up
Bump quasi and aster
2016-09-26 22:23:18 -07:00
David Tolnay 8e865f62c4 Fix conflicts with the __serde_state commit 2016-09-26 22:13:53 -07:00
David Tolnay 6cbf0d32da Merge branch origin/master into origin/syn
Conflicts:
    serde_codegen/src/ser.rs
2016-09-26 22:11:14 -07:00
David Tolnay 20afa85087 Bump quasi and aster 2016-09-26 22:08:21 -07:00
David Tolnay da6d967776 Merge pull request #558 from erickt/fix-serde-state
Make serde state variable unique by naming it __serde_state
2016-09-26 21:58:45 -07:00
Erick Tryzelaar f47a50e996 Make serde state variable unique by naming it __serde_state
Closes #557
2016-09-26 21:44:30 -07:00
David Tolnay 1eca7766ba Bump syn dependency 2016-09-24 09:54:10 -07:00
David Tolnay 51f95575ec Merge branch origin/master into origin/syn
Conflicts:
    serde_codegen/Cargo.toml
    serde_codegen_internals/Cargo.toml
    serde_derive/Cargo.toml
2016-09-24 09:29:21 -07:00
Oliver Schneider 429de89276 Release 0.8.9 2016-09-23 07:11:59 -07:00
David Tolnay a69b82c7c5 Recursion limit 2016-09-12 01:26:47 -07:00
David Tolnay 55e5f19437 Same for deserialization 2016-09-12 00:50:30 -07:00
David Tolnay c34baa1e5f No more syntex for serde_derive 2016-09-11 19:55:13 -07:00
David Tolnay 7cc36a9cd3 Release 0.8.8 2016-09-08 08:34:20 -07:00
Homu d343017f47 Auto merge of #546 - serde-rs:qual, r=oli-obk
Result needs to be fully qualified

Without this:

```
error[E0244]: wrong number of type arguments
  --> src/api/accounts.rs:19:10
   |
19 | #[derive(Serialize, Deserialize, Debug)]
   |          ^^^^^^^^^^ expected 1 type arguments, found 2
```
2016-09-08 18:05:36 +09:00
David Tolnay 2212bfbf2c Result needs to be fully qualified
Without this:

```
error[E0244]: wrong number of type arguments
  --> src/api/accounts.rs:19:10
   |
19 | #[derive(Serialize, Deserialize, Debug)]
   |          ^^^^^^^^^^ expected 1 type arguments, found 2
```
2016-09-07 16:37:26 -07:00
David Tolnay e85ca8411e Release 0.8.7 2016-09-05 09:39:27 -07:00
Homu 1ff2053262 Auto merge of #536 - serde-rs:mutempty, r=oli-obk
Fix "variable does not need to be mutable" warning

Fixes #534.

cc @EliDupree
2016-09-06 01:10:43 +09:00
Homu bf779ea343 Auto merge of #525 - serde-rs:forward, r=oli-obk
Expose forward_to_deserialize macro

Fixes #522.

```rust
impl Deserializer for MyDeserializer {
    fn deserialize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
        where V: Visitor
    {
        /* ... */
    }

    forward_to_deserialize! {
        bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
        unit option seq seq_fixed_size bytes map unit_struct newtype_struct
        tuple_struct struct struct_field tuple enum ignored_any
    }
}
```

cc @nox
2016-09-06 00:37:18 +09:00
David Tolnay 8fe66c7f2a Merge pull request #520 from serde-rs/bytes
Add constructors for Bytes and ByteBuf
2016-09-05 08:37:10 -07:00
David Tolnay e03dedabe4 Use peekable iterator to check for nonzero serialized fields 2016-09-05 08:22:17 -07:00
David Tolnay 08bc2d2e76 Use constructors to create Bytes and ByteBuf 2016-09-05 08:09:23 -07:00
David Tolnay 35be61d85f Resolve merge conflict 2016-09-05 08:02:35 -07:00
David Tolnay 3692edfd08 Merge branch serde-rs/master into serde-rs/forward 2016-09-05 07:59:42 -07:00
Homu 5a258ade27 Auto merge of #527 - serde-rs:seqvisitor, r=oli-obk
Impl SeqVisitor for MapDeserializer

@nox is this what you were trying to implement?
2016-09-05 20:09:44 +09:00
Homu f3052c392e Auto merge of #538 - serde-rs:notfalse, r=oli-obk
Remove `if !false { ... }` from generated serialization code

I don't think this negatively affects maintainability of the code in serde_codegen and I think there is some value in keeping our generated code relatively clear so that people can use it as a template when implementing Serialize manually with minor modifications.
2016-09-05 19:52:43 +09:00
David Tolnay d1ce4d62c9 Change to expression so that syntex keeps the semicolon 2016-09-02 18:07:26 -07:00
David Tolnay 869ebd9e4e Remove if !false { ... } from generated serialization code 2016-09-02 17:22:58 -07:00
David Tolnay 14446af537 Fix "variable does not need to be mutable" warning 2016-09-02 11:42:33 -07:00
David Tolnay 248d937f9a Release 0.8.6 2016-09-01 22:06:27 -07:00
David Tolnay ffa2f80186 Merge pull request #530 from serde-rs/derive
Macros 1.1
2016-09-01 21:59:32 -07:00
David Tolnay ac1128a647 Update serde_derive to 0.8.5 2016-09-01 21:28:58 -07:00
David Tolnay 88d845c4d1 Include! test suite for serde_derive 2016-09-01 21:28:40 -07:00
David Tolnay 87a402a751 Remove rustc_macro test crate 2016-09-01 11:17:35 -07:00
David Tolnay cdb0e6c899 Remove build script in favor of rust-lang/cargo#3064 2016-08-31 21:05:40 -07:00
David Tolnay 54cee86fd3 Bump to 0.8.5 2016-08-31 20:14:44 -07:00
David Tolnay 178edd1abc Merge branch origin/master into origin/derive 2016-08-31 20:12:46 -07:00
David Tolnay 4bb9279074 Bump syntex to 0.43 2016-08-31 12:53:27 -07:00
David Tolnay 3c45e5c7a5 Next iteration 2016-08-30 23:55:08 -07:00
David Tolnay d36f28971c Support no_std in forward_to_deserialize macro 2016-08-29 00:27:11 -07:00
David Tolnay d914fdf67b Macros 1.1 2016-08-28 22:21:25 -07:00
David Tolnay 7014c105b4 Remove coverage shield 2016-08-28 08:39:53 -07:00
David Tolnay f3d566af09 Remove clippy shield 2016-08-28 08:37:55 -07:00
David Tolnay 278e8eb720 Add deserialize_seq methods to MapDeserializer 2016-08-25 10:45:25 -04:00
David Tolnay e9b04de9a5 Impl SeqVisitor for MapDeserializer 2016-08-25 10:12:23 -04:00
David Tolnay 2a2891d54b Expose forward_to_deserialize macro 2016-08-24 00:16:22 -04:00
David Tolnay 123e040189 Merge pull request #524 from serde-rs/skeptic
Remove skeptic
2016-08-23 22:17:13 -04:00
David Tolnay 6f0f273d9c Remove skeptic 2016-08-23 22:04:50 -04:00
David Tolnay fb7ba225d1 Add constructors for Bytes and ByteBuf
This commit adds `Bytes::new(&[u8])` and `ByteBuf::from<T: Into<Vec<u8>>>(T)`.
2016-08-23 16:24:00 -04:00
David Tolnay d690ffda8d Release 0.8.4 2016-08-22 11:37:53 -04:00
David Tolnay 18a775277f Merge pull request #514 from nox/maps
Introduce MapDeserializer::unbounded (fixes #512)
2016-08-22 09:05:50 -04:00
Anthony Ramine fbb250766d Introduce MapDeserializer::unbounded (fixes #512) 2016-08-22 09:11:10 +02:00
David Tolnay 71116b860a Merge pull request #513 from nox/cow
Implement ValueDeserializer for Cow<str>
2016-08-21 14:07:56 -04:00
Anthony Ramine ce3f134145 Implement ValueDeserializer for Cow<str> 2016-08-21 19:52:13 +02:00
David Tolnay 80507d650c Merge pull request #511 from serde-rs/extra
Switch to syntex::with_extra_stack
2016-08-19 21:27:17 -04:00
David Tolnay 0ae61a3dd1 Switch to syntex::with_extra_stack 2016-08-19 21:09:55 -04:00
David Tolnay 5fb73073bd Release 0.8.3 2016-08-19 13:11:59 -04:00
David Tolnay 63d484d50c Merge pull request #510 from serde-rs/clippy
Re-enable clippy
2016-08-19 13:01:24 -04:00
David Tolnay f3f29f81bc Fix new lints 2016-08-19 12:46:45 -04:00
David Tolnay 621588b258 Revert "Disable clippy until Manishearth/rust-clippy#1174 is fixed"
This reverts commit 2bc1d62e50.
2016-08-19 11:47:31 -04:00
Homu 7aba920dec Auto merge of #509 - serde-rs:cow, r=oli-obk
Fix codegen with lifetimes but no type parameters

Fixes #507.
2016-08-20 00:16:54 +09:00
David Tolnay a732b9bad3 Fix codegen with lifetimes but no type parameters 2016-08-19 11:12:38 -04:00
Oliver Schneider 6723da67b3 Merge pull request #506 from serde-rs/https
HTTPS for serde.rs
2016-08-19 10:57:52 +02:00
David Tolnay 2d99a50c27 HTTPS for serde.rs 2016-08-18 17:08:05 -04:00
David Tolnay 01f6115d73 Merge pull request #503 from serde-rs/stack
Set RUST_MIN_STACK if unset
2016-08-18 16:09:09 -04:00
David Tolnay a4eb9d5788 Merge pull request #499 from serde-rs/ord
Simplify BTreeMapVisitor trait bounds
2016-08-18 15:44:03 -04:00
David Tolnay 6f77ea58fd Merge branch origin/master into origin/stack 2016-08-18 15:26:14 -04:00
David Tolnay 2cb55e8cb9 Merge branch origin/master into origin/ord 2016-08-18 15:25:47 -04:00
David Tolnay 671f5ebd07 Path override to prevent compiletest from seeing 2 versions of serde 2016-08-18 15:05:07 -04:00
David Tolnay 2bc1d62e50 Disable clippy until Manishearth/rust-clippy#1174 is fixed 2016-08-18 14:51:25 -04:00
David Tolnay 1796536962 Update syntex to 0.41 2016-08-18 14:33:14 -04:00
David Tolnay dba1377d1f Set RUST_MIN_STACK if unset 2016-08-18 13:55:58 -04:00
Oliver Schneider ce66b230e3 Merge pull request #502 from serde-rs/help
Getting help
2016-08-18 17:08:30 +02:00
David Tolnay affc81b1d6 Getting help 2016-08-18 10:56:41 -04:00
Oliver Schneider c3ec05f410 Merge pull request #501 from serde-rs/readme
Condense readme and link to serde.rs
2016-08-18 13:22:53 +02:00
David Tolnay 332d59f362 Condense readme and link to serde.rs 2016-08-18 01:11:36 -04:00
David Tolnay d98172f330 Simplify BTreeMapVisitor trait bounds
`Ord` implies `Eq`.
2016-08-17 23:11:38 -04:00
David Tolnay e0c9bd4b87 Remove doc-upload 2016-08-13 19:15:48 -07:00
David Tolnay 33d26c6d38 Remove CNAME
This is now managed by github.com/serde-rs/docs.
2016-08-13 17:54:56 -07:00
David Tolnay 0557a7feac Point links to docs.serde.rs 2016-08-13 15:01:57 -07:00
Oliver Schneider d46db730ff Merge pull request #490 from bluss/patch-1
Adjust doc(html_root_url)
2016-08-12 15:59:18 +02:00
bluss 07b1acc9f5 Adjust doc(html_root_url)
The URL does not need to contain the crate name. With this URL rustdoc can generate correct external doc links.
2016-08-12 15:53:07 +02:00
David Tolnay 85864e6ccb Bump remaining versions to 0.8.1 2016-08-11 09:16:29 -07:00
David Tolnay 1f31bb2db9 Merge pull request #489 from oli-obk/docs
fix an example in the README
2016-08-11 08:41:59 -07:00
Oliver Schneider 6b5bd24edd fix an example in the README (thanks @nox) 2016-08-11 13:57:43 +02:00
Oliver Schneider 8c2359f9c3 also publish build.rs 2016-08-11 11:38:44 +02:00
Oliver Schneider f59ec44a0b Merge pull request #488 from oli-obk/codegen_stack_overflow_hack
use a thread in the build script of serde_codegen to allow env vars to control the stack size
2016-08-11 11:28:53 +02:00
Oliver Schneider b7446db511 reintroduce path dependencies 2016-08-11 11:02:19 +02:00
Oliver Schneider 8bd7acc9fc use a thread in the build script of serde_codegen to allow env vars to control the stack size 2016-08-09 13:08:16 +02:00
Homu d120539310 Auto merge of #478 - serde-rs:visitor, r=oli-obk
Simplify generated visitors

Neither `__FieldVisitor` nor `__Visitor` need the `__D: Deserializer` type parameter.
2016-08-08 19:52:36 +09:00
Oliver Schneider 82098f4e49 Merge pull request #476 from serde-rs/duration
Serialize and Deserialize for std::time::Duration
2016-08-04 09:29:14 +02:00
Oliver Schneider 1c55f58093 Merge pull request #479 from serde-rs/nestser
Remove unnecessary nesting from generated impls
2016-08-04 09:08:59 +02:00
Oliver Schneider df3c3cb555 Merge pull request #477 from serde-rs/iter
Fix clippy lint about looping over iter()
2016-08-04 08:48:35 +02:00
David Tolnay c539563687 Remove unnecessary nesting fron generated Deserialize implementations 2016-08-03 21:08:17 -07:00
David Tolnay 69de46f9e0 Remove unnecessary nesting from generated Serialize implementations 2016-08-03 20:40:57 -07:00
David Tolnay d5102a7afd Simplify generated visitors 2016-08-03 19:56:47 -07:00
David Tolnay c4b5a42615 Serialize and Deserialize for std::time::Duration 2016-08-03 19:33:31 -07:00
David Tolnay d0502b93ef Fix clippy lint about looping over iter() 2016-08-03 19:32:51 -07:00
David Tolnay b289edd4a4 Merge pull request #475 from serde-rs/skeptic
use skeptic to test the readme and fix readme for 0.8
2016-08-03 07:49:30 -07:00
Oliver Schneider 3a687e5369 fix untestable docs 2016-08-03 16:04:11 +02:00
Oliver Schneider 8c30ec9698 fix doc bugs found by skeptic 2016-08-03 16:00:30 +02:00
Oliver Schneider e40b9e9814 fix skeptic 2016-08-03 16:00:20 +02:00
Erick Tryzelaar 22d0bdae8a tests(readme): Use skeptic to test the readme 2016-08-03 15:44:47 +02:00
David Tolnay 84fa3fba58 Fix feature name in serde-syntex-example readme 2016-07-31 15:47:46 -07:00
Oliver Schneider 85001608e0 Merge pull request #473 from serde-rs/docs
Generate docs from 'docs' branch instead of master
2016-07-31 12:04:12 +02:00
David Tolnay 09fe2dbba5 Generate docs from 'docs' branch instead of master 2016-07-30 16:45:47 -07:00
Oliver Schneider b6ed82dd7d Merge pull request #472 from serde-rs/exact
Use exact dependencies on other serde crates
2016-07-30 21:12:20 +02:00
David Tolnay 5bbeedadf2 Constrain only the two important dependencies 2016-07-30 08:43:33 -07:00
David Tolnay d786de6696 Use exact dependencies on other serde crates 2016-07-29 15:12:54 -07:00
David Tolnay 5d24d6cfb4 Merge pull request #471 from serde-rs/example
Re-enable serde-syntex-example build in Travis
2016-07-29 10:06:20 -07:00
David Tolnay c8c22c036f Re-enable serde-syntex-example build in Travis 2016-07-29 09:53:44 -07:00
David Tolnay b7f30d7f82 Use build() instead of unwrap() for the Builders
Fixes #429.
2016-07-29 09:48:55 -07:00
David Tolnay 4bf5a15d7e Merge pull request #469 from killercup/patch-1
Set explicit versions in Readme
2016-07-28 05:23:56 -07:00
Pascal Hertleif f394f25956 Set explicit versions in Readme 2016-07-28 10:34:55 +02:00
David Tolnay 9d96f95ddd Remove old upgrading tips 2016-07-27 23:51:48 -07:00
David Tolnay f12f640590 Release 0.8.0 2016-07-27 22:07:57 -07:00
David Tolnay d02e959b3f Merge pull request #468 from sfackler/split-map
Split serialize_map_elt
2016-07-27 12:50:42 -07:00
Steven Fackler ea833d3427 Split serialize_map_elt
Like what's been done on the deserialization side with MapVisitor, this
allows some weirder uses of Serde to handle the key and value in
separate steps.
2016-07-27 12:12:07 -07:00
David Tolnay 78e74886be Update syntex to 0.39 2016-07-26 09:22:33 -07:00
Oliver Schneider 061a1d8a8c Merge pull request #465 from serde-rs/underscore
Remove underscore from parameter names in deserializer traits
2016-07-26 08:25:15 +02:00
David Tolnay de9fd3b04e Remove underscore from parameter names in deserializer traits
This makes the generated rustdoc easier to read.
2016-07-25 20:18:45 -07:00
David Tolnay e36f33589c Release 0.8.0-rc3 2016-07-23 15:13:19 -07:00
Homu a892a13473 Auto merge of #462 - jimmycuadra:ser-error-docstring, r=oli-obk
Fix typos in docstring of ser::Error.

Just a minor documentation fix for grammar and and a copy/paste error.
2016-07-23 17:07:46 +09:00
Jimmy Cuadra 556d5bdc27 Fix typos in docstring of ser::Error. 2016-07-23 00:56:55 -07:00
Homu c6acec29e5 Auto merge of #459 - serde-rs:phantom, r=oli-obk
PhantomData<T> does not require bounds on T
2016-07-23 01:43:45 +09:00
David Tolnay dce02c624b Merge pull request #460 from serde-rs/revert
Revert "Mention Empty Bounds for Recursion in Readme"
2016-07-22 09:13:53 -07:00
David Tolnay 77e56613a5 Revert "Mention Empty Bounds for Recursion in Readme"
This reverts commit 93968455f3.
2016-07-22 09:09:23 -07:00
David Tolnay 3b7fa47b2e PhantomData<T> does not require bounds on T 2016-07-22 09:05:43 -07:00
David Tolnay f5fd7f5950 Merge pull request #458 from serde-rs/testgen
Add tests for concrete instantiations in test_gen
2016-07-22 09:04:33 -07:00
David Tolnay fb6fc4e19f Add tests for concrete instantiations in test_gen 2016-07-22 08:49:51 -07:00
David Tolnay 85772726ee Merge pull request #456 from serde-rs/generic
Generate bounds on type parameters only
2016-07-22 07:58:56 -07:00
Oliver Schneider f05ba9fdf2 unhygienize the generic parameter comparison
include! completely messes up the identifiers' expansion info
2016-07-22 14:09:14 +02:00
Homu 2e829ae4e6 Auto merge of #457 - serde-rs:phantom, r=oli-obk
Impl Deserialize for PhantomData<T> for all T
2016-07-22 16:31:51 +09:00
David Tolnay 25a5dd1579 Impl Deserialize for PhantomData<T> for all T 2016-07-21 23:22:38 -07:00
David Tolnay 1831b471f9 Generate bounds on type parameters only 2016-07-21 23:06:18 -07:00
Oliver Schneider 49ff56aa15 Merge pull request #452 from oli-obk/pure_interface
Pure interface for Deserializer
2016-07-21 11:25:16 +02:00
Oliver Schneider 89549e2567 fix nightly 2016-07-21 10:49:02 +02:00
Oliver Schneider 124bacd871 fix for 1.8, 1.9 and stable 2016-07-21 10:11:04 +02:00
Oliver Schneider 4280dd466d rename deserialize_fixed_size_array to deserialize_seq_fixed_size 2016-07-20 19:20:31 +02:00
Oliver Schneider 65eb116a85 address comments 2016-07-20 19:18:45 +02:00
Homu e15940f355 Auto merge of #454 - nox:boxed, r=oli-obk
Implement Deserialize for Box<str>
2016-07-20 19:49:11 +09:00
Anthony Ramine 68440952ab Implement Deserialize for Box<str> 2016-07-20 12:47:08 +02:00
Oliver Schneider d751b4c39a Merge pull request #451 from killercup/doc/recursive-bounds
Mention Empty Bounds for Recursion in Readme
2016-07-20 10:43:54 +02:00
Oliver Schneider d10a69b243 document some hints for defaults 2016-07-20 10:42:14 +02:00
Pascal Hertleif 1a1b6fbf85 Fix Typo in Readme 2016-07-20 10:39:57 +02:00
Pascal Hertleif 93968455f3 Mention Empty Bounds for Recursion in Readme
Fixes #427
2016-07-20 10:39:57 +02:00
Oliver Schneider 4722571a4d make VariantVisitor pure 2016-07-20 10:33:28 +02:00
Oliver Schneider 36a7bf6244 make Deserializer pure 2016-07-20 10:26:31 +02:00
David Tolnay 89f0ad99a6 Merge pull request #449 from oli-obk/docs
add more extensive docs
2016-07-18 07:09:20 -07:00
Oliver Schneider 05ad8662e2 add more extensive docs 2016-07-18 16:08:07 +02:00
Oliver Schneider 15c09a8d2c Merge pull request #448 from laktak/hjson
add Hjson
2016-07-18 13:04:02 +02:00
Christian Zangl 80a27cbb4a add Hjson 2016-07-18 12:06:21 +02:00
David Tolnay 13e1a129dd Ignore unused struct in test_gen.rs 2016-07-17 21:10:05 -07:00
David Tolnay 334a6e788a Remove commented code in test_macros.rs 2016-07-17 21:09:44 -07:00
70 changed files with 2991 additions and 5460 deletions
-7
View File
@@ -1,7 +0,0 @@
paths = [
"serde",
"serde_codegen",
"serde_codegen_internals",
"serde_macros",
"serde_test",
]
+6 -16
View File
@@ -1,17 +1,11 @@
sudo: false
language: rust
rust:
- 1.11.0
- 1.12.0
- stable
- nightly
- 1.8.0
- 1.9.0
- beta
addons:
apt:
packages:
- libcurl4-openssl-dev
- libelf-dev
- libdw-dev
- nightly
before_script:
- pip install 'travis-cargo<0.2' --user
- export PATH=$HOME/.local/bin:$PATH
@@ -24,14 +18,10 @@ script:
- (cd serde && travis-cargo --only nightly build -- --no-default-features --features collections)
- (cd testing && travis-cargo --skip nightly test)
- (cd testing && travis-cargo --only nightly test -- --features unstable-testing)
- (cd serde_macros && travis-cargo --only nightly test -- --features unstable-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 unstable)
- (cd serde_derive && travis-cargo --only nightly test)
- (cd examples/serde-syntex-example && travis-cargo --skip nightly run)
- (cd examples/serde-syntex-example && travis-cargo --only nightly run -- --no-default-features --features unstable)
- (cd serde && travis-cargo --only stable doc)
after_success:
- (cd serde && travis-cargo --only stable doc-upload)
- (cd testing && travis-cargo --only stable coveralls --no-sudo)
env:
global:
- TRAVIS_CARGO_NIGHTLY_FEATURE=""
- secure: Jcd11Jy0xLyacBUB+oKOaxKBm9iZNInenRDtNBY8GKOtqF5fHUfEjgDf538hwRl5L0FP7DLr8oK0IHmzA7lPjJxlzoKVKV3IM7bRZEYzW5DMonf/lcliuGte7SH0NVFhifM87T8HI2hjGdAb+7+m34siBR7M3AY/XjLInrvUFvY=
+38 -797
View File
@@ -1,215 +1,25 @@
Serde Rust Serialization Framework
==================================
# Serde &emsp; [![Build Status](https://api.travis-ci.org/serde-rs/serde.svg?branch=master)](https://travis-ci.org/serde-rs/serde) [![Latest Version](https://img.shields.io/crates/v/serde.svg)](https://crates.io/crates/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 framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
Serde is a powerful framework that enables serialization libraries to
generically serialize Rust data structures without the overhead of runtime type
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](https://serde-rs.github.io/serde/serde/index.html)
You may be looking for:
Simple Serde Example
====================
- [An overview of Serde](https://serde.rs/)
- [Data formats supported by Serde](https://serde.rs/#data-formats)
- [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/codegen.html)
- [Examples](https://serde.rs/examples.html)
- [API documentation](https://docs.serde.rs/serde/)
- [Release notes](https://github.com/serde-rs/serde/releases)
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
===============================================
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
[package]
name = "serde_example_nightly"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
[dependencies]
serde = "*"
serde_json = "*"
serde_macros = "*"
```
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:
## Serde in action
```rust
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
@@ -222,610 +32,41 @@ struct Point {
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 the same output:
```
% cargo run
{"x":1,"y":2}
Point { x: 1, y: 2 }
```
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:
`Cargo.toml`:
```toml
[package]
name = "serde_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 = "*", optional = true }
[dependencies]
serde = "*"
serde_json = "*"
serde_macros = { version = "*", optional = true }
```
`build.rs`:
```rust,ignore
#[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();
}
```
`src/main.rs`:
```rust,ignore
#![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"));
```
The `src/main.rs.in` is the same as before.
Then to run with stable:
```
% cargo build
...
```
Or with nightly:
```
% cargo build --features nightly --no-default-features
...
```
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/serde/ser/trait.Serializer.html)
and
[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,
Rust is able to remove most or all the visitor state, and generate code that's
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/serde/ser/trait.Serializer.html)
is threaded through the type:
```rust,ignore
impl serde::Serialize for i32 {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: serde::Serializer,
{
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/serde/ser/trait.MapVisitor.html)
to the
[Serializer](http://serde-rs.github.io/serde/serde/serde/ser/trait.Serializer.html)
in order to walk through the type:
```rust,ignore
impl<K, V> Serialize for BTreeMap<K, V>
where K: Serialize + Ord,
V: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
pub struct MapIteratorVisitor<Iter> {
iter: Iter,
len: Option<usize>,
}
impl<K, V, Iter> MapIteratorVisitor<Iter>
where Iter: Iterator<Item=(K, V)>
{
#[inline]
pub fn new(iter: Iter, len: Option<usize>) -> MapIteratorVisitor<Iter> {
MapIteratorVisitor {
iter: iter,
len: len,
}
}
}
impl<K, V, I> MapVisitor for MapIteratorVisitor<I>
where K: Serialize,
V: Serialize,
I: Iterator<Item=(K, V)>,
{
#[inline]
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer,
{
match self.iter.next() {
Some((key, value)) => {
let value = try!(serializer.serialize_map_elt(key, value));
Ok(Some(value))
}
None => Ok(None)
}
}
#[inline]
fn len(&self) -> Option<usize> {
self.len
}
}
```
Serializing structs follow this same pattern. In fact, structs are represented
as a named map. Its visitor uses a simple state machine to iterate through all
the fields:
```rust
extern crate serde;
extern crate serde_json;
struct Point {
x: i32,
y: i32,
}
impl serde::Serialize for Point {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: serde::Serializer
{
serializer.serialize_struct("Point", PointMapVisitor {
value: self,
state: 0,
})
}
}
struct PointMapVisitor<'a> {
value: &'a Point,
state: u8,
}
impl<'a> serde::ser::MapVisitor for PointMapVisitor<'a> {
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: serde::Serializer
{
match self.state {
0 => {
self.state += 1;
Ok(Some(try!(serializer.serialize_struct_elt("x", &self.value.x))))
}
1 => {
self.state += 1;
Ok(Some(try!(serializer.serialize_struct_elt("y", &self.value.y))))
}
_ => {
Ok(None)
}
}
}
}
fn main() {
let point = Point { x: 1, y: 2 };
// Convert the Point to a JSON string.
let serialized = serde_json::to_string(&point).unwrap();
println!("{}", serialized);
}
```
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/serde/de/trait.Deserialize.html)
implementation. It passes a
[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,ignore
impl Deserialize for i32 {
fn deserialize<D>(deserializer: &mut D) -> Result<i32, D::Error>
where D: serde::Deserializer,
{
deserializer.deserialize(I32Visitor)
}
}
struct I32Visitor;
impl serde::de::Visitor for I32Visitor {
type Value = i32;
fn visit_i16<E>(&mut self, value: i16) -> Result<i32, E>
where E: Error,
{
self.visit_i32(value as i32)
}
fn visit_i32<E>(&mut self, value: i32) -> Result<i32, E>
where E: Error,
{
Ok(value)
}
...
```
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/serde/de/trait.Error.html) trait,
which allows a
[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,ignore
...
fn visit_string<E>(&mut self, _: String) -> Result<i32, E>
where E: Error,
{
Err(serde::de::Error::custom("expect a string"))
}
...
```
Maps follow a similar pattern as before, and use a
[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/serde/de/trait.Deserializer.html).
```rust,ignore
impl<K, V> serde::Deserialize for BTreeMap<K, V>
where K: serde::Deserialize + Eq + Ord,
V: serde::Deserialize,
{
fn deserialize<D>(deserializer: &mut D) -> Result<BTreeMap<K, V>, D::Error>
where D: serde::Deserializer,
{
deserializer.deserialize(BTreeMapVisitor::new())
}
}
pub struct BTreeMapVisitor<K, V> {
marker: PhantomData<BTreeMap<K, V>>,
}
impl<K, V> BTreeMapVisitor<K, V> {
pub fn new() -> Self {
BTreeMapVisitor {
marker: PhantomData,
}
}
}
impl<K, V> serde::de::Visitor for BTreeMapVisitor<K, V>
where K: serde::de::Deserialize + Ord,
V: serde::de::Deserialize
{
type Value = BTreeMap<K, V>;
fn visit_unit<E>(&mut self) -> Result<BTreeMap<K, V>, E>
where E: Error,
{
Ok(BTreeMap::new())
}
fn visit_map<V_>(&mut self, mut visitor: V_) -> Result<BTreeMap<K, V>, V_::Error>
where V_: MapVisitor,
{
let mut values = BTreeMap::new();
while let Some((key, value)) = try!(visitor.visit()) {
values.insert(key, value);
}
try!(visitor.end());
Ok(values)
}
}
```
Deserializing structs goes a step further in order to support not allocating a
`String` to hold the field names. This is done by custom field enum that
deserializes an enum variant from a string. So for our `Point` example from
before, we need to generate:
```rust
extern crate serde;
extern crate serde_json;
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
enum PointField {
X,
Y,
}
impl serde::Deserialize for PointField {
fn deserialize<D>(deserializer: &mut D) -> Result<PointField, D::Error>
where D: serde::de::Deserializer
{
struct PointFieldVisitor;
impl serde::de::Visitor for PointFieldVisitor {
type Value = PointField;
fn visit_str<E>(&mut self, value: &str) -> Result<PointField, E>
where E: serde::de::Error
{
match value {
"x" => Ok(PointField::X),
"y" => Ok(PointField::Y),
_ => Err(serde::de::Error::custom("expected x or y")),
}
}
}
deserializer.deserialize(PointFieldVisitor)
}
}
impl serde::Deserialize for Point {
fn deserialize<D>(deserializer: &mut D) -> Result<Point, D::Error>
where D: serde::de::Deserializer
{
static FIELDS: &'static [&'static str] = &["x", "y"];
deserializer.deserialize_struct("Point", FIELDS, PointVisitor)
}
}
struct PointVisitor;
impl serde::de::Visitor for PointVisitor {
type Value = Point;
fn visit_map<V>(&mut self, mut visitor: V) -> Result<Point, V::Error>
where V: serde::de::MapVisitor
{
let mut x = None;
let mut y = None;
loop {
match try!(visitor.visit_key()) {
Some(PointField::X) => { x = Some(try!(visitor.visit_value())); }
Some(PointField::Y) => { y = Some(try!(visitor.visit_value())); }
None => { break; }
}
}
let x = match x {
Some(x) => x,
None => try!(visitor.missing_field("x")),
};
let y = match y {
Some(y) => y,
None => try!(visitor.missing_field("y")),
};
try!(visitor.end());
Ok(Point{ x: x, y: y })
}
}
fn main() {
let serialized = "{\"x\":1,\"y\":2}";
// Prints serialized = {"x":1,"y":2}
println!("serialized = {}", serialized);
// Convert the JSON string back to a Point.
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
println!("{:?}", deserialized);
// Prints deserialized = Point { x: 1, y: 2 }
println!("deserialized = {:?}", deserialized);
}
```
Design Considerations and tradeoffs for Serializers and Deserializers
=====================================================================
## Getting help
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.
Serde developers live in the #serde channel on
[`irc.mozilla.org`](https://wiki.mozilla.org/IRC). The #rust channel is also a
good resource with generally faster response time but less specific knowledge
about Serde. If IRC is not your thing, we are happy to respond to [GitHub
issues](https://github.com/serde-rs/serde/issues/new) as well.
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:
## License
```rust,ignore
...
Serde is licensed under either of
fn visit_none(&mut self) -> Result<(), Self::Error> {
self.visit_unit()
}
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
http://opensource.org/licenses/MIT)
fn visit_some<T>(&mut self, value: T) -> Result<(), Self::Error> {
value.serialize(self)
}
...
```
at your option.
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:
### Contribution
```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
===========
`serde_codegen` and `serde_macros` support annotations that help to customize
how types are serialized. Here are the supported annotations:
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) |
| 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) |
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.
+5 -5
View File
@@ -6,12 +6,12 @@ build = "build.rs"
[features]
default = ["serde_codegen"]
unstable = ["serde_macros"]
unstable = ["serde_derive"]
[build-dependencies]
serde_codegen = { version = "^0.7", optional = true }
serde_codegen = { version = "^0.8", optional = true, path = "../../serde_codegen" }
[dependencies]
serde = "^0.7"
serde_json = "^0.7"
serde_macros = { version = "^0.7", optional = true }
serde = "^0.8"
serde_derive = { version = "^0.8", optional = true, path = "../../serde_derive" }
serde_json = "^0.8"
+1 -1
View File
@@ -16,5 +16,5 @@ Point { x: 1, y: 2 }
On nightly, it can use a plugin with:
```
% rustup run nightly cargo run --features nightly --no-default-features
% rustup run nightly cargo run --features unstable --no-default-features
```
+2 -2
View File
@@ -1,4 +1,4 @@
#[cfg(not(feature = "serde_macros"))]
#[cfg(not(feature = "serde_derive"))]
mod inner {
extern crate serde_codegen;
@@ -15,7 +15,7 @@ mod inner {
}
}
#[cfg(feature = "serde_macros")]
#[cfg(feature = "serde_derive")]
mod inner {
pub fn main() {}
}
+7 -4
View File
@@ -1,11 +1,14 @@
#![cfg_attr(feature = "serde_macros", feature(custom_derive, plugin))]
#![cfg_attr(feature = "serde_macros", plugin(serde_macros))]
#![cfg_attr(feature = "serde_derive", feature(proc_macro))]
#[cfg(feature = "serde_derive")]
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
#[cfg(feature = "serde_macros")]
#[cfg(feature = "serde_derive")]
include!("main.rs.in");
#[cfg(not(feature = "serde_macros"))]
#[cfg(not(feature = "serde_derive"))]
include!(concat!(env!("OUT_DIR"), "/main.rs"));
+3 -4
View File
@@ -1,13 +1,12 @@
[package]
name = "serde"
# DO NOT RELEASE ANY MORE 0.7 RELEASES FROM THIS BRANCH
# USE THE 0.7.x BRANCH
version = "0.8.0-rc2"
version = "0.8.21"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde-rs.github.io/serde/serde/"
documentation = "https://docs.serde.rs/serde/"
readme = "../README.md"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
+22 -22
View File
@@ -19,6 +19,15 @@ pub struct Bytes<'a> {
bytes: &'a [u8],
}
impl<'a> Bytes<'a> {
/// Wrap an existing `&[u8]`.
pub fn new(bytes: &'a [u8]) -> Self {
Bytes {
bytes: bytes,
}
}
}
impl<'a> fmt::Debug for Bytes<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(f.write_str("b\""));
@@ -31,18 +40,14 @@ impl<'a> fmt::Debug for Bytes<'a> {
impl<'a> From<&'a [u8]> for Bytes<'a> {
fn from(bytes: &'a [u8]) -> Self {
Bytes {
bytes: bytes,
}
Bytes::new(bytes)
}
}
#[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::new(bytes)
}
}
@@ -90,15 +95,18 @@ mod bytebuf {
impl ByteBuf {
/// Construct a new, empty `ByteBuf`.
pub fn new() -> Self {
ByteBuf {
bytes: Vec::new(),
}
ByteBuf::from(Vec::new())
}
/// Construct a new, empty `ByteBuf` with the specified capacity.
pub fn with_capacity(cap: usize) -> Self {
ByteBuf::from(Vec::with_capacity(cap))
}
/// Wrap existing bytes in a `ByteBuf`.
pub fn from<T: Into<Vec<u8>>>(bytes: T) -> Self {
ByteBuf {
bytes: Vec::with_capacity(cap)
bytes: bytes.into(),
}
}
}
@@ -121,9 +129,7 @@ mod bytebuf {
impl From<Vec<u8>> for ByteBuf {
fn from(bytes: Vec<u8>) -> Self {
ByteBuf {
bytes: bytes,
}
ByteBuf::from(bytes)
}
}
@@ -179,9 +185,7 @@ mod bytebuf {
fn visit_unit<E>(&mut self) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf {
bytes: Vec::new(),
})
Ok(ByteBuf::new())
}
#[inline]
@@ -197,9 +201,7 @@ mod bytebuf {
try!(visitor.end());
Ok(ByteBuf {
bytes: values,
})
Ok(ByteBuf::from(values))
}
#[inline]
@@ -213,9 +215,7 @@ mod bytebuf {
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf {
bytes: v,
})
Ok(ByteBuf::from(v))
}
}
+221 -102
View File
@@ -53,6 +53,9 @@ use alloc::arc::Arc;
#[cfg(all(feature = "unstable", feature = "alloc", not(feature = "std")))]
use alloc::boxed::Box;
#[cfg(feature = "std")]
use std::time::Duration;
#[cfg(feature = "unstable")]
use core::nonzero::{NonZero, Zeroable};
@@ -280,6 +283,12 @@ impl Visitor for StringVisitor {
Ok(v)
}
fn visit_unit<E>(&mut self) -> Result<String, E>
where E: Error,
{
Ok(String::new())
}
fn visit_bytes<E>(&mut self, v: &[u8]) -> Result<String, E>
where E: Error,
{
@@ -356,7 +365,7 @@ pub struct PhantomDataVisitor<T> {
marker: PhantomData<T>,
}
impl<T> Visitor for PhantomDataVisitor<T> where T: Deserialize {
impl<T> Visitor for PhantomDataVisitor<T> {
type Value = PhantomData<T>;
#[inline]
@@ -367,7 +376,7 @@ impl<T> Visitor for PhantomDataVisitor<T> where T: Deserialize {
}
}
impl<T> Deserialize for PhantomData<T> where T: Deserialize {
impl<T> Deserialize for PhantomData<T> {
fn deserialize<D>(deserializer: &mut D) -> Result<PhantomData<T>, D::Error>
where D: Deserializer,
{
@@ -509,27 +518,26 @@ seq_impl!(
///////////////////////////////////////////////////////////////////////////////
struct ArrayVisitor0<T> {
marker: PhantomData<T>,
struct ArrayVisitor<A> {
marker: PhantomData<A>,
}
impl<T> ArrayVisitor0<T> {
/// Construct a `ArrayVisitor0<T>`.
impl<A> ArrayVisitor<A> {
pub fn new() -> Self {
ArrayVisitor0 {
ArrayVisitor {
marker: PhantomData,
}
}
}
impl<T> Visitor for ArrayVisitor0<T> where T: Deserialize + Default {
impl<T> Visitor for ArrayVisitor<[T; 0]> where T: Deserialize {
type Value = [T; 0];
#[inline]
fn visit_unit<E>(&mut self) -> Result<[T; 0], E>
where E: Error,
{
Ok([T::default(); 0])
Ok([])
}
#[inline]
@@ -537,37 +545,24 @@ impl<T> Visitor for ArrayVisitor0<T> where T: Deserialize + Default {
where V: SeqVisitor,
{
try!(visitor.end());
Ok([T::default(); 0])
Ok([])
}
}
impl<T> Deserialize for [T; 0]
where T: Deserialize + Default
where T: Deserialize
{
fn deserialize<D>(deserializer: &mut D) -> Result<[T; 0], D::Error>
where D: Deserializer,
{
deserializer.deserialize_seq(ArrayVisitor0::new())
deserializer.deserialize_seq_fixed_size(0, ArrayVisitor::<[T; 0]>::new())
}
}
macro_rules! array_impls {
($($visitor:ident, $len:expr => ($($name:ident),+),)+) => {
($($len:expr => ($($name:ident)+))+) => {
$(
struct $visitor<T> {
marker: PhantomData<T>,
}
impl<T> $visitor<T> {
/// Construct a `ArrayVisitor*<T>`.
pub fn new() -> Self {
$visitor {
marker: PhantomData
}
}
}
impl<T> Visitor for $visitor<T> where T: Deserialize {
impl<T> Visitor for ArrayVisitor<[T; $len]> where T: Deserialize {
type Value = [T; $len];
#[inline]
@@ -577,13 +572,13 @@ macro_rules! array_impls {
$(
let $name = match try!(visitor.visit()) {
Some(val) => val,
None => { return Err(Error::end_of_stream()); }
None => return Err(Error::end_of_stream()),
};
)+;
)+
try!(visitor.end());
Ok([$($name,)+])
Ok([$($name),+])
}
}
@@ -593,7 +588,7 @@ macro_rules! array_impls {
fn deserialize<D>(deserializer: &mut D) -> Result<[T; $len], D::Error>
where D: Deserializer,
{
deserializer.deserialize_fixed_size_array($len, $visitor::new())
deserializer.deserialize_seq_fixed_size($len, ArrayVisitor::<[T; $len]>::new())
}
}
)+
@@ -601,71 +596,58 @@ macro_rules! array_impls {
}
array_impls! {
ArrayVisitor1, 1 => (a),
ArrayVisitor2, 2 => (a, b),
ArrayVisitor3, 3 => (a, b, c),
ArrayVisitor4, 4 => (a, b, c, d),
ArrayVisitor5, 5 => (a, b, c, d, e),
ArrayVisitor6, 6 => (a, b, c, d, e, f),
ArrayVisitor7, 7 => (a, b, c, d, e, f, g),
ArrayVisitor8, 8 => (a, b, c, d, e, f, g, h),
ArrayVisitor9, 9 => (a, b, c, d, e, f, g, h, i),
ArrayVisitor10, 10 => (a, b, c, d, e, f, g, h, i, j),
ArrayVisitor11, 11 => (a, b, c, d, e, f, g, h, i, j, k),
ArrayVisitor12, 12 => (a, b, c, d, e, f, g, h, i, j, k, l),
ArrayVisitor13, 13 => (a, b, c, d, e, f, g, h, i, j, k, l, m),
ArrayVisitor14, 14 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n),
ArrayVisitor15, 15 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o),
ArrayVisitor16, 16 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p),
ArrayVisitor17, 17 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q),
ArrayVisitor18, 18 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r),
ArrayVisitor19, 19 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s),
ArrayVisitor20, 20 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s ,t),
ArrayVisitor21, 21 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u),
ArrayVisitor22, 22 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v),
ArrayVisitor23, 23 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w),
ArrayVisitor24, 24 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x),
ArrayVisitor25, 25 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
y),
ArrayVisitor26, 26 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
y, z),
ArrayVisitor27, 27 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
y, z, aa),
ArrayVisitor28, 28 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
y, z, aa, ab),
ArrayVisitor29, 29 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
y, z, aa, ab, ac),
ArrayVisitor30, 30 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
y, z, aa, ab, ac, ad),
ArrayVisitor31, 31 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
y, z, aa, ab, ac, ad, ae),
ArrayVisitor32, 32 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
y, z, aa, ab, ac, ad, ae, af),
1 => (a)
2 => (a b)
3 => (a b c)
4 => (a b c d)
5 => (a b c d e)
6 => (a b c d e f)
7 => (a b c d e f g)
8 => (a b c d e f g h)
9 => (a b c d e f g h i)
10 => (a b c d e f g h i j)
11 => (a b c d e f g h i j k)
12 => (a b c d e f g h i j k l)
13 => (a b c d e f g h i j k l m)
14 => (a b c d e f g h i j k l m n)
15 => (a b c d e f g h i j k l m n o)
16 => (a b c d e f g h i j k l m n o p)
17 => (a b c d e f g h i j k l m n o p q)
18 => (a b c d e f g h i j k l m n o p q r)
19 => (a b c d e f g h i j k l m n o p q r s)
20 => (a b c d e f g h i j k l m n o p q r s t)
21 => (a b c d e f g h i j k l m n o p q r s t u)
22 => (a b c d e f g h i j k l m n o p q r s t u v)
23 => (a b c d e f g h i j k l m n o p q r s t u v w)
24 => (a b c d e f g h i j k l m n o p q r s t u v w x)
25 => (a b c d e f g h i j k l m n o p q r s t u v w x y)
26 => (a b c d e f g h i j k l m n o p q r s t u v w x y z)
27 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa)
28 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab)
29 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac)
30 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad)
31 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad ae)
32 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad ae af)
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! tuple_impls {
($($len:expr => $visitor:ident => ($($name:ident),+),)+) => {
($($len:expr => $visitor:ident => ($($name:ident)+))+) => {
$(
/// Construct a tuple visitor.
pub struct $visitor<$($name,)+> {
marker: PhantomData<($($name,)+)>,
}
impl<
$($name: Deserialize,)+
> $visitor<$($name,)+> {
impl<$($name: Deserialize,)+> $visitor<$($name,)+> {
/// Construct a `TupleVisitor*<T>`.
pub fn new() -> Self {
$visitor { marker: PhantomData }
}
}
impl<
$($name: Deserialize,)+
> Visitor for $visitor<$($name,)+> {
impl<$($name: Deserialize),+> Visitor for $visitor<$($name,)+> {
type Value = ($($name,)+);
#[inline]
@@ -676,9 +658,9 @@ macro_rules! tuple_impls {
$(
let $name = match try!(visitor.visit()) {
Some(value) => value,
None => { return Err(Error::end_of_stream()); }
None => return Err(Error::end_of_stream()),
};
)+;
)+
try!(visitor.end());
@@ -686,9 +668,7 @@ macro_rules! tuple_impls {
}
}
impl<
$($name: Deserialize),+
> Deserialize for ($($name,)+) {
impl<$($name: Deserialize),+> Deserialize for ($($name,)+) {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<($($name,)+), D::Error>
where D: Deserializer,
@@ -701,22 +681,22 @@ macro_rules! tuple_impls {
}
tuple_impls! {
1 => TupleVisitor1 => (T0),
2 => TupleVisitor2 => (T0, T1),
3 => TupleVisitor3 => (T0, T1, T2),
4 => TupleVisitor4 => (T0, T1, T2, T3),
5 => TupleVisitor5 => (T0, T1, T2, T3, T4),
6 => TupleVisitor6 => (T0, T1, T2, T3, T4, T5),
7 => TupleVisitor7 => (T0, T1, T2, T3, T4, T5, T6),
8 => TupleVisitor8 => (T0, T1, T2, T3, T4, T5, T6, T7),
9 => TupleVisitor9 => (T0, T1, T2, T3, T4, T5, T6, T7, T8),
10 => TupleVisitor10 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9),
11 => TupleVisitor11 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10),
12 => TupleVisitor12 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11),
13 => TupleVisitor13 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12),
14 => TupleVisitor14 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13),
15 => TupleVisitor15 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14),
16 => TupleVisitor16 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15),
1 => TupleVisitor1 => (T0)
2 => TupleVisitor2 => (T0 T1)
3 => TupleVisitor3 => (T0 T1 T2)
4 => TupleVisitor4 => (T0 T1 T2 T3)
5 => TupleVisitor5 => (T0 T1 T2 T3 T4)
6 => TupleVisitor6 => (T0 T1 T2 T3 T4 T5)
7 => TupleVisitor7 => (T0 T1 T2 T3 T4 T5 T6)
8 => TupleVisitor8 => (T0 T1 T2 T3 T4 T5 T6 T7)
9 => TupleVisitor9 => (T0 T1 T2 T3 T4 T5 T6 T7 T8)
10 => TupleVisitor10 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9)
11 => TupleVisitor11 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10)
12 => TupleVisitor12 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11)
13 => TupleVisitor13 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12)
14 => TupleVisitor14 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13)
15 => TupleVisitor15 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14)
16 => TupleVisitor16 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15)
}
///////////////////////////////////////////////////////////////////////////////
@@ -788,7 +768,7 @@ macro_rules! map_impl {
#[cfg(any(feature = "std", feature = "collections"))]
map_impl!(
BTreeMap<K, V>,
BTreeMapVisitor<K: Deserialize + Eq + Ord,
BTreeMapVisitor<K: Deserialize + Ord,
V: Deserialize>,
visitor,
BTreeMap::new(),
@@ -806,7 +786,7 @@ map_impl!(
///////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "unstable", feature = "std"))]
#[cfg(feature = "std")]
impl Deserialize for net::IpAddr {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer,
@@ -939,6 +919,16 @@ impl<T: Deserialize> Deserialize for Box<[T]> {
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl Deserialize for Box<str> {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer
{
let s = try!(String::deserialize(deserializer));
Ok(s.into_boxed_str())
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Deserialize> Deserialize for Arc<T> {
fn deserialize<D>(deserializer: &mut D) -> Result<Arc<T>, D::Error>
@@ -972,6 +962,135 @@ impl<'a, T: ?Sized> Deserialize for Cow<'a, T> where T: ToOwned, T::Owned: Deser
///////////////////////////////////////////////////////////////////////////////
// This is a cleaned-up version of the impl generated by:
//
// #[derive(Deserialize)]
// #[serde(deny_unknown_fields)]
// struct Duration {
// secs: u64,
// nanos: u32,
// }
#[cfg(feature = "std")]
impl Deserialize for Duration {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer,
{
enum Field { Secs, Nanos };
impl Deserialize for Field {
fn deserialize<D>(deserializer: &mut D) -> Result<Field, D::Error>
where D: Deserializer,
{
struct FieldVisitor;
impl Visitor for FieldVisitor {
type Value = Field;
fn visit_usize<E>(&mut self, value: usize) -> Result<Field, E>
where E: Error,
{
match value {
0usize => Ok(Field::Secs),
1usize => Ok(Field::Nanos),
_ => Err(Error::invalid_value("expected a field")),
}
}
fn visit_str<E>(&mut self, value: &str) -> Result<Field, E>
where E: Error,
{
match value {
"secs" => Ok(Field::Secs),
"nanos" => Ok(Field::Nanos),
_ => Err(Error::unknown_field(value)),
}
}
fn visit_bytes<E>(&mut self, value: &[u8]) -> Result<Field, E>
where E: Error,
{
match value {
b"secs" => Ok(Field::Secs),
b"nanos" => Ok(Field::Nanos),
_ => {
let value = String::from_utf8_lossy(value);
Err(Error::unknown_field(&value))
}
}
}
}
deserializer.deserialize_struct_field(FieldVisitor)
}
}
struct DurationVisitor;
impl Visitor for DurationVisitor {
type Value = Duration;
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<Duration, V::Error>
where V: SeqVisitor,
{
let secs: u64 = match try!(visitor.visit()) {
Some(value) => value,
None => {
try!(visitor.end());
return Err(Error::invalid_length(0));
}
};
let nanos: u32 = match try!(visitor.visit()) {
Some(value) => value,
None => {
try!(visitor.end());
return Err(Error::invalid_length(1));
}
};
try!(visitor.end());
Ok(Duration::new(secs, nanos))
}
fn visit_map<V>(&mut self, mut visitor: V) -> Result<Duration, V::Error>
where V: MapVisitor,
{
let mut secs: Option<u64> = None;
let mut nanos: Option<u32> = None;
while let Some(key) = try!(visitor.visit_key::<Field>()) {
match key {
Field::Secs => {
if secs.is_some() {
return Err(<V::Error as Error>::duplicate_field("secs"));
}
secs = Some(try!(visitor.visit_value()));
}
Field::Nanos => {
if nanos.is_some() {
return Err(<V::Error as Error>::duplicate_field("nanos"));
}
nanos = Some(try!(visitor.visit_value()));
}
}
}
try!(visitor.end());
let secs = match secs {
Some(secs) => secs,
None => try!(visitor.missing_field("secs")),
};
let nanos = match nanos {
Some(nanos) => nanos,
None => try!(visitor.missing_field("nanos")),
};
Ok(Duration::new(secs, nanos))
}
}
const FIELDS: &'static [&'static str] = &["secs", "nanos"];
deserializer.deserialize_struct("Duration", FIELDS, DurationVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")]
impl<T> Deserialize for NonZero<T> where T: Deserialize + PartialEq + Zeroable + Zero {
fn deserialize<D>(deserializer: &mut D) -> Result<NonZero<T>, D::Error> where D: Deserializer {
+88 -194
View File
@@ -10,6 +10,8 @@ use collections::{String, Vec};
use core::fmt;
///////////////////////////////////////////////////////////////////////////////
pub mod impls;
pub mod value;
mod from_primitive;
@@ -243,278 +245,166 @@ pub trait Deserializer {
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a `bool` value.
#[inline]
fn deserialize_bool<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `usize` value.
#[inline]
/// A reasonable default is to forward to `deserialize_u64`.
fn deserialize_usize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_u64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `u8` value.
#[inline]
/// A reasonable default is to forward to `deserialize_u64`.
fn deserialize_u8<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_u64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `u16` value.
#[inline]
/// A reasonable default is to forward to `deserialize_u64`.
fn deserialize_u16<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_u64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `u32` value.
#[inline]
/// A reasonable default is to forward to `deserialize_u64`.
fn deserialize_u32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_u64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `u64` value.
#[inline]
fn deserialize_u64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `isize` value.
#[inline]
/// A reasonable default is to forward to `deserialize_i64`.
fn deserialize_isize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_i64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `i8` value.
#[inline]
/// A reasonable default is to forward to `deserialize_i64`.
fn deserialize_i8<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_i64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `i16` value.
#[inline]
/// A reasonable default is to forward to `deserialize_i64`.
fn deserialize_i16<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_i64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `i32` value.
#[inline]
/// A reasonable default is to forward to `deserialize_i64`.
fn deserialize_i32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_i64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `i64` value.
#[inline]
fn deserialize_i64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a `f32` value.
#[inline]
/// A reasonable default is to forward to `deserialize_f64`.
fn deserialize_f32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_f64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a `f64` value.
#[inline]
fn deserialize_f64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a `char` value.
#[inline]
fn deserialize_char<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a `&str` value.
#[inline]
fn deserialize_str<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a `String` value.
#[inline]
fn deserialize_string<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_str(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `unit` value.
#[inline]
fn deserialize_unit<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: 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 deserialize_option<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: 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 deserialize_seq<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// 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 deserialize_fixed_size_array<V>(&mut self,
_len: usize,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
fn deserialize_seq_fixed_size<V>(&mut self,
len: usize,
visitor: V) -> Result<V::Value, Self::Error>
where V: 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 deserialize_bytes<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_seq(visitor)
}
where V: 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.
#[inline]
fn deserialize_map<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: 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,
name: &'static str,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_unit(visitor)
}
where V: 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]
/// A reasonable default is to simply deserialize the expected value directly.
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)
}
where V: 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,
name: &'static str,
len: usize,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_tuple(len, visitor)
}
where V: 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],
name: &'static str,
fields: &'static [&'static str],
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_map(visitor)
}
where V: 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)
}
where V: 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)
}
fn deserialize_tuple<V>(&mut self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where V: 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))
}
name: &'static str,
variants: &'static [&'static str],
visitor: V) -> Result<V::Value, Self::Error>
where V: EnumVisitor;
/// 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)
}
where V: Visitor;
}
///////////////////////////////////////////////////////////////////////////////
@@ -525,9 +415,10 @@ pub trait Visitor {
type Value: Deserialize;
/// `visit_bool` deserializes a `bool` into a `Value`.
fn visit_bool<E>(&mut self, _v: bool) -> Result<Self::Value, E>
fn visit_bool<E>(&mut self, v: bool) -> Result<Self::Value, E>
where E: Error,
{
let _ = v;
Err(Error::invalid_type(Type::Bool))
}
@@ -560,9 +451,10 @@ pub trait Visitor {
}
/// `visit_i64` deserializes a `i64` into a `Value`.
fn visit_i64<E>(&mut self, _v: i64) -> Result<Self::Value, E>
fn visit_i64<E>(&mut self, v: i64) -> Result<Self::Value, E>
where E: Error,
{
let _ = v;
Err(Error::invalid_type(Type::I64))
}
@@ -595,9 +487,10 @@ pub trait Visitor {
}
/// `visit_u64` deserializes a `u64` into a `Value`.
fn visit_u64<E>(&mut self, _v: u64) -> Result<Self::Value, E>
fn visit_u64<E>(&mut self, v: u64) -> Result<Self::Value, E>
where E: Error,
{
let _ = v;
Err(Error::invalid_type(Type::U64))
}
@@ -609,9 +502,10 @@ pub trait Visitor {
}
/// `visit_f64` deserializes a `f64` into a `Value`.
fn visit_f64<E>(&mut self, _v: f64) -> Result<Self::Value, E>
fn visit_f64<E>(&mut self, v: f64) -> Result<Self::Value, E>
where E: Error,
{
let _ = v;
Err(Error::invalid_type(Type::F64))
}
@@ -624,9 +518,10 @@ pub trait Visitor {
}
/// `visit_str` deserializes a `&str` into a `Value`.
fn visit_str<E>(&mut self, _v: &str) -> Result<Self::Value, E>
fn visit_str<E>(&mut self, v: &str) -> Result<Self::Value, E>
where E: Error,
{
let _ = v;
Err(Error::invalid_type(Type::Str))
}
@@ -650,9 +545,10 @@ pub trait Visitor {
/// `visit_unit_struct` deserializes a unit struct into a `Value`.
#[inline]
fn visit_unit_struct<E>(&mut self, _name: &'static str) -> Result<Self::Value, E>
fn visit_unit_struct<E>(&mut self, name: &'static str) -> Result<Self::Value, E>
where E: Error,
{
let _ = name;
self.visit_unit()
}
@@ -664,37 +560,42 @@ pub trait Visitor {
}
/// `visit_some` deserializes a value into a `Value`.
fn visit_some<D>(&mut self, _deserializer: &mut D) -> Result<Self::Value, D::Error>
fn visit_some<D>(&mut self, deserializer: &mut D) -> Result<Self::Value, D::Error>
where D: Deserializer,
{
let _ = deserializer;
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>
fn visit_newtype_struct<D>(&mut self, deserializer: &mut D) -> Result<Self::Value, D::Error>
where D: Deserializer,
{
let _ = deserializer;
Err(Error::invalid_type(Type::NewtypeStruct))
}
/// `visit_seq` deserializes a `SeqVisitor` into a `Value`.
fn visit_seq<V>(&mut self, _visitor: V) -> Result<Self::Value, V::Error>
fn visit_seq<V>(&mut self, visitor: V) -> Result<Self::Value, V::Error>
where V: SeqVisitor,
{
let _ = visitor;
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>
fn visit_map<V>(&mut self, visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor,
{
let _ = visitor;
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>
fn visit_bytes<E>(&mut self, v: &[u8]) -> Result<Self::Value, E>
where E: Error,
{
let _ = v;
Err(Error::invalid_type(Type::Bytes))
}
@@ -870,33 +771,26 @@ pub trait VariantVisitor {
Err(Error::invalid_type(Type::UnitVariant))
}
/// `visit_newtype` is called when deserializing a variant with a single value. By default this
/// uses the `visit_tuple` method to deserialize the value.
#[inline]
/// `visit_newtype` is called when deserializing a variant with a single value.
/// A good default is often to use the `visit_tuple` method to deserialize a `(value,)`.
fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
where T: Deserialize,
{
let (value,) = try!(self.visit_tuple(1, impls::TupleVisitor1::new()));
Ok(value)
}
where T: Deserialize;
/// `visit_tuple` is called when deserializing a tuple-like variant.
/// If no tuple variants are expected, yield a
/// `Err(serde::de::Error::invalid_type(serde::de::Type::TupleVariant))`
fn visit_tuple<V>(&mut self,
_len: usize,
_visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
Err(Error::invalid_type(Type::TupleVariant))
}
len: usize,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
/// `visit_struct` is called when deserializing a struct-like variant.
/// If no struct variants are expected, yield a
/// `Err(serde::de::Error::invalid_type(serde::de::Type::StructVariant))`
fn visit_struct<V>(&mut self,
_fields: &'static [&'static str],
_visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
Err(Error::invalid_type(Type::StructVariant))
}
fields: &'static [&'static str],
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
}
impl<'a, T> VariantVisitor for &'a mut T where T: VariantVisitor {
+365 -13
View File
@@ -12,6 +12,8 @@ use std::collections::{
hash_set,
};
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(feature = "std")]
use std::vec;
#[cfg(all(feature = "collections", not(feature = "std")))]
@@ -24,6 +26,8 @@ use collections::{
btree_set,
vec,
};
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::borrow::Cow;
#[cfg(all(feature = "unstable", feature = "collections"))]
use collections::borrow::ToOwned;
@@ -128,7 +132,7 @@ impl fmt::Display for Error {
write!(formatter, "Unknown variant: {}", variant)
}
Error::UnknownField(ref field) => write!(formatter, "Unknown field: {}", field),
Error::MissingField(ref field) => write!(formatter, "Missing field: {}", field),
Error::MissingField(field) => write!(formatter, "Missing field: {}", field),
}
}
}
@@ -174,6 +178,12 @@ impl<E> de::Deserializer for UnitDeserializer<E>
{
type Error = E;
forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
unit seq seq_fixed_size bytes map unit_struct newtype_struct
tuple_struct struct struct_field tuple enum ignored_any
}
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
@@ -209,6 +219,13 @@ macro_rules! primitive_deserializer {
{
type Error = E;
forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str
string unit option seq seq_fixed_size bytes map unit_struct
newtype_struct tuple_struct struct struct_field tuple enum
ignored_any
}
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
@@ -273,6 +290,12 @@ impl<'a, E> de::Deserializer for StrDeserializer<'a, E>
{
visitor.visit(self)
}
forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
unit option seq seq_fixed_size bytes map unit_struct newtype_struct
tuple_struct struct struct_field tuple ignored_any
}
}
impl<'a, E> de::VariantVisitor for StrDeserializer<'a, E>
@@ -289,6 +312,29 @@ impl<'a, E> de::VariantVisitor for StrDeserializer<'a, E>
fn visit_unit(&mut self) -> Result<(), Self::Error> {
Ok(())
}
fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
where T: super::Deserialize,
{
let (value,) = try!(self.visit_tuple(1, super::impls::TupleVisitor1::new()));
Ok(value)
}
fn visit_tuple<V>(&mut self,
_len: usize,
_visitor: V) -> Result<V::Value, Self::Error>
where V: super::Visitor
{
Err(super::Error::invalid_type(super::Type::TupleVariant))
}
fn visit_struct<V>(&mut self,
_fields: &'static [&'static str],
_visitor: V) -> Result<V::Value, Self::Error>
where V: super::Visitor
{
Err(super::Error::invalid_type(super::Type::StructVariant))
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -331,6 +377,12 @@ impl<E> de::Deserializer for StringDeserializer<E>
{
visitor.visit(self)
}
forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
unit option seq seq_fixed_size bytes map unit_struct newtype_struct
tuple_struct struct struct_field tuple ignored_any
}
}
#[cfg(any(feature = "std", feature = "collections"))]
@@ -348,6 +400,118 @@ impl<'a, E> de::VariantVisitor for StringDeserializer<E>
fn visit_unit(&mut self) -> Result<(), Self::Error> {
Ok(())
}
fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
where T: super::Deserialize,
{
let (value,) = try!(self.visit_tuple(1, super::impls::TupleVisitor1::new()));
Ok(value)
}
fn visit_tuple<V>(&mut self,
_len: usize,
_visitor: V) -> Result<V::Value, Self::Error>
where V: super::Visitor
{
Err(super::Error::invalid_type(super::Type::TupleVariant))
}
fn visit_struct<V>(&mut self,
_fields: &'static [&'static str],
_visitor: V) -> Result<V::Value, Self::Error>
where V: super::Visitor
{
Err(super::Error::invalid_type(super::Type::StructVariant))
}
}
///////////////////////////////////////////////////////////////////////////////
/// A helper deserializer that deserializes a `String`.
#[cfg(any(feature = "std", feature = "collections"))]
pub struct CowStrDeserializer<'a, E>(Option<Cow<'a, str>>, PhantomData<E>);
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a, E> ValueDeserializer<E> for Cow<'a, str>
where E: de::Error,
{
type Deserializer = CowStrDeserializer<'a, E>;
fn into_deserializer(self) -> CowStrDeserializer<'a, E> {
CowStrDeserializer(Some(self), PhantomData)
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a, E> de::Deserializer for CowStrDeserializer<'a, E>
where E: de::Error,
{
type Error = E;
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
match self.0.take() {
Some(Cow::Borrowed(string)) => visitor.visit_str(string),
Some(Cow::Owned(string)) => visitor.visit_string(string),
None => Err(de::Error::end_of_stream()),
}
}
fn deserialize_enum<V>(&mut self,
_name: &str,
_variants: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::EnumVisitor,
{
visitor.visit(self)
}
forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
unit option seq seq_fixed_size bytes map unit_struct newtype_struct
tuple_struct struct struct_field tuple ignored_any
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a, E> de::VariantVisitor for CowStrDeserializer<'a, E>
where E: de::Error,
{
type Error = E;
fn visit_variant<T>(&mut self) -> Result<T, Self::Error>
where T: de::Deserialize,
{
de::Deserialize::deserialize(self)
}
fn visit_unit(&mut self) -> Result<(), Self::Error> {
Ok(())
}
fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
where T: super::Deserialize,
{
let (value,) = try!(self.visit_tuple(1, super::impls::TupleVisitor1::new()));
Ok(value)
}
fn visit_tuple<V>(&mut self,
_len: usize,
_visitor: V) -> Result<V::Value, Self::Error>
where V: super::Visitor
{
Err(super::Error::invalid_type(super::Type::TupleVariant))
}
fn visit_struct<V>(&mut self,
_fields: &'static [&'static str],
_visitor: V) -> Result<V::Value, Self::Error>
where V: super::Visitor
{
Err(super::Error::invalid_type(super::Type::StructVariant))
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -384,6 +548,12 @@ impl<I, T, E> de::Deserializer for SeqDeserializer<I, E>
{
visitor.visit_seq(self)
}
forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
unit option seq seq_fixed_size bytes map unit_struct newtype_struct
tuple_struct struct struct_field tuple enum ignored_any
}
}
impl<I, T, E> de::SeqVisitor for SeqDeserializer<I, E>
@@ -490,6 +660,12 @@ impl<V_, E> de::Deserializer for SeqVisitorDeserializer<V_, E>
fn deserialize<V: de::Visitor>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_seq(&mut self.visitor)
}
forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
unit option seq seq_fixed_size bytes map unit_struct newtype_struct
tuple_struct struct struct_field tuple enum ignored_any
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -503,7 +679,7 @@ pub struct MapDeserializer<I, K, V, E>
{
iter: I,
value: Option<V>,
len: usize,
len: Option<usize>,
marker: PhantomData<E>,
}
@@ -513,15 +689,35 @@ impl<I, K, V, E> MapDeserializer<I, K, V, E>
V: ValueDeserializer<E>,
E: de::Error,
{
/// Construct a new `MapDeserializer<I, K, V>`.
/// Construct a new `MapDeserializer<I, K, V, E>` with a specific length.
pub fn new(iter: I, len: usize) -> Self {
MapDeserializer {
iter: iter,
value: None,
len: len,
len: Some(len),
marker: PhantomData,
}
}
/// Construct a new `MapDeserializer<I, K, V, E>` that is not bounded
/// by a specific length and that delegates to `iter` for its size hint.
pub fn unbounded(iter: I) -> Self {
MapDeserializer {
iter: iter,
value: None,
len: None,
marker: PhantomData,
}
}
fn next(&mut self) -> Option<(K, V)> {
self.iter.next().map(|(k, v)| {
if let Some(len) = self.len.as_mut() {
*len -= 1;
}
(k, v)
})
}
}
impl<I, K, V, E> de::Deserializer for MapDeserializer<I, K, V, E>
@@ -537,6 +733,28 @@ impl<I, K, V, E> de::Deserializer for MapDeserializer<I, K, V, E>
{
visitor.visit_map(self)
}
fn deserialize_seq<V_>(&mut self, mut visitor: V_) -> Result<V_::Value, Self::Error>
where V_: de::Visitor,
{
visitor.visit_seq(self)
}
fn deserialize_seq_fixed_size<V_>(&mut self, len: usize, mut visitor: V_) -> Result<V_::Value, Self::Error>
where V_: de::Visitor,
{
match self.len {
Some(map_len) if map_len == len => visitor.visit_seq(self),
Some(_) => Err(de::Error::invalid_length(len)),
None => visitor.visit_seq(self),
}
}
forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
unit option bytes map unit_struct newtype_struct tuple_struct struct
struct_field tuple enum ignored_any
}
}
impl<I, K, V, E> de::MapVisitor for MapDeserializer<I, K, V, E>
@@ -550,12 +768,11 @@ impl<I, K, V, E> de::MapVisitor for MapDeserializer<I, K, V, E>
fn visit_key<T>(&mut self) -> Result<Option<T>, Self::Error>
where T: de::Deserialize,
{
match self.iter.next() {
match self.next() {
Some((key, value)) => {
self.len -= 1;
self.value = Some(value);
let mut de = key.into_deserializer();
Ok(Some(try!(de::Deserialize::deserialize(&mut de))))
de::Deserialize::deserialize(&mut de).map(Some)
}
None => Ok(None),
}
@@ -576,15 +793,133 @@ impl<I, K, V, E> de::MapVisitor for MapDeserializer<I, K, V, E>
}
fn end(&mut self) -> Result<(), Self::Error> {
if self.len == 0 {
Ok(())
} else {
Err(de::Error::invalid_length(self.len))
match self.len {
Some(len) if len > 0 => Err(de::Error::invalid_length(len)),
_ => Ok(())
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
self.len.map_or_else(
|| self.iter.size_hint(),
|len| (len, Some(len)))
}
}
impl<I, K, V, E> de::SeqVisitor for MapDeserializer<I, K, V, E>
where I: Iterator<Item=(K, V)>,
K: ValueDeserializer<E>,
V: ValueDeserializer<E>,
E: de::Error,
{
type Error = E;
fn visit<T>(&mut self) -> Result<Option<T>, Self::Error>
where T: de::Deserialize,
{
match self.next() {
Some(kv) => {
let mut de = PairDeserializer(Some(kv), PhantomData);
de::Deserialize::deserialize(&mut de).map(Some)
}
None => Ok(None),
}
}
fn end(&mut self) -> Result<(), Self::Error> {
de::MapVisitor::end(self)
}
fn size_hint(&self) -> (usize, Option<usize>) {
de::MapVisitor::size_hint(self)
}
}
// Used in the `impl SeqVisitor for MapDeserializer` to visit the map as a
// sequence of pairs.
struct PairDeserializer<A, B, E>(Option<(A, B)>, PhantomData<E>);
impl<A, B, E> de::Deserializer for PairDeserializer<A, B, E>
where A: ValueDeserializer<E>,
B: ValueDeserializer<E>,
E: de::Error
{
type Error = E;
forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
unit option bytes map unit_struct newtype_struct tuple_struct struct
struct_field tuple enum ignored_any
}
fn deserialize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
self.deserialize_seq(visitor)
}
fn deserialize_seq<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
match self.0.take() {
Some((k, v)) => {
visitor.visit_seq(PairVisitor(Some(k), Some(v), PhantomData))
}
None => Err(de::Error::end_of_stream()),
}
}
fn deserialize_seq_fixed_size<V>(&mut self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
if len == 2 {
self.deserialize_seq(visitor)
} else {
Err(de::Error::invalid_length(len))
}
}
}
struct PairVisitor<A, B, E>(Option<A>, Option<B>, PhantomData<E>);
impl<A, B, E> de::SeqVisitor for PairVisitor<A, B, E>
where A: ValueDeserializer<E>,
B: ValueDeserializer<E>,
E: de::Error,
{
type Error = E;
fn visit<T>(&mut self) -> Result<Option<T>, Self::Error>
where T: de::Deserialize,
{
if let Some(k) = self.0.take() {
let mut de = k.into_deserializer();
de::Deserialize::deserialize(&mut de).map(Some)
} else if let Some(v) = self.1.take() {
let mut de = v.into_deserializer();
de::Deserialize::deserialize(&mut de).map(Some)
} else {
Ok(None)
}
}
fn end(&mut self) -> Result<(), Self::Error> {
if self.1.is_none() {
Ok(())
} else {
Err(de::Error::invalid_length(self.size_hint().0))
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = if self.0.is_some() {
2
} else if self.1.is_some() {
1
} else {
0
};
(len, Some(len))
}
}
@@ -648,6 +983,12 @@ impl<V_, E> de::Deserializer for MapVisitorDeserializer<V_, E>
fn deserialize<V: de::Visitor>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_map(&mut self.visitor)
}
forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
unit option seq seq_fixed_size bytes map unit_struct newtype_struct
tuple_struct struct struct_field tuple enum ignored_any
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -678,8 +1019,13 @@ impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
None => Err(de::Error::end_of_stream()),
}
}
}
forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
unit option seq seq_fixed_size bytes map unit_struct newtype_struct
tuple_struct struct struct_field tuple enum ignored_any
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -712,4 +1058,10 @@ impl<E> de::Deserializer for ByteBufDeserializer<E>
None => Err(de::Error::end_of_stream()),
}
}
forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
unit option seq seq_fixed_size bytes map unit_struct newtype_struct
tuple_struct struct struct_field tuple enum ignored_any
}
}
+5 -2
View File
@@ -5,11 +5,11 @@
//! 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.
//!
//!
//! For a detailed tutorial on the different ways to use serde please check out the
//! [github repository](https://github.com/serde-rs/serde)
#![doc(html_root_url="https://serde-rs.github.io/serde/serde")]
#![doc(html_root_url="https://docs.serde.rs")]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "unstable", feature(reflect_marker, unicode, nonzero, plugin, step_trait, zero_one))]
#![cfg_attr(feature = "alloc", feature(alloc))]
@@ -45,6 +45,9 @@ macro_rules! format {
($s:expr, $($rest:tt)*) => ($s)
}
#[macro_use]
mod macros;
pub mod bytes;
pub mod de;
#[cfg(feature = "std")]
+179
View File
@@ -0,0 +1,179 @@
#[cfg(feature = "std")]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_method {
($func:ident($($arg:ty),*)) => {
#[inline]
fn $func<__V>(&mut self, $(_: $arg,)* visitor: __V) -> ::std::result::Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor
{
self.deserialize(visitor)
}
};
}
#[cfg(not(feature = "std"))]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_method {
($func:ident($($arg:ty),*)) => {
#[inline]
fn $func<__V>(&mut self, $(_: $arg,)* visitor: __V) -> ::core::result::Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor
{
self.deserialize(visitor)
}
};
}
#[cfg(feature = "std")]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_enum {
() => {
#[inline]
fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _: __V) -> ::std::result::Result<__V::Value, Self::Error>
where __V: $crate::de::EnumVisitor
{
Err($crate::de::Error::invalid_type($crate::de::Type::Enum))
}
};
}
#[cfg(not(feature = "std"))]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_enum {
() => {
#[inline]
fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _: __V) -> ::core::result::Result<__V::Value, Self::Error>
where __V: $crate::de::EnumVisitor
{
Err($crate::de::Error::invalid_type($crate::de::Type::Enum))
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_helper {
(bool) => {
forward_to_deserialize_method!{deserialize_bool()}
};
(usize) => {
forward_to_deserialize_method!{deserialize_usize()}
};
(u8) => {
forward_to_deserialize_method!{deserialize_u8()}
};
(u16) => {
forward_to_deserialize_method!{deserialize_u16()}
};
(u32) => {
forward_to_deserialize_method!{deserialize_u32()}
};
(u64) => {
forward_to_deserialize_method!{deserialize_u64()}
};
(isize) => {
forward_to_deserialize_method!{deserialize_isize()}
};
(i8) => {
forward_to_deserialize_method!{deserialize_i8()}
};
(i16) => {
forward_to_deserialize_method!{deserialize_i16()}
};
(i32) => {
forward_to_deserialize_method!{deserialize_i32()}
};
(i64) => {
forward_to_deserialize_method!{deserialize_i64()}
};
(f32) => {
forward_to_deserialize_method!{deserialize_f32()}
};
(f64) => {
forward_to_deserialize_method!{deserialize_f64()}
};
(char) => {
forward_to_deserialize_method!{deserialize_char()}
};
(str) => {
forward_to_deserialize_method!{deserialize_str()}
};
(string) => {
forward_to_deserialize_method!{deserialize_string()}
};
(unit) => {
forward_to_deserialize_method!{deserialize_unit()}
};
(option) => {
forward_to_deserialize_method!{deserialize_option()}
};
(seq) => {
forward_to_deserialize_method!{deserialize_seq()}
};
(seq_fixed_size) => {
forward_to_deserialize_method!{deserialize_seq_fixed_size(usize)}
};
(bytes) => {
forward_to_deserialize_method!{deserialize_bytes()}
};
(map) => {
forward_to_deserialize_method!{deserialize_map()}
};
(unit_struct) => {
forward_to_deserialize_method!{deserialize_unit_struct(&'static str)}
};
(newtype_struct) => {
forward_to_deserialize_method!{deserialize_newtype_struct(&'static str)}
};
(tuple_struct) => {
forward_to_deserialize_method!{deserialize_tuple_struct(&'static str, usize)}
};
(struct) => {
forward_to_deserialize_method!{deserialize_struct(&'static str, &'static [&'static str])}
};
(struct_field) => {
forward_to_deserialize_method!{deserialize_struct_field()}
};
(tuple) => {
forward_to_deserialize_method!{deserialize_tuple(usize)}
};
(ignored_any) => {
forward_to_deserialize_method!{deserialize_ignored_any()}
};
(enum) => {
forward_to_deserialize_enum!();
};
}
/// Helper to forward `Deserializer` methods to `Deserializer::deserialize`.
/// Every given method ignores all arguments and forwards to `deserialize`.
/// Note that `deserialize_enum` simply returns an `Error::invalid_type`; a
/// better approach is tracked in [serde-rs/serde#521][1].
///
/// ```rust,ignore
/// impl Deserializer for MyDeserializer {
/// fn deserialize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor
/// {
/// /* ... */
/// }
///
/// forward_to_deserialize! {
/// bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
/// unit option seq seq_fixed_size bytes map unit_struct newtype_struct
/// tuple_struct struct struct_field tuple enum ignored_any
/// }
/// }
/// ```
///
/// [1]: https://github.com/serde-rs/serde/issues/521
#[macro_export]
macro_rules! forward_to_deserialize {
($($func:ident)*) => {
$(forward_to_deserialize_helper!{$func})*
};
}
+28 -15
View File
@@ -1,4 +1,8 @@
//! Implementations for all of Rust's builtin types.
//! Implementations for all of Rust's builtin types. Tuples implement the `Serialize` trait if they
//! have at most 16 fields. Arrays implement the `Serialize` trait if their length is 32 or less.
//! You can always forward array serialization to slice serialization, which works for any length.
//! Long tuples are best replaced by tuple structs, for which you can use `derive(Serialize)`. In
//! that case the number of fields is irrelevant.
#[cfg(feature = "std")]
use std::borrow::Cow;
@@ -46,6 +50,8 @@ use std::path;
use std::rc::Rc;
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::rc::Rc;
#[cfg(feature = "std")]
use std::time::Duration;
#[cfg(feature = "std")]
use std::sync::Arc;
@@ -153,7 +159,7 @@ impl<T> Serialize for [T]
where S: Serializer,
{
let mut state = try!(serializer.serialize_seq(Some(self.len())));
for e in self.iter() {
for e in self {
try!(serializer.serialize_seq_elt(&mut state, e));
}
serializer.serialize_seq_end(state)
@@ -170,7 +176,7 @@ macro_rules! array_impls {
where S: Serializer,
{
let mut state = try!(serializer.serialize_seq_fixed_size($len));
for e in self.iter() {
for e in self {
try!(serializer.serialize_seq_elt(&mut state, e));
}
serializer.serialize_seq_end(state)
@@ -307,11 +313,6 @@ impl Serialize for () {
///////////////////////////////////////////////////////////////////////////////
// FIXME(rust #19630) Remove this work-around
macro_rules! e {
($e:expr) => { $e }
}
macro_rules! tuple_impls {
($(
$TupleVisitor:ident ($len:expr, $($T:ident),+) {
@@ -328,7 +329,7 @@ macro_rules! tuple_impls {
{
let mut state = try!(serializer.serialize_tuple($len));
$(
try!(serializer.serialize_tuple_elt(&mut state, &e!(self.$idx)));
try!(serializer.serialize_tuple_elt(&mut state, &self.$idx));
)+
serializer.serialize_tuple_end(state)
}
@@ -518,7 +519,8 @@ macro_rules! serialize_map {
{
let mut state = try!(serializer.serialize_map(Some(self.len())));
for (k, v) in self {
try!(serializer.serialize_map_elt(&mut state, k, v));
try!(serializer.serialize_map_key(&mut state, k));
try!(serializer.serialize_map_value(&mut state, v));
}
serializer.serialize_map_end(state)
}
@@ -619,15 +621,26 @@ impl<T, E> Serialize for Result<T, E> where T: Serialize, E: Serialize {
///////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "std", feature = "unstable"))]
#[cfg(feature = "std")]
impl Serialize for Duration {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
let mut state = try!(serializer.serialize_struct("Duration", 2));
try!(serializer.serialize_struct_elt(&mut state, "secs", self.as_secs()));
try!(serializer.serialize_struct_elt(&mut state, "nanos", self.subsec_nanos()));
serializer.serialize_struct_end(state)
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
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),
}
self.to_string().serialize(serializer)
}
}
+56 -11
View File
@@ -1,4 +1,14 @@
//! Generic serialization framework.
//! # For Developers who want to serialize objects
//! Implement the `Serialize` trait for the type of objects you want to serialize. Call methods of
//! the `serializer` object. For which methods to call and how to do so, look at the documentation
//! of the `Serializer` trait.
//!
//! # For Serialization Format Developers
//! Implement the `Serializer` trait for a structure that contains fields that enable it to write
//! the serialization result to your target. When a method's argument is an object of type
//! `Serialize`, you can either forward the serializer object (`self`) or create a new one,
//! depending on the quirks of your format.
#[cfg(feature = "std")]
use std::error;
@@ -15,11 +25,11 @@ 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.
/// Raised when there is a general error when serializing 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.
/// Raised when there is a general error when serializing a type.
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
fn custom<T: Into<&'static str>>(msg: T) -> Self;
@@ -41,6 +51,26 @@ pub trait Serialize {
///////////////////////////////////////////////////////////////////////////////
/// A trait that describes a type that can serialize a stream of values into the underlying format.
///
/// # For `Serialize` Developers
/// Non-aggrergate types like integers and strings can be serialized directly by calling the
/// appropriate function. For Aggregate types there's an initial `serialize_T` method that yields
/// a State object that you should not interact with. For each part of the aggregate there's a
/// `serialize_T_elt` method that allows you to pass values or key/value pairs. The types of the
/// values or the keys may change between calls, but the serialization format may not necessarily
/// accept it. The `serialize_T_elt` method also takes a mutable reference to the state object.
/// Make sure that you always use the same state object and only the state object that was returned
/// by the `serialize_T` method. Finally, when your object is done, call the `serialize_T_end`
/// method and pass the state object by value
///
/// # For Serialization Format Developers
/// If your format has different situations where it accepts different types, create a
/// `Serializer` for each situation. You can create the sub-`Serializer` in one of the aggregate
/// `serialize_T` methods and return it as a state object. Remember to also set the corresponding
/// associated type `TState`. In the `serialize_T_elt` methods you will be given a mutable
/// reference to that state. You do not need to do any additional checks for the correctness of the
/// state object, as it is expected that the user will not modify it. Due to the generic nature
/// of the `Serialize` impls, modifying the object is impossible on stable Rust.
pub trait Serializer {
/// The error type that can be returned if some error occurs during serialization.
type Error: Error;
@@ -131,7 +161,8 @@ pub trait Serializer {
/// Serializes an `f64` value.
fn serialize_f64(&mut self, v: f64) -> Result<(), Self::Error>;
/// Serializes a character.
/// Serializes a character. If the format does not support characters,
/// it is reasonable to serialize it as a single element `str` or a `u32`.
fn serialize_char(&mut self, v: char) -> Result<(), Self::Error>;
/// Serializes a `&str`.
@@ -140,10 +171,17 @@ pub trait Serializer {
/// Enables serializers to serialize byte slices more compactly or more
/// efficiently than other types of slices. If no efficient implementation
/// is available, a reasonable implementation would be to forward to
/// `serialize_seq`.
/// `serialize_seq`. If forwarded, the implementation looks usually just like this:
/// ```rust
/// let mut state = try!(self.serialize_seq(value));
/// for b in value {
/// try!(self.serialize_seq_elt(&mut state, b));
/// }
/// self.serialize_seq_end(state)
/// ```
fn serialize_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error>;
/// Serializes a `()` value.
/// Serializes a `()` value. It's reasonable to just not serialize anything.
fn serialize_unit(&mut self) -> Result<(), Self::Error>;
/// Serializes a unit struct value. A reasonable implementation would be to
@@ -166,7 +204,7 @@ pub trait Serializer {
/// Allows a tuple struct with a single element, also known as a newtype
/// struct, to be more efficiently serialized than a tuple struct with
/// multiple items. A reasonable implementation would be to forward to
/// `serialize_tuple_struct`.
/// `serialize_tuple_struct` or to just serialize the inner value without wrapping.
fn serialize_newtype_struct<T: Serialize>(
&mut self,
name: &'static str,
@@ -296,18 +334,25 @@ pub trait Serializer {
) -> Result<(), Self::Error>;
/// Begins to serialize a map. This call must be followed by zero or more
/// calls to `serialize_map_elt`, then a call to `serialize_map_end`.
/// calls to `serialize_map_key` and `serialize_map_value`, then a call to
/// `serialize_map_end`.
fn serialize_map(
&mut self,
len: Option<usize>,
) -> Result<Self::MapState, Self::Error>;
/// Serialize a map element. Must have previously called `serialize_map`.
fn serialize_map_elt<K: Serialize, V: Serialize>(
/// Serialize a map key. Must have previously called `serialize_map`.
fn serialize_map_key<T: Serialize>(
&mut self,
state: &mut Self::MapState,
key: K,
value: V,
key: T
) -> Result<(), Self::Error>;
/// Serialize a map value. Must have previously called `serialize_map`.
fn serialize_map_value<T: Serialize>(
&mut self,
state: &mut Self::MapState,
value: T
) -> Result<(), Self::Error>;
/// Finishes serializing a map.
+11 -21
View File
@@ -1,39 +1,29 @@
[package]
name = "serde_codegen"
# DO NOT RELEASE ANY MORE 0.7 RELEASES FROM THIS BRANCH
# USE THE 0.7.x BRANCH
version = "0.8.0-rc2"
version = "0.8.21"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://github.com/serde-rs/serde"
documentation = "https://serde.rs/codegen.html"
keywords = ["serde", "serialization"]
build = "build.rs"
include = ["Cargo.toml", "build.rs", "src/**/*.rs", "src/lib.rs.in"]
include = ["Cargo.toml", "src/**/*.rs"]
[features]
default = ["with-syntex"]
unstable = ["quasi_macros"]
unstable = []
unstable-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 = { version = "^0.15.0", optional = true }
syntex = { version = "^0.38.0", optional = true }
with-syn = []
[dependencies]
aster = { version = "^0.21.1", default-features = false }
clippy = { version = "^0.*", optional = true }
quasi = { version = "^0.15.0", default-features = false }
quasi_macros = { version = "^0.15.0", optional = true }
serde_codegen_internals = { version = "0.4.0-rc1", default-features = false }
syntex = { version = "^0.38.0", optional = true }
syntex_syntax = { version = "^0.38.0", optional = true }
quote = "0.3.8"
serde_codegen_internals = { version = "=0.11.3", default-features = false, path = "../serde_codegen_internals" }
syn = { version = "0.10", features = ["aster", "visit"] }
syntex = { version = "^0.52.0", optional = true }
syntex_syntax = { version = "^0.52.0", optional = true }
-25
View File
@@ -1,25 +0,0 @@
#[cfg(feature = "with-syntex")]
mod inner {
extern crate quasi_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/lib.rs.in");
let dst = Path::new(&out_dir).join("lib.rs");
quasi_codegen::expand(&src, &dst).unwrap();
}
}
#[cfg(not(feature = "with-syntex"))]
mod inner {
pub fn main() {}
}
fn main() {
inner::main();
}
+78 -107
View File
@@ -1,8 +1,6 @@
use aster::AstBuilder;
use std::collections::HashSet;
use syntax::ast;
use syntax::ptr::P;
use syntax::visit;
use syn::{self, aster, visit};
use internals::ast::Item;
use internals::attr;
@@ -10,10 +8,10 @@ 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 {
pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
syn::Generics {
ty_params: generics.ty_params.iter().map(|ty_param| {
ast::TyParam {
syn::TyParam {
default: None,
.. ty_param.clone()
}}).collect(),
@@ -22,24 +20,22 @@ pub fn without_defaults(generics: &ast::Generics) -> ast::Generics {
}
pub fn with_where_predicates(
builder: &AstBuilder,
generics: &ast::Generics,
predicates: &[ast::WherePredicate],
) -> ast::Generics {
builder.from_generics(generics.clone())
generics: &syn::Generics,
predicates: &[syn::WherePredicate],
) -> syn::Generics {
aster::from_generics(generics.clone())
.with_predicates(predicates.to_vec())
.build()
}
pub fn with_where_predicates_from_fields<F>(
builder: &AstBuilder,
item: &Item,
generics: &ast::Generics,
generics: &syn::Generics,
from_field: F,
) -> ast::Generics
where F: Fn(&attr::Field) -> Option<&[ast::WherePredicate]>,
) -> syn::Generics
where F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
{
builder.from_generics(generics.clone())
aster::from_generics(generics.clone())
.with_predicates(
item.body.all_fields()
.flat_map(|field| from_field(&field.attrs))
@@ -47,104 +43,79 @@ pub fn with_where_predicates_from_fields<F>(
.build()
}
// Puts the given bound on any generic type parameters that are used in fields
// for which filter returns true.
//
// For example, the following struct needs the bound `A: Serialize, B: Serialize`.
//
// struct S<'b, A, B: 'b, C> {
// a: A,
// b: Option<&'b B>
// #[serde(skip_serializing)]
// c: C,
// }
pub fn with_bound<F>(
builder: &AstBuilder,
item: &Item,
generics: &ast::Generics,
generics: &syn::Generics,
filter: F,
bound: &ast::Path,
) -> ast::Generics
bound: &syn::Path,
) -> syn::Generics
where F: Fn(&attr::Field) -> bool,
{
builder.from_generics(generics.clone())
struct FindTyParams {
// Set of all generic type parameters on the current struct (A, B, C in
// the example). Initialized up front.
all_ty_params: HashSet<syn::Ident>,
// Set of generic type parameters used in fields for which filter
// returns true (A and B in the example). Filled in as the visitor sees
// them.
relevant_ty_params: HashSet<syn::Ident>,
}
impl visit::Visitor for FindTyParams {
fn visit_path(&mut self, path: &syn::Path) {
if let Some(seg) = path.segments.last() {
if seg.ident == "PhantomData" {
// Hardcoded exception, because PhantomData<T> implements
// Serialize and Deserialize whether or not T implements it.
return;
}
}
if !path.global && path.segments.len() == 1 {
let id = path.segments[0].ident.clone();
if self.all_ty_params.contains(&id) {
self.relevant_ty_params.insert(id);
}
}
visit::walk_path(self, path);
}
}
let all_ty_params: HashSet<_> = generics.ty_params.iter()
.map(|ty_param| ty_param.ident.clone())
.collect();
let relevant_tys = item.body.all_fields()
.filter(|&field| filter(&field.attrs))
.map(|field| &field.ty);
let mut visitor = FindTyParams {
all_ty_params: all_ty_params,
relevant_ty_params: HashSet::new(),
};
for ty in relevant_tys {
visit::walk_ty(&mut visitor, ty);
}
aster::from_generics(generics.clone())
.with_predicates(
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())
generics.ty_params.iter()
.map(|ty_param| ty_param.ident.clone())
.filter(|id| visitor.relevant_ty_params.contains(id))
.map(|id| aster::where_predicate()
// the type parameter that is being bounded e.g. T
.bound().build(aster::ty().id(id))
// the bound e.g. Serialize
.bound().trait_(bound.clone()).build()
.build()))
.build()
}
// 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
}
+432 -613
View File
File diff suppressed because it is too large Load Diff
+116 -39
View File
@@ -2,11 +2,10 @@
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "clippy", 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;
// The `quote!` macro requires deep recursion.
#![recursion_limit = "192"]
extern crate serde_codegen_internals as internals;
#[cfg(feature = "with-syntex")]
@@ -16,30 +15,19 @@ extern crate syntex;
#[macro_use]
extern crate syntex_syntax as syntax;
#[cfg(not(feature = "with-syntex"))]
extern crate syn;
#[macro_use]
extern crate syntax;
#[cfg(not(feature = "with-syntex"))]
extern crate rustc_plugin;
extern crate quote;
#[cfg(feature = "with-syntex")]
use std::path::Path;
#[cfg(not(feature = "with-syntex"))]
use syntax::feature_gate::AttributeType;
mod bound;
mod de;
mod ser;
#[cfg(feature = "with-syntex")]
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>,
{
fn syntex_registry() -> syntex::Registry {
use syntax::{ast, fold};
/// Strip the serde attributes from the crate.
@@ -50,11 +38,11 @@ pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
impl fold::Folder for StripAttributeFolder {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
match attr.node.value.node {
ast::MetaItemKind::List(ref n, _) if n == &"serde" => { return None; }
_ => {}
if attr.value.name == "serde" {
if let ast::MetaItemKind::List(..) = attr.value.node {
return None;
}
}
Some(attr)
}
@@ -71,25 +59,114 @@ pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
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_decorator("derive_Serialize", shim::expand_derive_serialize);
reg.add_decorator("derive_Deserialize", shim::expand_derive_deserialize);
reg.add_post_expansion_pass(strip_attributes);
reg.expand("", src.as_ref(), dst.as_ref())
reg
}
#[cfg(not(feature = "with-syntex"))]
pub fn register(reg: &mut rustc_plugin::Registry) {
reg.register_syntax_extension(
syntax::parse::token::intern("derive_Serialize"),
syntax::ext::base::MultiDecorator(
Box::new(ser::expand_derive_serialize)));
#[cfg(feature = "with-syntex")]
pub fn expand_str(src: &str) -> Result<String, syntex::Error> {
let src = src.to_owned();
reg.register_syntax_extension(
syntax::parse::token::intern("derive_Deserialize"),
syntax::ext::base::MultiDecorator(
Box::new(de::expand_derive_deserialize)));
let expand_thread = move || {
syntex_registry().expand_str("", "", &src)
};
reg.register_attribute("serde".to_owned(), AttributeType::Normal);
syntex::with_extra_stack(expand_thread)
}
#[cfg(feature = "with-syntex")]
pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
where S: AsRef<Path>,
D: AsRef<Path>,
{
let src = src.as_ref().to_owned();
let dst = dst.as_ref().to_owned();
let expand_thread = move || {
syntex_registry().expand("", src, dst)
};
syntex::with_extra_stack(expand_thread)
}
macro_rules! shim {
($name:ident $pkg:ident :: $func:ident) => {
pub fn $func(
cx: &mut ::syntax::ext::base::ExtCtxt,
span: ::syntax::codemap::Span,
meta_item: &::syntax::ast::MetaItem,
annotatable: &::syntax::ext::base::Annotatable,
push: &mut FnMut(::syntax::ext::base::Annotatable)
) {
let item = match *annotatable {
::syntax::ext::base::Annotatable::Item(ref item) => item,
_ => {
cx.span_err(
meta_item.span,
concat!("`#[derive(",
stringify!($name),
")]` may only be applied to structs and enums"));
return;
}
};
use syntax::{attr, ast, visit};
struct MarkSerdeAttributesUsed;
impl visit::Visitor for MarkSerdeAttributesUsed {
fn visit_attribute(&mut self, attr: &ast::Attribute) {
if attr.value.name == "serde" {
if let ast::MetaItemKind::List(..) = attr.value.node {
attr::mark_used(attr);
}
}
}
}
visit::walk_item(&mut MarkSerdeAttributesUsed, item);
use syntax::print::pprust;
let s = pprust::item_to_string(item);
use {syn, $pkg};
let syn_item = syn::parse_macro_input(&s).unwrap();
let expanded = match $pkg::$func(&syn_item) {
Ok(expanded) => expanded.to_string(),
Err(msg) => {
cx.span_err(span, &msg);
return;
}
};
use syntax::parse;
let name = stringify!($name).to_string();
let sess = cx.parse_sess;
let impl_item = parse::parse_item_from_source_str(name, expanded, sess);
push(::syntax::ext::base::Annotatable::Item(impl_item.unwrap().unwrap()));
}
};
}
#[cfg(feature = "with-syntex")]
mod shim {
shim!(Serialize ser::expand_derive_serialize);
shim!(Deserialize de::expand_derive_deserialize);
}
#[cfg(feature = "with-syn")]
#[doc(hidden)]
/// Not public API. Use the serde_derive crate.
pub fn expand_derive_serialize(item: &str) -> Result<quote::Tokens, String> {
let syn_item = syn::parse_macro_input(item).unwrap();
ser::expand_derive_serialize(&syn_item)
}
#[cfg(feature = "with-syn")]
#[doc(hidden)]
/// Not public API. Use the serde_derive crate.
pub fn expand_derive_deserialize(item: &str) -> Result<quote::Tokens, String> {
let syn_item = syn::parse_macro_input(item).unwrap();
de::expand_derive_deserialize(&syn_item)
}
-4
View File
@@ -1,4 +0,0 @@
mod bound;
mod de;
mod ser;
mod span;
+286 -358
View File
@@ -1,104 +1,62 @@
use aster;
use syntax::ast::{self, Ident, MetaItem};
use syntax::codemap::Span;
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ptr::P;
use syn::{self, aster};
use quote::Tokens;
use bound;
use span;
use internals::ast::{Body, Field, Item, Style, Variant};
use internals::{attr, Error};
use internals::{self, attr};
pub fn expand_derive_serialize(
cx: &mut ExtCtxt,
span: Span,
meta_item: &MetaItem,
annotatable: &Annotatable,
push: &mut FnMut(Annotatable)
) {
let item = match *annotatable {
Annotatable::Item(ref item) => item,
_ => {
cx.span_err(
meta_item.span,
"`#[derive(Serialize)]` may only be applied to structs and enums");
return;
}
};
pub fn expand_derive_serialize(item: &syn::MacroInput) -> Result<Tokens, String> {
let ctxt = internals::Ctxt::new();
let item = Item::from_ast(&ctxt, item);
try!(ctxt.check());
let 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 impl_generics = build_impl_generics(&item);
let builder = aster::AstBuilder::new().span(span);
let impl_item = serialize_item(cx, &builder, &item);
push(span::record_expansion(cx, impl_item, "Serialize"))
}
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()
let ty = aster::ty().path()
.segment(item.ident.clone()).with_generics(impl_generics.clone()).build()
.build();
let body = serialize_body(cx,
builder,
&item,
let body = serialize_body(&item,
&impl_generics,
ty.clone());
let where_clause = &impl_generics.where_clause;
let dummy_const = builder.id(format!("_IMPL_SERIALIZE_FOR_{}", item.ident));
let dummy_const = aster::id(format!("_IMPL_SERIALIZE_FOR_{}", item.ident));
quote_item!(cx,
Ok(quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const $dummy_const: () = {
const #dummy_const: () = {
extern crate serde as _serde;
#[automatically_derived]
impl $impl_generics _serde::ser::Serialize for $ty $where_clause {
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,
where __S: _serde::ser::Serializer
{
$body
#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 {
fn build_impl_generics(item: &Item) -> syn::Generics {
let generics = bound::without_defaults(item.generics);
let generics = bound::with_where_predicates_from_fields(
builder, item, &generics,
item, &generics,
|attrs| attrs.ser_bound());
match item.attrs.ser_bound() {
Some(predicates) => {
bound::with_where_predicates(builder, &generics, predicates)
bound::with_where_predicates(&generics, predicates)
}
None => {
bound::with_bound(builder, item, &generics,
bound::with_bound(item, &generics,
needs_serialize_bound,
&builder.path().ids(&["_serde", "ser", "Serialize"]).build())
&aster::path().ids(&["_serde", "ser", "Serialize"]).build())
}
}
}
@@ -114,18 +72,14 @@ fn needs_serialize_bound(attrs: &attr::Field) -> bool {
}
fn serialize_body(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
item: &Item,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
) -> P<ast::Expr> {
impl_generics: &syn::Generics,
ty: syn::Ty,
) -> Tokens {
match item.body {
Body::Enum(ref variants) => {
serialize_item_enum(
cx,
builder,
item.ident,
&item.ident,
impl_generics,
ty,
variants,
@@ -133,12 +87,10 @@ fn serialize_body(
}
Body::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) {
cx.span_bug(item.span, "struct has unnamed fields")
panic!("struct has unnamed fields");
}
serialize_struct(
cx,
builder,
impl_generics,
ty,
fields,
@@ -146,12 +98,10 @@ fn serialize_body(
}
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")
panic!("tuple struct has named fields");
}
serialize_tuple_struct(
cx,
builder,
impl_generics,
ty,
fields,
@@ -159,8 +109,6 @@ fn serialize_body(
}
Body::Struct(Style::Newtype, ref fields) => {
serialize_newtype_struct(
cx,
builder,
impl_generics,
ty,
&fields[0],
@@ -168,129 +116,116 @@ fn serialize_body(
}
Body::Struct(Style::Unit, _) => {
serialize_unit_struct(
cx,
builder,
&item.attrs)
}
}
}
fn serialize_unit_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
item_attrs: &attr::Item,
) -> P<ast::Expr> {
let type_name = name_expr(builder, item_attrs.name());
fn serialize_unit_struct(item_attrs: &attr::Item) -> Tokens {
let type_name = item_attrs.name().serialize_name();
quote_expr!(cx,
_serializer.serialize_unit_struct($type_name)
)
quote! {
_serializer.serialize_unit_struct(#type_name)
}
}
fn serialize_newtype_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
impl_generics: &ast::Generics,
item_ty: P<ast::Ty>,
impl_generics: &syn::Generics,
item_ty: syn::Ty,
field: &Field,
item_attrs: &attr::Item,
) -> P<ast::Expr> {
let type_name = name_expr(builder, item_attrs.name());
) -> Tokens {
let type_name = item_attrs.name().serialize_name();
let mut field_expr = quote_expr!(cx, &self.0);
let mut field_expr = quote!(&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);
field_expr = wrap_serialize_with(
&item_ty, impl_generics, field.ty, path, field_expr);
}
quote_expr!(cx,
_serializer.serialize_newtype_struct($type_name, $field_expr)
)
quote! {
_serializer.serialize_newtype_struct(#type_name, #field_expr)
}
}
fn serialize_tuple_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
impl_generics: &syn::Generics,
ty: syn::Ty,
fields: &[Field],
item_attrs: &attr::Item,
) -> P<ast::Expr> {
) -> Tokens {
let serialize_stmts = serialize_tuple_struct_visitor(
cx,
builder,
ty.clone(),
fields,
impl_generics,
false,
cx.ident_of("serialize_tuple_struct_elt"),
aster::id("serialize_tuple_struct_elt"),
);
let type_name = name_expr(builder, item_attrs.name());
let type_name = item_attrs.name().serialize_name();
let len = serialize_stmts.len();
let let_mut = mut_if(len > 0);
quote_expr!(cx, {
let mut state = try!(_serializer.serialize_tuple_struct($type_name, $len));
$serialize_stmts
_serializer.serialize_tuple_struct_end(state)
})
quote! {
let #let_mut __serde_state = try!(_serializer.serialize_tuple_struct(#type_name, #len));
#(#serialize_stmts)*
_serializer.serialize_tuple_struct_end(__serde_state)
}
}
fn serialize_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
impl_generics: &syn::Generics,
ty: syn::Ty,
fields: &[Field],
item_attrs: &attr::Item,
) -> P<ast::Expr> {
) -> Tokens {
let serialize_fields = serialize_struct_visitor(
cx,
builder,
ty.clone(),
fields,
impl_generics,
false,
cx.ident_of("serialize_struct_elt"),
aster::id("serialize_struct_elt"),
);
let type_name = name_expr(builder, item_attrs.name());
let len = fields.iter()
let type_name = item_attrs.name().serialize_name();
let mut serialized_fields = fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields
.map(|field| {
let ident = field.ident.expect("struct has unnamed fields");
let field_expr = quote_expr!(cx, &self.$ident);
let ident = field.ident.clone().expect("struct has unnamed fields");
let field_expr = quote!(&self.#ident);
match field.attrs.skip_serializing_if() {
Some(path) => quote_expr!(cx, if $path($field_expr) { 0 } else { 1 }),
None => quote_expr!(cx, 1),
Some(path) => quote!(if #path(#field_expr) { 0 } else { 1 }),
None => quote!(1),
}
})
.fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr));
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote_expr!(cx, {
let mut state = try!(_serializer.serialize_struct($type_name, $len));
$serialize_fields
_serializer.serialize_struct_end(state)
})
quote! {
let #let_mut __serde_state = try!(_serializer.serialize_struct(#type_name, #len));
#(#serialize_fields)*
_serializer.serialize_struct_end(__serde_state)
}
}
fn serialize_item_enum(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
type_ident: &syn::Ident,
impl_generics: &syn::Generics,
ty: syn::Ty,
variants: &[Variant],
item_attrs: &attr::Item,
) -> P<ast::Expr> {
) -> Tokens {
let arms: Vec<_> =
variants.iter()
.enumerate()
.map(|(variant_index, variant)| {
serialize_variant(
cx,
builder,
type_ident,
impl_generics,
ty.clone(),
@@ -301,342 +236,335 @@ fn serialize_item_enum(
})
.collect();
quote_expr!(cx,
quote! {
match *self {
$arms
#(#arms)*
}
)
}
}
fn serialize_variant(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident,
generics: &ast::Generics,
ty: P<ast::Ty>,
type_ident: &syn::Ident,
generics: &syn::Generics,
ty: syn::Ty,
variant: &Variant,
variant_index: usize,
item_attrs: &attr::Item,
) -> ast::Arm {
let type_name = name_expr(builder, item_attrs.name());
) -> Tokens {
let type_name = item_attrs.name().serialize_name();
let variant_ident = variant.ident;
let variant_name = name_expr(builder, variant.attrs.name());
let variant_ident = variant.ident.clone();
let variant_name = variant.attrs.name().serialize_name();
match variant.style {
Style::Unit => {
quote_arm!(cx,
$type_ident::$variant_ident => {
_serde::ser::Serializer::serialize_unit_variant(
_serializer,
$type_name,
$variant_index,
$variant_name,
)
}
)
},
Style::Newtype => {
let expr = serialize_newtype_variant(
cx,
builder,
type_name,
variant_index,
variant_name,
ty,
generics,
&variant.fields[0],
);
quote_arm!(cx,
$type_ident::$variant_ident(ref __simple_value) => { $expr }
)
},
Style::Tuple => {
let field_names: Vec<ast::Ident> = (0 .. variant.fields.len())
.map(|i| builder.id(format!("__field{}", i)))
.collect();
let pat = builder.pat().enum_()
.id(type_ident).id(variant_ident).build()
.with_pats(
field_names.iter()
.map(|field| builder.pat().ref_id(field))
)
.build();
let expr = serialize_tuple_variant(
cx,
builder,
type_name,
variant_index,
variant_name,
generics,
ty,
&variant.fields,
);
quote_arm!(cx,
$pat => { $expr }
)
if variant.attrs.skip_serializing() {
let skipped_msg = format!("The enum variant {}::{} cannot be serialized",
type_ident, variant_ident);
let skipped_err = quote! {
Err(_serde::ser::Error::invalid_value(#skipped_msg))
};
let fields_pat = match variant.style {
Style::Unit => quote!(),
Style::Newtype | Style::Tuple => quote!( (..) ),
Style::Struct => quote!( {..} ),
};
quote! {
#type_ident::#variant_ident #fields_pat => #skipped_err,
}
Style::Struct => {
let mut pat = builder.pat().struct_().id(type_ident).id(variant_ident).build();
for field in variant.fields.iter() {
let name = match field.ident {
Some(name) => name,
None => cx.span_bug(field.span, "struct variant has unnamed fields"),
};
pat = pat.with_field_pat(ast::FieldPat {
ident: name,
pat: builder.pat().ref_id(name),
is_shorthand: true,
});
} else { // variant wasn't skipped
match variant.style {
Style::Unit => {
quote! {
#type_ident::#variant_ident =>
_serde::ser::Serializer::serialize_unit_variant(
_serializer,
#type_name,
#variant_index,
#variant_name,
),
}
},
Style::Newtype => {
let block = serialize_newtype_variant(
type_name,
variant_index,
variant_name,
ty,
generics,
&variant.fields[0],
);
quote! {
#type_ident::#variant_ident(ref __simple_value) => #block,
}
},
Style::Tuple => {
let field_names = (0 .. variant.fields.len())
.map(|i| aster::id(format!("__field{}", i)));
let block = serialize_tuple_variant(
type_name,
variant_index,
variant_name,
generics,
ty,
&variant.fields,
);
quote! {
#type_ident::#variant_ident(#(ref #field_names),*) => { #block }
}
}
let pat = pat.build();
Style::Struct => {
let fields = variant.fields.iter()
.map(|f| f.ident.clone().expect("struct variant has unnamed fields"));
let expr = serialize_struct_variant(
cx,
builder,
variant_index,
variant_name,
generics,
ty,
&variant.fields,
item_attrs,
);
let block = serialize_struct_variant(
variant_index,
variant_name,
generics,
ty,
&variant.fields,
item_attrs,
);
quote_arm!(cx,
$pat => { $expr }
)
quote! {
#type_ident::#variant_ident { #(ref #fields),* } => { #block }
}
}
}
}
}
fn serialize_newtype_variant(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_name: P<ast::Expr>,
type_name: String,
variant_index: usize,
variant_name: P<ast::Expr>,
item_ty: P<ast::Ty>,
generics: &ast::Generics,
variant_name: String,
item_ty: syn::Ty,
generics: &syn::Generics,
field: &Field,
) -> P<ast::Expr> {
let mut field_expr = quote_expr!(cx, __simple_value);
) -> Tokens {
let mut field_expr = quote!(__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);
field_expr = wrap_serialize_with(
&item_ty, generics, field.ty, path, field_expr);
}
quote_expr!(cx,
quote! {
_serde::ser::Serializer::serialize_newtype_variant(
_serializer,
$type_name,
$variant_index,
$variant_name,
$field_expr,
#type_name,
#variant_index,
#variant_name,
#field_expr,
)
)
}
}
fn serialize_tuple_variant(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_name: P<ast::Expr>,
type_name: String,
variant_index: usize,
variant_name: P<ast::Expr>,
generics: &ast::Generics,
structure_ty: P<ast::Ty>,
variant_name: String,
generics: &syn::Generics,
structure_ty: syn::Ty,
fields: &[Field],
) -> P<ast::Expr> {
) -> Tokens {
let serialize_stmts = serialize_tuple_struct_visitor(
cx,
builder,
structure_ty,
fields,
generics,
true,
cx.ident_of("serialize_tuple_variant_elt"),
aster::id("serialize_tuple_variant_elt"),
);
let len = serialize_stmts.len();
let let_mut = mut_if(len > 0);
quote_expr!(cx, {
let mut state = try!(_serializer.serialize_tuple_variant($type_name, $variant_index, $variant_name, $len));
$serialize_stmts
_serializer.serialize_tuple_variant_end(state)
})
quote! {
let #let_mut __serde_state = try!(_serializer.serialize_tuple_variant(
#type_name,
#variant_index,
#variant_name,
#len));
#(#serialize_stmts)*
_serializer.serialize_tuple_variant_end(__serde_state)
}
}
fn serialize_struct_variant(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
variant_index: usize,
variant_name: P<ast::Expr>,
generics: &ast::Generics,
ty: P<ast::Ty>,
variant_name: String,
generics: &syn::Generics,
ty: syn::Ty,
fields: &[Field],
item_attrs: &attr::Item,
) -> P<ast::Expr> {
) -> Tokens {
let serialize_fields = serialize_struct_visitor(
cx,
builder,
ty.clone(),
fields,
&generics,
generics,
true,
cx.ident_of("serialize_struct_variant_elt"),
aster::id("serialize_struct_variant_elt"),
);
let item_name = name_expr(builder, item_attrs.name());
let len = fields.iter()
let item_name = item_attrs.name().serialize_name();
let mut serialized_fields = fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields
.map(|field| {
let ident = field.ident.expect("struct has unnamed fields");
let field_expr = quote_expr!(cx, $ident);
let ident = field.ident.clone().expect("struct has unnamed fields");
match field.attrs.skip_serializing_if() {
Some(path) => quote_expr!(cx, if $path($field_expr) { 0 } else { 1 }),
None => quote_expr!(cx, 1),
Some(path) => quote!(if #path(#ident) { 0 } else { 1 }),
None => quote!(1),
}
})
.fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr));
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote_expr!(cx, {
let mut state = try!(_serializer.serialize_struct_variant(
$item_name,
$variant_index,
$variant_name,
$len,
quote! {
let #let_mut __serde_state = try!(_serializer.serialize_struct_variant(
#item_name,
#variant_index,
#variant_name,
#len,
));
$serialize_fields
_serializer.serialize_struct_variant_end(state)
})
#(#serialize_fields)*
_serializer.serialize_struct_variant_end(__serde_state)
}
}
fn serialize_tuple_struct_visitor(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
structure_ty: P<ast::Ty>,
structure_ty: syn::Ty,
fields: &[Field],
generics: &ast::Generics,
generics: &syn::Generics,
is_enum: bool,
func: ast::Ident,
) -> Vec<ast::Stmt> {
func: syn::Ident,
) -> Vec<Tokens> {
fields.iter()
.enumerate()
.map(|(i, field)| {
let mut field_expr = if is_enum {
builder.expr().path().id(format!("__field{}", i)).build()
let id = aster::id(format!("__field{}", i));
quote!(#id)
} else {
builder.expr().ref_().tup_field(i).self_()
let i = aster::id(i);
quote!(&self.#i)
};
let skip = field.attrs.skip_serializing_if()
.map(|path| quote_expr!(cx, $path($field_expr)))
.unwrap_or(quote_expr!(cx, false));
.map(|path| quote!(#path(#field_expr)));
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(cx, builder,
&structure_ty, generics, &field.ty, path, field_expr);
field_expr = wrap_serialize_with(
&structure_ty, generics, field.ty, path, field_expr);
}
quote_stmt!(cx,
if !$skip {
try!(_serializer.$func(&mut state, $field_expr));
}
).unwrap()
let ser = quote! {
try!(_serializer.#func(&mut __serde_state, #field_expr));
};
match skip {
None => ser,
Some(skip) => quote!(if !#skip { #ser }),
}
})
.collect()
}
fn serialize_struct_visitor(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
structure_ty: P<ast::Ty>,
structure_ty: syn::Ty,
fields: &[Field],
generics: &ast::Generics,
generics: &syn::Generics,
is_enum: bool,
func: ast::Ident,
) -> Vec<ast::Stmt> {
func: syn::Ident,
) -> Vec<Tokens> {
fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.map(|field| {
let ident = field.ident.expect("struct has unnamed field");
let ident = field.ident.clone().expect("struct has unnamed field");
let mut field_expr = if is_enum {
quote_expr!(cx, $ident)
quote!(#ident)
} else {
quote_expr!(cx, &self.$ident)
quote!(&self.#ident)
};
let key_expr = name_expr(builder, field.attrs.name());
let key_expr = field.attrs.name().serialize_name();
let skip = field.attrs.skip_serializing_if()
.map(|path| quote_expr!(cx, $path($field_expr)))
.unwrap_or(quote_expr!(cx, false));
.map(|path| quote!(#path(#field_expr)));
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(cx, builder,
&structure_ty, generics, &field.ty, path, field_expr)
field_expr = wrap_serialize_with(
&structure_ty, generics, field.ty, path, field_expr)
}
quote_stmt!(cx,
if !$skip {
try!(_serializer.$func(&mut state, $key_expr, $field_expr));
}
).unwrap()
let ser = quote! {
try!(_serializer.#func(&mut __serde_state, #key_expr, #field_expr));
};
match skip {
None => ser,
Some(skip) => quote!(if !#skip { #ser }),
}
})
.collect()
}
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> {
item_ty: &syn::Ty,
generics: &syn::Generics,
field_ty: &syn::Ty,
path: &syn::Path,
value: Tokens,
) -> Tokens {
let where_clause = &generics.where_clause;
let wrapper_generics = builder.from_generics(generics.clone())
let wrapper_generics = aster::from_generics(generics.clone())
.add_lifetime_bound("'__a")
.lifetime_name("'__a")
.build();
let wrapper_ty = builder.path()
let wrapper_ty = aster::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>,
quote!({
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>
impl #wrapper_generics _serde::ser::Serialize for #wrapper_ty #where_clause {
fn serialize<__S>(&self, __s: &mut __S) -> ::std::result::Result<(), __S::Error>
where __S: _serde::ser::Serializer
{
$path(self.value, __s)
#path(self.value, __s)
}
}
__SerializeWith {
value: $value,
phantom: ::std::marker::PhantomData::<$item_ty>,
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())
// Serialization of an empty struct results in code like:
//
// let mut __serde_state = try!(serializer.serialize_struct("S", 0));
// serializer.serialize_struct_end(__serde_state)
//
// where we want to omit the `mut` to avoid a warning.
fn mut_if(is_mut: bool) -> Option<Tokens> {
if is_mut {
Some(quote!(mut))
} else {
None
}
}
-43
View File
@@ -1,43 +0,0 @@
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)
}
}
+4 -6
View File
@@ -1,20 +1,18 @@
[package]
name = "serde_codegen_internals"
version = "0.4.0-rc1"
version = "0.11.3"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "AST representation used by Serde codegen. Unstable."
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_codegen_internals/"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[features]
default = ["with-syntex"]
unstable-testing = ["clippy"]
with-syntex = ["syntex_syntax", "syntex_errors"]
[dependencies]
clippy = { version = "^0.*", optional = true }
syntex_syntax = { version = "^0.38.0", optional = true }
syntex_errors = { version = "^0.38.0", optional = true }
syn = "0.10"
+29 -55
View File
@@ -1,17 +1,12 @@
use syntax::ast;
use syntax::codemap;
use syntax::ext::base::ExtCtxt;
use syntax::ptr::P;
use syn;
use attr;
use Error;
use Ctxt;
pub struct Item<'a> {
pub ident: ast::Ident,
pub span: codemap::Span,
pub ident: syn::Ident,
pub attrs: attr::Item,
pub body: Body<'a>,
pub generics: &'a ast::Generics,
pub generics: &'a syn::Generics,
}
pub enum Body<'a> {
@@ -20,18 +15,16 @@ pub enum Body<'a> {
}
pub struct Variant<'a> {
pub ident: ast::Ident,
pub span: codemap::Span,
pub ident: syn::Ident,
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 ident: Option<syn::Ident>,
pub attrs: attr::Field,
pub ty: &'a P<ast::Ty>,
pub ty: &'a syn::Ty,
}
pub enum Style {
@@ -42,33 +35,25 @@ pub enum Style {
}
impl<'a> Item<'a> {
pub fn from_ast(
cx: &ExtCtxt,
item: &'a ast::Item,
) -> Result<Item<'a>, Error> {
pub fn from_ast(cx: &Ctxt, item: &'a syn::MacroInput) -> Item<'a> {
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)
let body = match item.body {
syn::Body::Enum(ref variants) => {
Body::Enum(enum_from_ast(cx, variants))
}
ast::ItemKind::Struct(ref variant_data, ref generics) => {
syn::Body::Struct(ref variant_data) => {
let (style, fields) = struct_from_ast(cx, variant_data);
(Body::Struct(style, fields), generics)
}
_ => {
return Err(Error::UnexpectedItemKind);
Body::Struct(style, fields)
}
};
Ok(Item {
ident: item.ident,
span: item.span,
Item {
ident: item.ident.clone(),
attrs: attrs,
body: body,
generics: generics,
})
generics: &item.generics,
}
}
}
@@ -86,16 +71,12 @@ impl<'a> Body<'a> {
}
}
fn enum_from_ast<'a>(
cx: &ExtCtxt,
enum_def: &'a ast::EnumDef,
) -> Vec<Variant<'a>> {
enum_def.variants.iter()
fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>> {
variants.iter()
.map(|variant| {
let (style, fields) = struct_from_ast(cx, &variant.node.data);
let (style, fields) = struct_from_ast(cx, &variant.data);
Variant {
ident: variant.node.name,
span: variant.span,
ident: variant.ident.clone(),
attrs: attr::Variant::from_ast(cx, variant),
style: style,
fields: fields,
@@ -104,36 +85,29 @@ fn enum_from_ast<'a>(
.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, _) => {
fn struct_from_ast<'a>(cx: &Ctxt, data: &'a syn::VariantData) -> (Style, Vec<Field<'a>>) {
match *data {
syn::VariantData::Struct(ref fields) => {
(Style::Struct, fields_from_ast(cx, fields))
}
ast::VariantData::Tuple(ref fields, _) if fields.len() == 1 => {
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
(Style::Newtype, fields_from_ast(cx, fields))
}
ast::VariantData::Tuple(ref fields, _) => {
syn::VariantData::Tuple(ref fields) => {
(Style::Tuple, fields_from_ast(cx, fields))
}
ast::VariantData::Unit(_) => {
syn::VariantData::Unit => {
(Style::Unit, Vec::new())
}
}
}
fn fields_from_ast<'a>(
cx: &ExtCtxt,
fields: &'a [ast::StructField],
) -> Vec<Field<'a>> {
fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field]) -> Vec<Field<'a>> {
fields.iter()
.enumerate()
.map(|(i, field)| {
Field {
ident: field.ident,
span: field.span,
ident: field.ident.clone(),
attrs: attr::Field::from_ast(cx, i, field),
ty: &field.ty,
}
+192 -287
View File
@@ -1,16 +1,7 @@
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};
use Ctxt;
use syn;
use syn::MetaItem::{List, NameValue, Word};
use syn::NestedMetaItem::{Literal, MetaItem};
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
// are `attr::Item::from_ast`, `attr::Variant::from_ast`, and
@@ -20,13 +11,14 @@ use syntax::tokenstream::{self, TokenTree};
// 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>,
struct Attr<'c, T> {
cx: &'c Ctxt,
name: &'static str,
value: Option<Spanned<T>>,
value: Option<T>,
}
impl<'a, 'b, T> Attr<'a, 'b, T> {
fn none(cx: &'a ExtCtxt<'b>, name: &'static str) -> Self {
impl<'c, T> Attr<'c, T> {
fn none(cx: &'c Ctxt, name: &'static str) -> Self {
Attr {
cx: cx,
name: name,
@@ -34,47 +26,40 @@ impl<'a, 'b, T> Attr<'a, 'b, T> {
}
}
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();
fn set(&mut self, value: T) {
if self.value.is_some() {
self.cx.error(format!("duplicate serde attribute `{}`", self.name));
} else {
self.value = Some(respan(span, t));
self.value = Some(value);
}
}
fn set_opt(&mut self, v: Option<Spanned<T>>) {
if let Some(v) = v {
self.set(v.span, v.node);
fn set_opt(&mut self, value: Option<T>) {
if let Some(value) = value {
self.set(value);
}
}
fn set_if_none(&mut self, span: Span, t: T) {
fn set_if_none(&mut self, value: T) {
if self.value.is_none() {
self.value = Some(respan(span, t));
self.value = Some(value);
}
}
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 {
struct BoolAttr<'c>(Attr<'c, ()>);
impl<'c> BoolAttr<'c> {
fn none(cx: &'c Ctxt, name: &'static str) -> Self {
BoolAttr(Attr::none(cx, name))
}
fn set_true(&mut self, span: Span) {
self.0.set(span, ());
fn set_true(&mut self) {
self.0.set(());
}
fn get(&self) -> bool {
@@ -84,18 +69,18 @@ impl<'a, 'b> BoolAttr<'a, 'b> {
#[derive(Debug)]
pub struct Name {
serialize: InternedString,
deserialize: InternedString,
serialize: String,
deserialize: String,
}
impl Name {
/// Return the container name for the container when serializing.
pub fn serialize_name(&self) -> InternedString {
pub fn serialize_name(&self) -> String {
self.serialize.clone()
}
/// Return the container name for the container when deserializing.
pub fn deserialize_name(&self) -> InternedString {
pub fn deserialize_name(&self) -> String {
self.deserialize.clone()
}
}
@@ -105,35 +90,32 @@ impl Name {
pub struct Item {
name: Name,
deny_unknown_fields: bool,
ser_bound: Option<Vec<ast::WherePredicate>>,
de_bound: Option<Vec<ast::WherePredicate>>,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
}
impl Item {
/// Extract out the `#[serde(...)]` attributes from an item.
pub fn from_ast(cx: &ExtCtxt, item: &ast::Item) -> Self {
pub fn from_ast(cx: &Ctxt, item: &syn::MacroInput) -> 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_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 {
match meta_item {
// 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);
MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
ser_name.set(s.clone());
de_name.set(s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"rename" => {
MetaItem(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);
@@ -141,31 +123,33 @@ impl Item {
}
// Parse `#[serde(deny_unknown_fields)]`
ast::MetaItemKind::Word(ref name) if name == &"deny_unknown_fields" => {
deny_unknown_fields.set_true(span);
MetaItem(Word(ref name)) if name == "deny_unknown_fields" => {
deny_unknown_fields.set_true();
}
// 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);
MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
}
}
// Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"bound" => {
MetaItem(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)));
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde container attribute `{}`",
meta_item.name()));
}
Literal(_) => {
cx.error(format!("unexpected literal in serde container attribute"));
}
}
}
@@ -173,8 +157,8 @@ impl Item {
Item {
name: Name {
serialize: ser_name.get().unwrap_or(ident.clone()),
deserialize: de_name.get().unwrap_or(ident),
serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()),
deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()),
},
deny_unknown_fields: deny_unknown_fields.get(),
ser_bound: ser_bound.get(),
@@ -190,11 +174,11 @@ impl Item {
self.deny_unknown_fields
}
pub fn ser_bound(&self) -> Option<&[ast::WherePredicate]> {
pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
self.ser_bound.as_ref().map(|vec| &vec[..])
}
pub fn de_bound(&self) -> Option<&[ast::WherePredicate]> {
pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
}
@@ -203,40 +187,51 @@ impl Item {
#[derive(Debug)]
pub struct Variant {
name: Name,
skip_deserializing: bool,
skip_serializing: bool,
}
impl Variant {
pub fn from_ast(cx: &ExtCtxt, variant: &ast::Variant) -> Self {
pub fn from_ast(cx: &Ctxt, variant: &syn::Variant) -> Self {
let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename");
let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing");
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
let ident = variant.node.name.name.as_str();
for meta_items in variant.node.attrs.iter().filter_map(get_serde_meta_items) {
for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
let span = meta_item.span;
match meta_item.node {
match meta_item {
// 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);
MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
ser_name.set(s.clone());
de_name.set(s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"rename" => {
MetaItem(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(skip_deserializing)]`
MetaItem(Word(ref name)) if name == "skip_deserializing" => {
skip_deserializing.set_true();
}
// Parse `#[serde(skip_serializing)]`
MetaItem(Word(ref name)) if name == "skip_serializing" => {
skip_serializing.set_true();
}
_ => {
cx.span_err(
meta_item.span,
&format!("unknown serde variant attribute `{}`",
meta_item_to_string(meta_item)));
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde variant attribute `{}`",
meta_item.name()));
}
Literal(_) => {
cx.error(format!("unexpected literal in serde variant attribute"));
}
}
}
@@ -244,15 +239,25 @@ impl Variant {
Variant {
name: Name {
serialize: ser_name.get().unwrap_or(ident.clone()),
deserialize: de_name.get().unwrap_or(ident),
serialize: ser_name.get().unwrap_or_else(|| variant.ident.to_string()),
deserialize: de_name.get().unwrap_or_else(|| variant.ident.to_string()),
},
skip_deserializing: skip_deserializing.get(),
skip_serializing: skip_serializing.get(),
}
}
pub fn name(&self) -> &Name {
&self.name
}
pub fn skip_deserializing(&self) -> bool {
self.skip_deserializing
}
pub fn skip_serializing(&self) -> bool {
self.skip_serializing
}
}
/// Represents field attribute information
@@ -261,12 +266,12 @@ pub struct Field {
name: Name,
skip_serializing: bool,
skip_deserializing: bool,
skip_serializing_if: Option<ast::Path>,
skip_serializing_if: Option<syn::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>>,
serialize_with: Option<syn::Path>,
deserialize_with: Option<syn::Path>,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
}
/// Represents the default to use for a field when deserializing.
@@ -277,14 +282,14 @@ pub enum FieldDefault {
/// The default is given by `std::default::Default::default()`.
Default,
/// The default is given by this function.
Path(ast::Path),
Path(syn::Path),
}
impl Field {
/// Extract out the `#[serde(...)]` attributes from a struct field.
pub fn from_ast(cx: &ExtCtxt,
pub fn from_ast(cx: &Ctxt,
index: usize,
field: &ast::StructField) -> Self {
field: &syn::Field) -> Self {
let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename");
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
@@ -297,24 +302,23 @@ impl Field {
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()),
Some(ref ident) => ident.to_string(),
None => 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 {
match meta_item {
// 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);
MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
ser_name.set(s.clone());
de_name.set(s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"rename" => {
MetaItem(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);
@@ -322,69 +326,71 @@ impl Field {
}
// Parse `#[serde(default)]`
ast::MetaItemKind::Word(ref name) if name == &"default" => {
default.set(span, FieldDefault::Default);
MetaItem(Word(ref name)) if name == "default" => {
default.set(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));
MetaItem(NameValue(ref name, ref lit)) if name == "default" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
default.set(FieldDefault::Path(path));
}
}
// Parse `#[serde(skip_serializing)]`
ast::MetaItemKind::Word(ref name) if name == &"skip_serializing" => {
skip_serializing.set_true(span);
MetaItem(Word(ref name)) if name == "skip_serializing" => {
skip_serializing.set_true();
}
// Parse `#[serde(skip_deserializing)]`
ast::MetaItemKind::Word(ref name) if name == &"skip_deserializing" => {
skip_deserializing.set_true(span);
MetaItem(Word(ref name)) if name == "skip_deserializing" => {
skip_deserializing.set_true();
}
// 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);
MetaItem(NameValue(ref name, ref lit)) if name == "skip_serializing_if" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
skip_serializing_if.set(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);
MetaItem(NameValue(ref name, ref lit)) if name == "serialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
serialize_with.set(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);
MetaItem(NameValue(ref name, ref lit)) if name == "deserialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
deserialize_with.set(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);
MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
}
}
// Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"bound" => {
MetaItem(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)));
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde field attribute `{}`",
meta_item.name()));
}
Literal(_) => {
cx.error(format!("unexpected literal in serde field attribute"));
}
}
}
@@ -392,8 +398,8 @@ impl Field {
// 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);
if skip_deserializing.0.value.is_some() {
default.set_if_none(FieldDefault::Default);
}
Field {
@@ -424,7 +430,7 @@ impl Field {
self.skip_deserializing
}
pub fn skip_serializing_if(&self) -> Option<&ast::Path> {
pub fn skip_serializing_if(&self) -> Option<&syn::Path> {
self.skip_serializing_if.as_ref()
}
@@ -432,207 +438,106 @@ impl Field {
&self.default
}
pub fn serialize_with(&self) -> Option<&ast::Path> {
pub fn serialize_with(&self) -> Option<&syn::Path> {
self.serialize_with.as_ref()
}
pub fn deserialize_with(&self) -> Option<&ast::Path> {
pub fn deserialize_with(&self) -> Option<&syn::Path> {
self.deserialize_with.as_ref()
}
pub fn ser_bound(&self) -> Option<&[ast::WherePredicate]> {
pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
self.ser_bound.as_ref().map(|vec| &vec[..])
}
pub fn de_bound(&self) -> Option<&[ast::WherePredicate]> {
pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
}
type SerAndDe<T> = (Option<T>, Option<T>);
fn get_ser_and_de<T, F>(
cx: &ExtCtxt,
attribute: &'static str,
items: &[P<ast::MetaItem>],
cx: &Ctxt,
attr_name: &'static str,
items: &[syn::NestedMetaItem],
f: F
) -> Result<(Option<Spanned<T>>, Option<Spanned<T>>), ()>
where F: Fn(&ExtCtxt, &str, &ast::Lit) -> Result<T, ()>,
) -> Result<SerAndDe<T>, ()>
where F: Fn(&Ctxt, &str, &str, &syn::Lit) -> Result<T, ()>,
{
let mut ser_item = Attr::none(cx, attribute);
let mut de_item = Attr::none(cx, attribute);
let mut ser_item = Attr::none(cx, attr_name);
let mut de_item = Attr::none(cx, attr_name);
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);
match *item {
MetaItem(NameValue(ref name, ref lit)) if name == "serialize" => {
if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) {
ser_item.set(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);
MetaItem(NameValue(ref name, ref lit)) if name == "deserialize" => {
if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) {
de_item.set(v);
}
}
_ => {
cx.span_err(
item.span,
&format!("unknown {} attribute `{}`",
attribute,
meta_item_to_string(item)));
cx.error(format!("malformed {0} attribute, expected `{0}(serialize = ..., deserialize = ...)`",
attr_name));
return Err(());
}
}
}
Ok((ser_item.get_spanned(), de_item.get_spanned()))
Ok((ser_item.get(), de_item.get()))
}
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)
cx: &Ctxt,
items: &[syn::NestedMetaItem],
) -> Result<SerAndDe<String>, ()> {
get_ser_and_de(cx, "rename", items, get_string_from_lit)
}
fn get_where_predicates(
cx: &ExtCtxt,
items: &[P<ast::MetaItem>],
) -> Result<(Option<Spanned<Vec<ast::WherePredicate>>>, Option<Spanned<Vec<ast::WherePredicate>>>), ()> {
cx: &Ctxt,
items: &[syn::NestedMetaItem],
) -> Result<SerAndDe<Vec<syn::WherePredicate>>, ()> {
get_ser_and_de(cx, "bound", items, parse_lit_into_where)
}
pub fn get_serde_meta_items(attr: &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)
pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option<Vec<syn::NestedMetaItem>> {
match attr.value {
List(ref name, ref items) if name == "serde" => {
Some(items.iter().cloned().collect())
}
_ => None
}
}
/// 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_string_from_lit(cx: &Ctxt, attr_name: &str, meta_item_name: &str, lit: &syn::Lit) -> Result<String, ()> {
if let syn::Lit::Str(ref s, _) = *lit {
Ok(s.clone())
} else {
cx.error(format!("expected serde {} attribute to be a string: `{} = \"...\"`",
attr_name, meta_item_name));
Err(())
}
}
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(());
}
}
fn parse_lit_into_path(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::Path, ()> {
let string = try!(get_string_from_lit(cx, attr_name, attr_name, lit));
syn::parse_path(&string).map_err(|err| cx.error(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));
fn parse_lit_into_where(cx: &Ctxt, attr_name: &str, meta_item_name: &str, lit: &syn::Lit) -> Result<Vec<syn::WherePredicate>, ()> {
let string = try!(get_string_from_lit(cx, attr_name, meta_item_name, lit));
if string.is_empty() {
return Ok(Vec::new());
}
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)
})
syn::parse_where_clause(&where_string).map(|wh| wh.predicates).map_err(|err| cx.error(err))
}
+43
View File
@@ -0,0 +1,43 @@
use std::fmt::Display;
use std::cell::RefCell;
#[derive(Default)]
pub struct Ctxt {
errors: RefCell<Option<Vec<String>>>,
}
impl Ctxt {
pub fn new() -> Self {
Ctxt {
errors: RefCell::new(Some(Vec::new())),
}
}
pub fn error<T: Display>(&self, msg: T) {
self.errors.borrow_mut().as_mut().unwrap().push(msg.to_string());
}
pub fn check(self) -> Result<(), String> {
let mut errors = self.errors.borrow_mut().take().unwrap();
match errors.len() {
0 => Ok(()),
1 => Err(errors.pop().unwrap()),
n => {
let mut msg = format!("{} errors:", n);
for err in errors {
msg.push_str("\n\t# ");
msg.push_str(&err);
}
Err(msg)
}
}
}
}
impl Drop for Ctxt {
fn drop(&mut self) {
if self.errors.borrow().is_some() {
panic!("forgot to check for errors");
}
}
}
-19
View File
@@ -1,19 +0,0 @@
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"
}
}
+3 -14
View File
@@ -1,21 +1,10 @@
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", 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;
extern crate syn;
pub mod ast;
pub mod attr;
mod error;
pub use error::Error;
mod ctxt;
pub use ctxt::Ctxt;
+27
View File
@@ -0,0 +1,27 @@
[package]
name = "serde_derive"
version = "0.8.21"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde.rs/codegen.html"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[lib]
name = "serde_derive"
proc-macro = true
[dependencies.serde_codegen]
version = "=0.8.21"
path = "../serde_codegen"
default-features = false
features = ["with-syn"]
[dev-dependencies]
compiletest_rs = "^0.2.0"
fnv = "1.0"
serde = { version = "0.8.21", path = "../serde" }
serde_test = { version = "0.8.21", path = "../serde_test" }
+22
View File
@@ -0,0 +1,22 @@
#![feature(proc_macro, proc_macro_lib)]
extern crate proc_macro;
extern crate serde_codegen;
use proc_macro::TokenStream;
#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
match serde_codegen::expand_derive_serialize(&input.to_string()) {
Ok(expanded) => expanded.parse().unwrap(),
Err(msg) => panic!(msg),
}
}
#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
match serde_codegen::expand_derive_deserialize(&input.to_string()) {
Ok(expanded) => expanded.parse().unwrap(),
Err(msg) => panic!(msg),
}
}
@@ -0,0 +1,12 @@
#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
struct S {
#[serde(rename="x", serialize="y")] //~^^ HELP: unknown serde field attribute `serialize`
x: (),
}
fn main() {}
@@ -0,0 +1,13 @@
#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
struct S {
#[serde(rename="x")]
#[serde(rename(deserialize="y"))] //~^^^ HELP: duplicate serde attribute `rename`
x: (),
}
fn main() {}
@@ -0,0 +1,12 @@
#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
struct S {
#[serde(rename(serialize="x"), rename(serialize="y"))] //~^^ HELP: duplicate serde attribute `rename`
x: (),
}
fn main() {}
@@ -0,0 +1,13 @@
#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
struct S {
#[serde(rename(serialize="x"))]
#[serde(rename="y")] //~^^^ HELP: duplicate serde attribute `rename`
x: (),
}
fn main() {}
@@ -0,0 +1,12 @@
#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
struct S {
#[serde(rename(serialize="x", serialize="y"))] //~^^ HELP: duplicate serde attribute `rename`
x: (),
}
fn main() {}
@@ -0,0 +1,13 @@
#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
struct S {
#[serde(rename(serialize="x"))]
#[serde(rename(serialize="y"))] //~^^^ HELP: duplicate serde attribute `rename`
x: (),
}
fn main() {}
@@ -0,0 +1,11 @@
#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;
#[derive(Serialize, Deserialize)] //~ ERROR: custom derive attribute panicked
struct Test<'a> {
s: &'a str, //~^^ HELP: Serde does not support deserializing fields of type &str
}
fn main() {}
@@ -0,0 +1,12 @@
#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
#[serde(abc="xyz")] //~^ HELP: unknown serde container attribute `abc`
struct A {
x: u32,
}
fn main() { }
@@ -0,0 +1,12 @@
#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
struct C {
#[serde(abc="xyz")] //~^^ HELP: unknown serde field attribute `abc`
x: u32,
}
fn main() { }
@@ -0,0 +1,12 @@
#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
enum E {
#[serde(abc="xyz")] //~^^ HELP: unknown serde variant attribute `abc`
V,
}
fn main() { }
@@ -1,8 +1,9 @@
#![feature(custom_derive, plugin)]
#![plugin(serde_macros, clippy)]
#![feature(proc_macro)]
#![deny(identity_op)]
#[macro_use]
extern crate serde_derive;
// 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.
+10
View File
@@ -0,0 +1,10 @@
#![feature(test, proc_macro)]
#[macro_use]
extern crate serde_derive;
extern crate test;
include!("../../testing/tests/test.rs.in");
mod compile_tests;
-2
View File
@@ -1,2 +0,0 @@
/target
/Cargo.lock
-39
View File
@@ -1,39 +0,0 @@
[package]
name = "serde_macros"
# DO NOT RELEASE ANY MORE 0.7 RELEASES FROM THIS BRANCH
# USE THE 0.7.x BRANCH
version = "0.8.0-rc2"
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]
unstable-testing = ["clippy", "serde/unstable-testing", "serde_codegen/unstable-testing"]
[dependencies]
clippy = { version = "^0.*", optional = true }
serde_codegen = { version = "^0.8.0-rc2", default-features = false, features = ["unstable"] }
[dev-dependencies]
clippy = "^0.*"
compiletest_rs = "^0.2.0"
fnv = "1.0"
rustc-serialize = "^0.3.16"
serde = "0.8.0-rc2"
serde_test = "0.8.0-rc2"
[[test]]
name = "test"
path = "tests/test.rs"
[[bench]]
name = "bench"
path = "benches/bench.rs"
-9
View File
@@ -1,9 +0,0 @@
#![feature(custom_attribute, custom_derive, plugin, test)]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![plugin(serde_macros)]
extern crate rustc_serialize;
extern crate serde;
extern crate test;
include!("../../testing/benches/bench.rs.in");
-12
View File
@@ -1,12 +0,0 @@
#![feature(plugin_registrar, rustc_private)]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
extern crate serde_codegen;
extern crate rustc_plugin;
#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut rustc_plugin::Registry) {
serde_codegen::register(reg);
}
@@ -1,32 +0,0 @@
#![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() {}
@@ -1,30 +0,0 @@
#![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() { }
@@ -1,9 +0,0 @@
#![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() {}
-9
View File
@@ -1,9 +0,0 @@
#![feature(test, custom_attribute, custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
extern crate test;
include!("../../testing/tests/test.rs.in");
mod compile_tests;
+4 -5
View File
@@ -1,16 +1,15 @@
[package]
name = "serde_test"
# DO NOT RELEASE ANY MORE 0.7 RELEASES FROM THIS BRANCH
# USE THE 0.7.x BRANCH
version = "0.8.0-rc2"
version = "0.8.21"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde-rs.github.io/serde/serde/"
documentation = "https://docs.serde.rs/serde_test/"
readme = "../README.md"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[dependencies]
serde = "0.8.0-rc2"
serde = { version = "0.8.21", path = "../serde" }
+90 -1
View File
@@ -110,6 +110,95 @@ impl<I> de::Deserializer for Deserializer<I>
{
type Error = Error;
fn deserialize_seq<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_struct_field<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_map<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_unit<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_bytes<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_ignored_any<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_string<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_str<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_char<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i64<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i32<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i16<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i8<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u64<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u32<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u16<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u8<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_f32<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_f64<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_bool<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_usize<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_isize<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
@@ -241,7 +330,7 @@ impl<I> de::Deserializer for Deserializer<I>
}
}
fn deserialize_fixed_size_array<V>(&mut self,
fn deserialize_seq_fixed_size<V>(&mut self,
len: usize,
visitor: V) -> Result<V::Value, Error>
where V: Visitor,
+5 -2
View File
@@ -259,9 +259,12 @@ impl<'a, I> ser::Serializer for Serializer<'a, I>
Ok(())
}
fn serialize_map_elt<K, V>(&mut self, _: &mut (), key: K, value: V) -> Result<(), Self::Error> where K: Serialize, V: Serialize {
fn serialize_map_key<T>(&mut self, _: &mut (), key: T) -> Result<(), Self::Error> where T: Serialize {
assert_eq!(self.tokens.next(), Some(&Token::MapSep));
try!(key.serialize(self));
key.serialize(self)
}
fn serialize_map_value<T>(&mut self, _: &mut (), value: T) -> Result<(), Self::Error> where T: Serialize {
value.serialize(self)
}
+3 -6
View File
@@ -1,11 +1,12 @@
[package]
name = "serde_testing"
version = "0.8.0-rc2"
version = "0.8.21"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "http://serde-rs.github.io/serde/serde"
documentation = "https://docs.serde.rs/serde/"
readme = "README.md"
keywords = ["serialization"]
build = "build.rs"
@@ -28,7 +29,3 @@ clippy = { version = "^0.*", optional = true }
[[test]]
name = "test"
path = "tests/test.rs"
[[bench]]
name = "bench"
path = "benches/bench.rs"
-9
View File
@@ -1,9 +0,0 @@
#![feature(test)]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
extern crate rustc_serialize;
extern crate serde;
extern crate test;
include!(concat!(env!("OUT_DIR"), "/bench.rs"));
-4
View File
@@ -1,4 +0,0 @@
mod bench_enum;
mod bench_map;
mod bench_struct;
mod bench_vec;
-466
View File
@@ -1,466 +0,0 @@
use test::Bencher;
use std::error;
use std::fmt;
use rustc_serialize::Decodable;
use serde;
use serde::de::Deserialize;
//////////////////////////////////////////////////////////////////////////////
#[derive(Clone, PartialEq, Debug, RustcDecodable, Deserialize)]
pub enum Animal {
Dog,
Frog(String, isize)
}
//////////////////////////////////////////////////////////////////////////////
#[derive(Debug)]
pub enum Error {
EndOfStream,
Syntax,
}
impl serde::de::Error for Error {
fn custom<T: Into<String>>(_: T) -> Error { Error::Syntax }
fn end_of_stream() -> Error { Error::EndOfStream }
fn unknown_field(_: &str) -> Error { Error::Syntax }
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 {
use rustc_serialize::Decoder;
use super::{Animal, Error};
use super::Animal::{Dog, Frog};
enum State {
Animal(Animal),
Isize(isize),
String(String),
}
pub struct AnimalDecoder {
stack: Vec<State>,
}
impl AnimalDecoder {
#[inline]
pub fn new(animal: Animal) -> AnimalDecoder {
AnimalDecoder {
stack: vec!(State::Animal(animal)),
}
}
}
impl Decoder for AnimalDecoder {
type Error = Error;
fn error(&mut self, _: &str) -> Error { Error::Syntax }
// Primitive types:
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(State::Isize(x)) => Ok(x),
_ => 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) }
#[inline]
fn read_str(&mut self) -> Result<String, Error> {
match self.stack.pop() {
Some(State::String(x)) => Ok(x),
_ => Err(Error::Syntax),
}
}
// Compound types:
#[inline]
fn read_enum<T, F>(&mut self, name: &str, f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
match self.stack.pop() {
Some(State::Animal(animal)) => {
self.stack.push(State::Animal(animal));
if name == "Animal" {
f(self)
} else {
Err(Error::Syntax)
}
}
_ => Err(Error::Syntax)
}
}
#[inline]
fn read_enum_variant<T, F>(&mut self, names: &[&str], f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder, usize) -> Result<T, Error>,
{
let name = match self.stack.pop() {
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::Syntax); }
};
let idx = match names.iter().position(|n| *n == name) {
Some(idx) => idx,
None => { return Err(Error::Syntax); }
};
f(self, idx)
}
#[inline]
fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
f(self)
}
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::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::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::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::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::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::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::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::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::Syntax)
}
#[inline]
fn read_seq<T, F>(&mut self, f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder, usize) -> Result<T, Error>,
{
f(self, 3)
}
#[inline]
fn read_seq_elt<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
f(self)
}
fn read_map<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder, usize) -> Result<T, Error>,
{
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::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::Syntax)
}
}
}
//////////////////////////////////////////////////////////////////////////////
mod deserializer {
use super::{Animal, Error};
use serde::de;
#[derive(Debug)]
enum State {
Animal(Animal),
Isize(isize),
Str(&'static str),
String(String),
UnitState,
}
pub struct AnimalDeserializer {
stack: Vec<State>,
}
impl AnimalDeserializer {
#[inline]
pub fn new(animal: Animal) -> AnimalDeserializer {
AnimalDeserializer {
stack: vec!(State::Animal(animal)),
}
}
}
impl de::Deserializer for AnimalDeserializer {
type Error = Error;
#[inline]
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.stack.pop() {
Some(State::Isize(value)) => {
visitor.visit_isize(value)
}
Some(State::String(value)) => {
visitor.visit_string(value)
}
Some(State::Str(value)) => {
visitor.visit_str(value)
}
Some(State::UnitState) => {
visitor.visit_unit()
}
Some(_) => {
Err(Error::Syntax)
}
None => {
Err(Error::EndOfStream)
}
}
}
#[inline]
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::Animal(Animal::Dog)) => {
self.stack.push(State::UnitState);
self.stack.push(State::Str("Dog"));
visitor.visit(DogVisitor {
de: self,
})
}
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::Syntax)
}
None => {
Err(Error::EndOfStream)
}
}
}
}
struct DogVisitor<'a> {
de: &'a mut AnimalDeserializer,
}
impl<'a> de::VariantVisitor for DogVisitor<'a> {
type Error = Error;
fn visit_variant<V>(&mut self) -> Result<V, Error>
where V: de::Deserialize
{
de::Deserialize::deserialize(self.de)
}
fn visit_unit(&mut self) -> Result<(), Error> {
de::Deserialize::deserialize(self.de)
}
}
struct FrogVisitor<'a> {
de: &'a mut AnimalDeserializer,
state: usize,
}
impl<'a> de::VariantVisitor for FrogVisitor<'a> {
type Error = Error;
fn visit_variant<V>(&mut self) -> Result<V, Error>
where V: de::Deserialize
{
de::Deserialize::deserialize(self.de)
}
fn visit_tuple<V>(&mut self,
_len: usize,
mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_seq(self)
}
}
impl<'a> de::SeqVisitor for FrogVisitor<'a> {
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: de::Deserialize,
{
match self.state {
0 => {
self.state += 1;
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
1 => {
self.state += 1;
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
_ => {
Ok(None)
}
}
}
fn end(&mut self) -> Result<(), Error> {
if self.state == 2 {
Ok(())
} else {
Err(Error::Syntax)
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = 2 - self.state;
(len, Some(len))
}
}
}
//////////////////////////////////////////////////////////////////////////////
#[bench]
fn bench_decoder_dog(b: &mut Bencher) {
b.iter(|| {
let animal = Animal::Dog;
let mut d = decoder::AnimalDecoder::new(animal.clone());
let value: Animal = Decodable::decode(&mut d).unwrap();
assert_eq!(value, animal);
})
}
#[bench]
fn bench_decoder_frog(b: &mut Bencher) {
b.iter(|| {
let animal = Animal::Frog("Henry".to_owned(), 349);
let mut d = decoder::AnimalDecoder::new(animal.clone());
let value: Animal = Decodable::decode(&mut d).unwrap();
assert_eq!(value, animal);
})
}
#[bench]
fn bench_deserializer_dog(b: &mut Bencher) {
b.iter(|| {
let animal = Animal::Dog;
let mut d = deserializer::AnimalDeserializer::new(animal.clone());
let value: Animal = Deserialize::deserialize(&mut d).unwrap();
assert_eq!(value, animal);
})
}
#[bench]
fn bench_deserializer_frog(b: &mut Bencher) {
b.iter(|| {
let animal = Animal::Frog("Henry".to_owned(), 349);
let mut d = deserializer::AnimalDeserializer::new(animal.clone());
let value: Animal = Deserialize::deserialize(&mut d).unwrap();
assert_eq!(value, animal);
})
}
-474
View File
@@ -1,474 +0,0 @@
use std::fmt::Debug;
use std::fmt;
use std::error;
use std::collections::HashMap;
use test::Bencher;
use rustc_serialize::{Decoder, Decodable};
use serde;
use serde::de::{Deserializer, Deserialize};
//////////////////////////////////////////////////////////////////////////////
#[derive(PartialEq, Debug)]
pub enum Error {
EndOfStream,
Syntax,
MissingField,
}
impl serde::de::Error for Error {
fn custom<T: Into<String>>(_: T) -> Error { Error::Syntax }
fn end_of_stream() -> Error { Error::EndOfStream }
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 std::collections::hash_map::IntoIter;
use rustc_serialize;
use super::Error;
enum Value {
String(String),
Isize(isize),
}
pub struct IsizeDecoder {
len: usize,
iter: IntoIter<String, isize>,
stack: Vec<Value>,
}
impl IsizeDecoder {
#[inline]
pub fn new(values: HashMap<String, isize>) -> IsizeDecoder {
IsizeDecoder {
len: values.len(),
iter: values.into_iter(),
stack: vec!(),
}
}
}
impl rustc_serialize::Decoder for IsizeDecoder {
type Error = Error;
fn error(&mut self, _msg: &str) -> Error {
Error::Syntax
}
// Primitive types:
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(Value::Isize(x)) => Ok(x),
Some(_) => Err(Error::Syntax),
None => Err(Error::EndOfStream),
}
}
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(Value::String(x)) => Ok(x),
Some(_) => Err(Error::Syntax),
None => Err(Error::EndOfStream),
}
}
// Compound types:
fn read_enum<T, F>(&mut self, _name: &str, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
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::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::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::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::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::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::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::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::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::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::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::Syntax)
}
fn read_seq<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder, usize) -> Result<T, Error>,
{
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::Syntax)
}
#[inline]
fn read_map<T, F>(&mut self, f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder, usize) -> Result<T, Error>,
{
let len = self.len;
f(self, len)
}
#[inline]
fn read_map_elt_key<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
match self.iter.next() {
Some((key, value)) => {
self.stack.push(Value::Isize(value));
self.stack.push(Value::String(key));
f(self)
}
None => {
Err(Error::Syntax)
}
}
}
#[inline]
fn read_map_elt_val<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
f(self)
}
}
}
//////////////////////////////////////////////////////////////////////////////
mod deserializer {
use std::collections::HashMap;
use std::collections::hash_map;
use super::Error;
use serde::de;
#[derive(PartialEq, Debug)]
enum State {
StartState,
Key(String),
Value(isize),
}
pub struct IsizeDeserializer {
stack: Vec<State>,
iter: hash_map::IntoIter<String, isize>,
}
impl IsizeDeserializer {
#[inline]
pub fn new(values: HashMap<String, isize>) -> IsizeDeserializer {
IsizeDeserializer {
stack: vec!(State::StartState),
iter: values.into_iter(),
}
}
}
impl de::Deserializer for IsizeDeserializer {
type Error = 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::Key(key)) => {
visitor.visit_string(key)
}
Some(State::Value(value)) => {
visitor.visit_isize(value)
}
None => {
Err(Error::EndOfStream)
}
}
}
}
impl de::MapVisitor for IsizeDeserializer {
type Error = Error;
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
where K: de::Deserialize,
{
match self.iter.next() {
Some((key, value)) => {
self.stack.push(State::Value(value));
self.stack.push(State::Key(key));
Ok(Some(try!(de::Deserialize::deserialize(self))))
}
None => {
Ok(None)
}
}
}
fn visit_value<V>(&mut self) -> Result<V, Error>
where V: de::Deserialize,
{
de::Deserialize::deserialize(self)
}
fn end(&mut self) -> Result<(), Error> {
match self.iter.next() {
Some(_) => Err(Error::Syntax),
None => Ok(()),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
/*
impl Iterator for IsizeDeserializer {
type Item = Result<de::Token, Error>;
#[inline]
fn next(&mut self) -> Option<Result<de::Token, Error>> {
match self.stack.pop() {
Some(State::StartState) => {
self.stack.push(KeyOrEndState);
Some(Ok(de::Token::MapStart(self.len)))
}
Some(State::KeyOrEndState) => {
match self.iter.next() {
Some((key, value)) => {
self.stack.push(Value(value));
Some(Ok(de::Token::String(key)))
}
None => {
self.stack.push(EndState);
Some(Ok(de::Token::End))
}
}
}
Some(State::Value(x)) => {
self.stack.push(KeyOrEndState);
Some(Ok(de::Token::Isize(x)))
}
Some(EndState) => {
None
}
None => {
None
}
}
}
}
impl de::Deserializer<Error> for IsizeDeserializer {
#[inline]
fn end_of_stream(&mut self) -> Error {
EndOfStream
}
#[inline]
fn syntax(&mut self, _token: de::Token, _expected: &[de::TokenKind]) -> Error {
Syntax
}
#[inline]
fn unexpected_name(&mut self, _token: de::Token) -> Error {
Syntax
}
#[inline]
fn conversion_error(&mut self, _token: de::Token) -> Error {
Syntax
}
#[inline]
fn missing_field<
T: de::Deserialize<IsizeDeserializer, Error>
>(&mut self, _field: &'static str) -> Result<T, Error> {
Err(Error::Syntax)
}
}
*/
}
//////////////////////////////////////////////////////////////////////////////
fn run_decoder<
D: Decoder<Error=Error>,
T: Clone + PartialEq + Debug + Decodable
>(mut d: D, value: T) {
let v = Decodable::decode(&mut d);
assert_eq!(Ok(value), v);
}
#[bench]
fn bench_decoder_000(b: &mut Bencher) {
b.iter(|| {
let m: HashMap<String, isize> = HashMap::new();
run_decoder(decoder::IsizeDecoder::new(m.clone()), m)
})
}
#[bench]
fn bench_decoder_003(b: &mut Bencher) {
b.iter(|| {
let mut m: HashMap<String, isize> = HashMap::new();
for i in 0 .. 3 {
m.insert(i.to_string(), i);
}
run_decoder(decoder::IsizeDecoder::new(m.clone()), m)
})
}
#[bench]
fn bench_decoder_100(b: &mut Bencher) {
b.iter(|| {
let mut m: HashMap<String, isize> = HashMap::new();
for i in 0 .. 100 {
m.insert(i.to_string(), i);
}
run_decoder(decoder::IsizeDecoder::new(m.clone()), m)
})
}
fn run_deserializer<D, T>(mut d: D, value: T)
where D: Deserializer,
D::Error: Debug + PartialEq,
T: Clone + PartialEq + Debug + Deserialize
{
let v = T::deserialize(&mut d);
assert_eq!(Ok(value), v);
}
#[bench]
fn bench_deserializer_000(b: &mut Bencher) {
b.iter(|| {
let m: HashMap<String, isize> = HashMap::new();
run_deserializer(deserializer::IsizeDeserializer::new(m.clone()), m)
})
}
#[bench]
fn bench_deserializer_003(b: &mut Bencher) {
b.iter(|| {
let mut m: HashMap<String, isize> = HashMap::new();
for i in 0 .. 3 {
m.insert(i.to_string(), i);
}
run_deserializer(deserializer::IsizeDeserializer::new(m.clone()), m)
})
}
#[bench]
fn bench_deserializer_100(b: &mut Bencher) {
b.iter(|| {
let mut m: HashMap<String, isize> = HashMap::new();
for i in 0 .. 100 {
m.insert(i.to_string(), i);
}
run_deserializer(deserializer::IsizeDeserializer::new(m.clone()), m)
})
}
-745
View File
@@ -1,745 +0,0 @@
use std::collections::HashMap;
use test::Bencher;
use std::fmt;
use std::error;
use rustc_serialize::Decodable;
use serde;
use serde::de::Deserialize;
//////////////////////////////////////////////////////////////////////////////
#[derive(Clone, PartialEq, Debug, RustcDecodable, Deserialize)]
pub struct Inner {
a: (),
b: usize,
c: HashMap<String, Option<char>>,
}
//////////////////////////////////////////////////////////////////////////////
#[derive(Clone, PartialEq, Debug, RustcDecodable, Deserialize)]
pub struct Outer {
inner: Vec<Inner>,
}
//////////////////////////////////////////////////////////////////////////////
#[derive(Debug, PartialEq)]
pub enum Error {
EndOfStream,
Syntax,
MissingField,
OtherError,
}
impl serde::de::Error for Error {
fn custom<T: Into<String>>(_: T) -> Error { Error::Syntax }
fn end_of_stream() -> Error { Error::EndOfStream }
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};
#[derive(Debug)]
enum State {
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 {
stack: Vec<State>,
}
impl OuterDecoder {
#[inline]
pub fn new(animal: Outer) -> OuterDecoder {
OuterDecoder {
stack: vec!(State::Outer(animal)),
}
}
}
impl Decoder for OuterDecoder {
type Error = Error;
fn error(&mut self, _msg: &str) -> Error {
Error::OtherError
}
// Primitive types:
#[inline]
fn read_nil(&mut self) -> Result<(), Error> {
match self.stack.pop() {
Some(State::Null) => Ok(()),
_ => Err(Error::Syntax),
}
}
#[inline]
fn read_usize(&mut self) -> Result<usize, Error> {
match self.stack.pop() {
Some(State::Usize(value)) => Ok(value),
_ => 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) }
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(State::Char(c)) => Ok(c),
_ => Err(Error::Syntax),
}
}
#[inline]
fn read_str(&mut self) -> Result<String, Error> {
match self.stack.pop() {
Some(State::String(value)) => Ok(value),
_ => Err(Error::Syntax),
}
}
// Compound types:
fn read_enum<T, F>(&mut self, _name: &str, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
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::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::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::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::Syntax)
}
#[inline]
fn read_struct<T, F>(&mut self, s_name: &str, _len: usize, f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
match self.stack.pop() {
Some(State::Outer(Outer { inner })) => {
if s_name == "Outer" {
self.stack.push(State::Vec(inner));
self.stack.push(State::Field("inner"));
f(self)
} else {
Err(Error::Syntax)
}
}
Some(State::Inner(Inner { a: (), b, c })) => {
if s_name == "Inner" {
self.stack.push(State::Map(c));
self.stack.push(State::Field("c"));
self.stack.push(State::Usize(b));
self.stack.push(State::Field("b"));
self.stack.push(State::Null);
self.stack.push(State::Field("a"));
f(self)
} else {
Err(Error::Syntax)
}
}
_ => Err(Error::Syntax),
}
}
#[inline]
fn read_struct_field<T, F>(&mut self, f_name: &str, _f_idx: usize, f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
match self.stack.pop() {
Some(State::Field(name)) => {
if f_name == name {
f(self)
} else {
Err(Error::Syntax)
}
}
_ => 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::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::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::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::Syntax)
}
// Specialized types:
#[inline]
fn read_option<T, F>(&mut self, f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder, bool) -> Result<T, Error>,
{
match self.stack.pop() {
Some(State::Option(b)) => f(self, b),
_ => Err(Error::Syntax),
}
}
#[inline]
fn read_seq<T, F>(&mut self, f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder, usize) -> Result<T, Error>,
{
match self.stack.pop() {
Some(State::Vec(value)) => {
let len = value.len();
for inner in value.into_iter().rev() {
self.stack.push(State::Inner(inner));
}
f(self, len)
}
_ => Err(Error::Syntax)
}
}
#[inline]
fn read_seq_elt<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
f(self)
}
#[inline]
fn read_map<T, F>(&mut self, f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder, usize) -> Result<T, Error>,
{
match self.stack.pop() {
Some(State::Map(map)) => {
let len = map.len();
for (key, value) in map {
match value {
Some(c) => {
self.stack.push(State::Char(c));
self.stack.push(State::Option(true));
}
None => {
self.stack.push(State::Option(false));
}
}
self.stack.push(State::String(key));
}
f(self, len)
}
_ => Err(Error::Syntax),
}
}
#[inline]
fn read_map_elt_key<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
f(self)
}
#[inline]
fn read_map_elt_val<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
f(self)
}
}
}
//////////////////////////////////////////////////////////////////////////////
mod deserializer {
use std::collections::HashMap;
use std::collections::hash_map;
use std::vec;
use super::{Outer, Inner};
use super::Error;
use serde::de;
#[derive(Debug)]
enum State {
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 {
stack: Vec<State>,
}
impl OuterDeserializer {
#[inline]
pub fn new(outer: Outer) -> OuterDeserializer {
OuterDeserializer {
stack: vec!(State::Outer(outer)),
}
}
}
impl de::Deserializer for OuterDeserializer {
type Error = Error;
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.stack.pop() {
Some(State::Vec(value)) => {
visitor.visit_seq(OuterSeqVisitor {
de: self,
iter: value.into_iter(),
})
}
Some(State::Map(value)) => {
visitor.visit_map(MapVisitor {
de: self,
iter: value.into_iter(),
})
}
Some(State::Null) => {
visitor.visit_unit()
}
Some(State::Usize(x)) => {
visitor.visit_usize(x)
}
Some(State::Char(x)) => {
visitor.visit_char(x)
}
Some(State::Str(x)) => {
visitor.visit_str(x)
}
Some(State::String(x)) => {
visitor.visit_string(x)
}
Some(State::Option(false)) => {
visitor.visit_none()
}
Some(State::Option(true)) => {
visitor.visit_some(self)
}
Some(_) => Err(Error::Syntax),
None => Err(Error::EndOfStream),
}
}
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::Outer(Outer { inner })) => {
if name != "Outer" {
return Err(Error::Syntax);
}
self.stack.push(State::Vec(inner));
self.stack.push(State::Str("inner"));
visitor.visit_map(OuterMapVisitor {
de: self,
state: 0,
})
}
Some(State::Inner(Inner { a: (), b, c })) => {
if name != "Inner" {
return Err(Error::Syntax);
}
self.stack.push(State::Map(c));
self.stack.push(State::Str("c"));
self.stack.push(State::Usize(b));
self.stack.push(State::Str("b"));
self.stack.push(State::Null);
self.stack.push(State::Str("a"));
visitor.visit_map(InnerMapVisitor {
de: self,
state: 0,
})
}
_ => {
Err(Error::Syntax)
}
}
}
}
struct OuterMapVisitor<'a> {
de: &'a mut OuterDeserializer,
state: usize,
}
impl<'a> de::MapVisitor for OuterMapVisitor<'a> {
type Error = Error;
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
where K: de::Deserialize,
{
match self.state {
0 => {
self.state += 1;
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
_ => {
Ok(None)
}
}
}
fn visit_value<V>(&mut self) -> Result<V, Error>
where V: de::Deserialize,
{
de::Deserialize::deserialize(self.de)
}
fn end(&mut self) -> Result<(), Error> {
if self.state == 1 {
Ok(())
} else {
Err(Error::Syntax)
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = 1 - self.state;
(len, Some(len))
}
}
struct OuterSeqVisitor<'a> {
de: &'a mut OuterDeserializer,
iter: vec::IntoIter<Inner>,
}
impl<'a> de::SeqVisitor for OuterSeqVisitor<'a> {
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: de::Deserialize,
{
match self.iter.next() {
Some(value) => {
self.de.stack.push(State::Inner(value));
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
None => {
Ok(None)
}
}
}
fn end(&mut self) -> Result<(), Error> {
match self.iter.next() {
Some(_) => Err(Error::Syntax),
None => Ok(()),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
struct InnerMapVisitor<'a> {
de: &'a mut OuterDeserializer,
state: usize,
}
impl<'a> de::MapVisitor for InnerMapVisitor<'a> {
type Error = Error;
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
where K: de::Deserialize,
{
match self.state {
0 ... 2 => {
self.state += 1;
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
_ => {
Ok(None)
}
}
}
fn visit_value<V>(&mut self) -> Result<V, Error>
where V: de::Deserialize,
{
de::Deserialize::deserialize(self.de)
}
fn end(&mut self) -> Result<(), Error> {
if self.state == 3 {
Ok(())
} else {
Err(Error::Syntax)
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = 1 - self.state;
(len, Some(len))
}
}
struct MapVisitor<'a> {
de: &'a mut OuterDeserializer,
iter: hash_map::IntoIter<String, Option<char>>,
}
impl<'a> de::MapVisitor for MapVisitor<'a> {
type Error = Error;
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
where K: de::Deserialize,
{
match self.iter.next() {
Some((key, Some(value))) => {
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::Option(false));
self.de.stack.push(State::String(key));
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
None => {
Ok(None)
}
}
}
fn visit_value<V>(&mut self) -> Result<V, Error>
where V: de::Deserialize,
{
de::Deserialize::deserialize(self.de)
}
fn end(&mut self) -> Result<(), Error> {
match self.iter.next() {
Some(_) => Err(Error::Syntax),
None => Ok(()),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
}
#[bench]
fn bench_decoder_0_0(b: &mut Bencher) {
b.iter(|| {
let mut map = HashMap::new();
map.insert("abc".to_owned(), Some('c'));
let outer = Outer {
inner: vec!(),
};
let mut d = decoder::OuterDecoder::new(outer.clone());
let value: Result<Outer, Error> = Decodable::decode(&mut d);
assert_eq!(value, Ok(outer));
})
}
#[bench]
fn bench_decoder_1_0(b: &mut Bencher) {
b.iter(|| {
let map = HashMap::new();
let outer = Outer {
inner: vec!(
Inner {
a: (),
b: 5,
c: map,
},
)
};
let mut d = decoder::OuterDecoder::new(outer.clone());
let value: Result<Outer, Error> = Decodable::decode(&mut d);
assert_eq!(value, Ok(outer));
})
}
#[bench]
fn bench_decoder_1_5(b: &mut Bencher) {
b.iter(|| {
let mut map = HashMap::new();
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!(
Inner {
a: (),
b: 5,
c: map,
},
)
};
let mut d = decoder::OuterDecoder::new(outer.clone());
let value: Result<Outer, Error> = Decodable::decode(&mut d);
assert_eq!(value, Ok(outer));
})
}
#[bench]
fn bench_deserializer_0_0(b: &mut Bencher) {
b.iter(|| {
let outer = Outer {
inner: vec!(),
};
let mut d = deserializer::OuterDeserializer::new(outer.clone());
let value: Result<Outer, Error> = Deserialize::deserialize(&mut d);
assert_eq!(value, Ok(outer));
})
}
#[bench]
fn bench_deserializer_1_0(b: &mut Bencher) {
b.iter(|| {
let map = HashMap::new();
let outer = Outer {
inner: vec!(
Inner {
a: (),
b: 5,
c: map,
},
)
};
let mut d = deserializer::OuterDeserializer::new(outer.clone());
let value: Result<Outer, Error> = Deserialize::deserialize(&mut d);
assert_eq!(value, Ok(outer));
})
}
#[bench]
fn bench_deserializer_1_5(b: &mut Bencher) {
b.iter(|| {
let mut map = HashMap::new();
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!(
Inner {
a: (),
b: 5,
c: map,
},
)
};
let mut d = deserializer::OuterDeserializer::new(outer.clone());
let value: Result<Outer, Error> = Deserialize::deserialize(&mut d);
assert_eq!(value, Ok(outer));
})
}
-628
View File
@@ -1,628 +0,0 @@
use std::fmt::Debug;
use std::fmt;
use std::error;
use test::Bencher;
use rustc_serialize::{Decoder, Decodable};
use serde;
use serde::de::{Deserializer, Deserialize};
//////////////////////////////////////////////////////////////////////////////
#[derive(PartialEq, Debug)]
pub enum Error {
EndOfStream,
Syntax,
}
impl serde::de::Error for Error {
fn custom<T: Into<String>>(_: T) -> Error { Error::Syntax }
fn end_of_stream() -> Error { Error::EndOfStream }
fn unknown_field(_: &str) -> Error { Error::Syntax }
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 {
use std::vec;
use rustc_serialize;
use super::Error;
pub struct UsizeDecoder {
len: usize,
iter: vec::IntoIter<usize>,
}
impl UsizeDecoder {
#[inline]
pub fn new(values: Vec<usize>) -> UsizeDecoder {
UsizeDecoder {
len: values.len(),
iter: values.into_iter(),
}
}
}
impl rustc_serialize::Decoder for UsizeDecoder {
type Error = Error;
fn error(&mut self, _: &str) -> Error { Error::Syntax }
// Primitive types:
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::EndOfStream),
}
}
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::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::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::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::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::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::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::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::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::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::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::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::Syntax)
}
#[inline]
fn read_seq<T, F>(&mut self, f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder, usize) -> Result<T, Error>,
{
let len = self.len;
f(self, len)
}
#[inline]
fn read_seq_elt<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
f(self)
}
fn read_map<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder, usize) -> Result<T, Error>,
{
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::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::Syntax)
}
}
pub struct U8Decoder {
len: usize,
iter: vec::IntoIter<u8>,
}
impl U8Decoder {
#[inline]
pub fn new(values: Vec<u8>) -> U8Decoder {
U8Decoder {
len: values.len(),
iter: values.into_iter(),
}
}
}
impl rustc_serialize::Decoder for U8Decoder {
type Error = Error;
fn error(&mut self, _: &str) -> Error { Error::Syntax }
// Primitive types:
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::EndOfStream),
}
}
#[inline]
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::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::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::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::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::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::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::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::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::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::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::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::Syntax)
}
#[inline]
fn read_seq<T, F>(&mut self, f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder, usize) -> Result<T, Error>,
{
let len = self.len;
f(self, len)
}
#[inline]
fn read_seq_elt<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
f(self)
}
fn read_map<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder, usize) -> Result<T, Error>,
{
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::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::Syntax)
}
}
}
//////////////////////////////////////////////////////////////////////////////
mod deserializer {
//use std::num;
use std::vec;
use super::Error;
use serde::de;
#[derive(PartialEq, Debug)]
enum State {
Start,
SepOrEnd,
End,
}
pub struct Deserializer<A> {
state: State,
iter: vec::IntoIter<A>,
len: usize,
value: Option<A>,
}
impl<A> Deserializer<A> {
#[inline]
pub fn new(values: Vec<A>) -> Deserializer<A> {
let len = values.len();
Deserializer {
state: State::Start,
iter: values.into_iter(),
len: len,
value: None,
}
}
}
impl de::Deserializer for Deserializer<usize> {
type Error = Error;
#[inline]
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.state {
State::Start => {
self.state = State::SepOrEnd;
visitor.visit_seq(self)
}
State::SepOrEnd => {
visitor.visit_usize(self.value.take().unwrap())
}
State::End => {
Err(Error::EndOfStream)
}
}
}
}
impl de::SeqVisitor for Deserializer<usize> {
type Error = Error;
#[inline]
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: de::Deserialize,
{
match self.iter.next() {
Some(value) => {
self.len -= 1;
self.value = Some(value);
Ok(Some(try!(de::Deserialize::deserialize(self))))
}
None => {
self.state = State::End;
Ok(None)
}
}
}
#[inline]
fn end(&mut self) -> Result<(), Error> {
match self.iter.next() {
Some(_) => Err(Error::Syntax),
None => {
self.state = State::End;
Ok(())
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl de::Deserializer for Deserializer<u8> {
type Error = Error;
#[inline]
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.state {
State::Start => {
self.state = State::SepOrEnd;
visitor.visit_seq(self)
}
State::SepOrEnd => {
visitor.visit_u8(self.value.take().unwrap())
}
State::End => {
Err(Error::EndOfStream)
}
}
}
}
impl de::SeqVisitor for Deserializer<u8> {
type Error = Error;
#[inline]
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: de::Deserialize,
{
match self.iter.next() {
Some(value) => {
self.len -= 1;
self.value = Some(value);
Ok(Some(try!(de::Deserialize::deserialize(self))))
}
None => {
self.state = State::End;
Ok(None)
}
}
}
#[inline]
fn end(&mut self) -> Result<(), Error> {
match self.iter.next() {
Some(_) => Err(Error::Syntax),
None => {
self.state = State::End;
Ok(())
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
}
//////////////////////////////////////////////////////////////////////////////
fn run_decoder<
D: Decoder<Error=Error>,
T: Clone + PartialEq + Debug + Decodable
>(mut d: D, value: T) {
let v = Decodable::decode(&mut d);
assert_eq!(Ok(value), v);
}
fn run_deserializer<D, T>(mut d: D, value: T)
where D: Deserializer,
D::Error: Debug + PartialEq,
T: Clone + PartialEq + Debug + Deserialize
{
let v = T::deserialize(&mut d);
assert_eq!(Ok(value), v);
}
#[bench]
fn bench_decoder_usize_000(b: &mut Bencher) {
b.iter(|| {
let v: Vec<usize> = vec!();
run_decoder(decoder::UsizeDecoder::new(v.clone()), v)
})
}
#[bench]
fn bench_decoder_usize_003(b: &mut Bencher) {
b.iter(|| {
let v: Vec<usize> = vec!(1, 2, 3);
run_decoder(decoder::UsizeDecoder::new(v.clone()), v)
})
}
#[bench]
fn bench_decoder_usize_100(b: &mut Bencher) {
b.iter(|| {
let v: Vec<usize> = (0 .. 100).collect();
run_decoder(decoder::UsizeDecoder::new(v.clone()), v)
})
}
#[bench]
fn bench_decoder_u8_000(b: &mut Bencher) {
b.iter(|| {
let v: Vec<u8> = vec!();
run_decoder(decoder::U8Decoder::new(v.clone()), v)
})
}
#[bench]
fn bench_decoder_u8_003(b: &mut Bencher) {
b.iter(|| {
let v: Vec<u8> = vec!(1, 2, 3);
run_decoder(decoder::U8Decoder::new(v.clone()), v)
})
}
#[bench]
fn bench_decoder_u8_100(b: &mut Bencher) {
b.iter(|| {
let v: Vec<u8> = (0 .. 100).collect();
run_decoder(decoder::U8Decoder::new(v.clone()), v)
})
}
#[bench]
fn bench_deserializer_usize_000(b: &mut Bencher) {
b.iter(|| {
let v: Vec<usize> = vec!();
run_deserializer(deserializer::Deserializer::new(v.clone()), v)
})
}
#[bench]
fn bench_deserializer_usize_003(b: &mut Bencher) {
b.iter(|| {
let v: Vec<usize> = vec!(1, 2, 3);
run_deserializer(deserializer::Deserializer::new(v.clone()), v)
})
}
#[bench]
fn bench_deserializer_usize_100(b: &mut Bencher) {
b.iter(|| {
let v: Vec<usize> = (0 .. 100).collect();
run_deserializer(deserializer::Deserializer::new(v.clone()), v)
})
}
#[bench]
fn bench_deserializer_u8_000(b: &mut Bencher) {
b.iter(|| {
let v: Vec<u8> = vec!();
run_deserializer(deserializer::Deserializer::new(v.clone()), v)
})
}
#[bench]
fn bench_deserializer_u8_003(b: &mut Bencher) {
b.iter(|| {
let v: Vec<u8> = vec!(1, 2, 3);
run_deserializer(deserializer::Deserializer::new(v.clone()), v)
})
}
#[bench]
fn bench_deserializer_u8_100(b: &mut Bencher) {
b.iter(|| {
let v: Vec<u8> = (0 .. 100).collect();
run_deserializer(deserializer::Deserializer::new(v.clone()), v)
})
}
+3 -9
View File
@@ -5,13 +5,7 @@ use std::path::Path;
fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
for &(src, dst) in &[
("tests/test.rs.in", "test.rs"),
("benches/bench.rs.in", "bench.rs"),
] {
let src = Path::new(src);
let dst = Path::new(&out_dir).join(dst);
serde_codegen::expand(&src, &dst).unwrap();
}
let src = Path::new("tests/test.rs.in");
let dst = Path::new(&out_dir).join("test.rs");
serde_codegen::expand(&src, &dst).unwrap();
}
+2
View File
@@ -1,3 +1,5 @@
extern crate serde;
#[macro_use]
mod macros;
+146 -23
View File
@@ -1,20 +1,21 @@
use std::fmt;
use std::error;
extern crate serde;
use self::serde::Serialize;
use self::serde::bytes::{ByteBuf, Bytes};
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde::bytes::{ByteBuf, Bytes};
use serde::ser;
use serde::de;
///////////////////////////////////////////////////////////////////////////////
#[derive(Debug, PartialEq)]
struct Error;
impl serde::ser::Error for Error {
impl ser::Error for Error {
fn custom<T: Into<String>>(_: T) -> Error { Error }
}
impl serde::de::Error for Error {
impl de::Error for Error {
fn custom<T: Into<String>>(_: T) -> Error { Error }
fn end_of_stream() -> Error { Error }
@@ -50,7 +51,7 @@ impl BytesSerializer {
}
}
impl serde::Serializer for BytesSerializer {
impl Serializer for BytesSerializer {
type Error = Error;
type SeqState = ();
type MapState = ();
@@ -137,19 +138,19 @@ impl serde::Serializer for BytesSerializer {
}
fn serialize_some<V>(&mut self, _value: V) -> Result<(), Error>
where V: serde::Serialize,
where V: Serialize,
{
Err(Error)
}
fn serialize_newtype_struct<V>(&mut self, _: &'static str, _value: V) -> Result<(), Error>
where V: serde::Serialize,
where V: Serialize,
{
Err(Error)
}
fn serialize_newtype_variant<V>(&mut self, _: &'static str, _: usize, _: &'static str, _value: V) -> Result<(), Error>
where V: serde::Serialize,
where V: Serialize,
{
Err(Error)
}
@@ -165,7 +166,7 @@ impl serde::Serializer for BytesSerializer {
}
fn serialize_seq_elt<T>(&mut self, _: &mut (), _value: T) -> Result<(), Error>
where T: serde::Serialize
where T: Serialize
{
Err(Error)
}
@@ -181,7 +182,7 @@ impl serde::Serializer for BytesSerializer {
}
fn serialize_tuple_elt<T>(&mut self, _: &mut (), _value: T) -> Result<(), Error>
where T: serde::Serialize
where T: Serialize
{
Err(Error)
}
@@ -197,7 +198,7 @@ impl serde::Serializer for BytesSerializer {
}
fn serialize_tuple_struct_elt<T>(&mut self, _: &mut (), _value: T) -> Result<(), Error>
where T: serde::Serialize
where T: Serialize
{
Err(Error)
}
@@ -213,7 +214,7 @@ impl serde::Serializer for BytesSerializer {
}
fn serialize_tuple_variant_elt<T>(&mut self, _: &mut (), _value: T) -> Result<(), Error>
where T: serde::Serialize
where T: Serialize
{
Err(Error)
}
@@ -228,9 +229,14 @@ impl serde::Serializer for BytesSerializer {
Err(Error)
}
fn serialize_map_elt<K, V>(&mut self, _: &mut (), _key: K, _value: V) -> Result<(), Error>
where K: serde::Serialize,
V: serde::Serialize,
fn serialize_map_key<T>(&mut self, _: &mut (), _key: T) -> Result<(), Error>
where T: Serialize
{
Err(Error)
}
fn serialize_map_value<T>(&mut self, _: &mut (), _value: T) -> Result<(), Error>
where T: Serialize
{
Err(Error)
}
@@ -246,7 +252,7 @@ impl serde::Serializer for BytesSerializer {
}
fn serialize_struct_elt<V>(&mut self, _: &mut (), _key: &'static str, _value: V) -> Result<(), Error>
where V: serde::Serialize,
where V: Serialize,
{
Err(Error)
}
@@ -262,7 +268,7 @@ impl serde::Serializer for BytesSerializer {
}
fn serialize_struct_variant_elt<V>(&mut self, _: &mut (), _key: &'static str, _value: V) -> Result<(), Error>
where V: serde::Serialize,
where V: Serialize,
{
Err(Error)
}
@@ -292,20 +298,137 @@ impl BytesDeserializer {
}
}
impl serde::Deserializer for BytesDeserializer {
impl Deserializer for BytesDeserializer {
type Error = Error;
fn deserialize<V>(&mut self, _visitor: V) -> Result<V::Value, Error>
where V: serde::de::Visitor,
where V: de::Visitor,
{
Err(Error)
}
fn deserialize_bytes<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: serde::de::Visitor,
where V: de::Visitor,
{
visitor.visit_byte_buf(self.bytes.take().unwrap())
}
fn deserialize_seq<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_struct_field<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_map<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_unit<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_ignored_any<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_string<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_str<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_char<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i64<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i32<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i16<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i8<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u64<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u32<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u16<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u8<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_f32<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_f64<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_bool<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_usize<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_isize<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_option<__V>(&mut self, visitor: __V)
-> Result<__V::Value, Self::Error> where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_seq_fixed_size<__V>(&mut self, _: usize, visitor: __V)
-> Result<__V::Value, Self::Error> where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_unit_struct<__V>(&mut self, _: &str, visitor: __V)
-> Result<__V::Value, Self::Error> where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_newtype_struct<__V>(&mut self, _: &str, visitor: __V)
-> Result<__V::Value, Self::Error> where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_tuple_struct<__V>(&mut self, _: &str, _: usize, visitor: __V)
-> Result<__V::Value, Self::Error> where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_struct<__V>(&mut self, _: &str, _: &[&str], visitor: __V)
-> Result<__V::Value, Self::Error> where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_tuple<__V>(&mut self, _: usize, visitor: __V)
-> Result<__V::Value, Self::Error> where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _visitor: __V)
-> Result<__V::Value, Self::Error> where __V: de::EnumVisitor {
Err(Error)
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -328,10 +451,10 @@ fn test_bytes_ser_bytes() {
#[test]
fn test_byte_buf_de_bytes() {
let mut de = BytesDeserializer::new(vec![]);
let bytes = serde::Deserialize::deserialize(&mut de);
let bytes = Deserialize::deserialize(&mut de);
assert_eq!(bytes, Ok(ByteBuf::new()));
let mut de = BytesDeserializer::new(vec![1, 2, 3]);
let bytes = serde::Deserialize::deserialize(&mut de);
let bytes = Deserialize::deserialize(&mut de);
assert_eq!(bytes, Ok(ByteBuf::from(vec![1, 2, 3])));
}
+37 -3
View File
@@ -1,9 +1,9 @@
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::net;
use std::path::PathBuf;
use std::time::Duration;
extern crate serde;
use self::serde::Deserialize;
use serde::Deserialize;
extern crate fnv;
use self::fnv::FnvHasher;
@@ -37,7 +37,10 @@ enum Enum {
Unit,
Simple(i32),
Seq(i32, i32, i32),
Map { a: i32, b: i32, c: i32 }
Map { a: i32, b: i32, c: i32 },
#[allow(dead_code)]
#[serde(skip_deserializing)]
Skipped,
}
//////////////////////////////////////////////////////////////////////////
@@ -215,6 +218,9 @@ declare_tests! {
Token::SeqEnd,
],
}
test_unit_string {
String::new() => &[Token::Unit],
}
test_tuple_struct {
TupleStruct(1, 2, 3) => &[
Token::SeqStart(Some(3)),
@@ -746,6 +752,28 @@ declare_tests! {
Token::SeqEnd,
],
}
test_duration {
Duration::new(1, 2) => &[
Token::StructStart("Duration", 2),
Token::StructSep,
Token::Str("secs"),
Token::U64(1),
Token::StructSep,
Token::Str("nanos"),
Token::U32(2),
Token::StructEnd,
],
Duration::new(1, 2) => &[
Token::SeqStart(Some(2)),
Token::SeqSep,
Token::I64(1),
Token::SeqSep,
Token::I64(2),
Token::SeqEnd,
],
}
test_net_ipv4addr {
"1.2.3.4".parse::<net::Ipv4Addr>().unwrap() => &[Token::Str("1.2.3.4")],
}
@@ -780,6 +808,12 @@ declare_error_tests! {
],
Error::UnknownVariant("Foo".to_owned()),
}
test_enum_skipped_variant<Enum> {
&[
Token::EnumUnit("Enum", "Skipped"),
],
Error::UnknownVariant("Skipped".to_owned()),
}
test_struct_seq_too_long<Struct> {
&[
Token::SeqStart(Some(4)),
+208 -101
View File
@@ -6,129 +6,236 @@ extern crate serde;
use self::serde::ser::{Serialize, Serializer};
use self::serde::de::{Deserialize, Deserializer};
use std::borrow::Cow;
use std::marker::PhantomData;
// Try to trip up the generated code if it fails to use fully qualified paths.
#[allow(dead_code)]
struct Result;
use std::result::Result as StdResult;
//////////////////////////////////////////////////////////////////////////
#[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 {
#[test]
fn test_gen() {
#[derive(Serialize, Deserialize)]
struct With<T> {
t: T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
x: X },
}
x: X,
}
assert::<With<i32>>();
#[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 WithRef<'a, T: 'a> {
#[serde(skip_deserializing)]
t: Option<&'a T>,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
x: X,
}
assert::<WithRef<i32>>();
#[derive(Serialize, Deserialize)]
struct Newtype(
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X
);
#[derive(Serialize, Deserialize)]
struct PhantomX {
x: PhantomData<X>,
}
assert::<PhantomX>();
#[derive(Serialize, Deserialize)]
struct Tuple<T>(
T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X,
);
#[derive(Serialize, Deserialize)]
struct PhantomT<T> {
t: PhantomData<T>,
}
assert::<PhantomT<X>>();
#[derive(Serialize, Deserialize)]
enum TreeNode<D> {
Split {
left: Box<TreeNode<D>>,
right: Box<TreeNode<D>>,
},
Leaf {
#[derive(Serialize, Deserialize)]
struct Bounds<T: Serialize + Deserialize> {
t: T,
option: Option<T>,
boxed: Box<T>,
option_boxed: Option<Box<T>>,
}
assert::<Bounds<i32>>();
#[derive(Serialize, Deserialize)]
struct NoBounds<T> {
t: T,
option: Option<T>,
boxed: Box<T>,
option_boxed: Option<Box<T>>,
}
assert::<NoBounds<i32>>();
#[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 },
}
assert::<EnumWith<i32>>();
#[derive(Serialize)]
struct MultipleRef<'a, 'b, 'c, T> where T: 'c, 'c: 'b, 'b: 'a {
t: T,
rrrt: &'a &'b &'c T,
}
assert_ser::<MultipleRef<i32>>();
#[derive(Serialize, Deserialize)]
struct Newtype(
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X
);
assert::<Newtype>();
#[derive(Serialize, Deserialize)]
struct Tuple<T>(
T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X,
);
assert::<Tuple<i32>>();
#[derive(Serialize, Deserialize)]
enum TreeNode<D> {
Split {
left: Box<TreeNode<D>>,
right: Box<TreeNode<D>>,
},
Leaf {
data: D,
},
}
assert::<TreeNode<i32>>();
#[derive(Serialize, Deserialize)]
struct ListNode<D> {
data: D,
},
}
next: Box<ListNode<D>>,
}
assert::<ListNode<i32>>();
#[derive(Serialize, Deserialize)]
struct ListNode<D> {
data: D,
next: Box<ListNode<D>>,
}
#[derive(Serialize, Deserialize)]
struct RecursiveA {
b: Box<RecursiveB>,
}
assert::<RecursiveA>();
#[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)]
enum RecursiveB {
A(RecursiveA),
}
assert::<RecursiveB>();
#[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,
#[derive(Serialize, Deserialize)]
struct RecursiveGenericA<T> {
t: T,
b: Box<RecursiveGenericB<T>>,
}
assert::<RecursiveGenericA<i32>>();
#[derive(Serialize, Deserialize)]
enum RecursiveGenericB<T> {
T(T),
A(RecursiveGenericA<T>),
}
assert::<RecursiveGenericB<i32>>();
#[derive(Serialize)]
struct OptionStatic<'a> {
a: Option<&'a str>,
b: Option<&'static str>,
}
assert_ser::<OptionStatic>();
#[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,
}
assert::<WithTraits1<X, X>>();
#[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,
}
assert::<WithTraits2<X, X>>();
#[derive(Serialize, Deserialize)]
struct CowStr<'a>(Cow<'a, str>);
assert::<CowStr>();
#[derive(Serialize, Deserialize)]
#[serde(bound(deserialize = "T::Owned: Deserialize"))]
struct CowT<'a, T: ?Sized + 'a + ToOwned>(Cow<'a, T>);
assert::<CowT<str>>();
#[derive(Serialize, Deserialize)]
struct EmptyStruct {}
assert::<EmptyStruct>();
#[derive(Serialize, Deserialize)]
enum EmptyEnumVariant {
EmptyStruct {},
}
assert::<EmptyEnumVariant>();
}
//////////////////////////////////////////////////////////////////////////
fn assert<T: Serialize + Deserialize>() {}
fn assert_ser<T: Serialize>() {}
trait SerializeWith {
fn serialize_with<S: Serializer>(_: &Self, _: &mut S) -> Result<(), S::Error>;
fn serialize_with<S: Serializer>(_: &Self, _: &mut S) -> StdResult<(), S::Error>;
}
trait DeserializeWith: Sized {
fn deserialize_with<D: Deserializer>(_: &mut D) -> Result<Self, D::Error>;
fn deserialize_with<D: Deserializer>(_: &mut D) -> StdResult<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!() }
fn ser_x<S: Serializer>(_: &X, _: &mut S) -> StdResult<(), S::Error> {
unimplemented!()
}
fn de_x<D: Deserializer>(_: &mut D) -> StdResult<X, D::Error> {
unimplemented!()
}
impl SerializeWith for X {
fn serialize_with<S: Serializer>(_: &Self, _: &mut S) -> StdResult<(), S::Error> {
unimplemented!()
}
}
impl DeserializeWith for X {
fn deserialize_with<D: Deserializer>(_: &mut D) -> StdResult<Self, D::Error> {
unimplemented!()
}
}
+45 -52
View File
@@ -39,23 +39,19 @@ struct DeNamedMap<A, B, C> {
}
#[derive(Debug, PartialEq, Serialize)]
enum SerEnum<'a, B: 'a, C: /* Trait + */ 'a, D> where D: /* Trait + */ 'a {
enum SerEnum<'a, B: 'a, C: 'a, D> where D: 'a {
Unit,
Seq(
i8,
B,
&'a C,
//C::Type,
&'a mut D,
//<D as Trait>::Type,
),
Map {
a: i8,
b: B,
c: &'a C,
//d: C::Type,
e: &'a mut D,
//f: <D as Trait>::Type,
d: &'a mut D,
},
// Make sure we can support more than one variant.
@@ -64,38 +60,30 @@ enum SerEnum<'a, B: 'a, C: /* Trait + */ 'a, D> where D: /* Trait + */ 'a {
i8,
B,
&'a C,
//C::Type,
&'a mut D,
//<D as Trait>::Type,
),
_Map2 {
a: i8,
b: B,
c: &'a C,
//d: C::Type,
e: &'a mut D,
//f: <D as Trait>::Type,
d: &'a mut D,
},
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum DeEnum<B, C: /* Trait */, D> /* where D: Trait */ {
enum DeEnum<B, C, D> {
Unit,
Seq(
i8,
B,
C,
//C::Type,
D,
//<D as Trait>::Type,
),
Map {
a: i8,
b: B,
c: C,
//d: C::Type,
e: D,
//f: <D as Trait>::Type,
d: D,
},
// Make sure we can support more than one variant.
@@ -104,17 +92,13 @@ enum DeEnum<B, C: /* Trait */, D> /* where D: Trait */ {
i8,
B,
C,
//C::Type,
D,
//<D as Trait>::Type,
),
_Map2 {
a: i8,
b: B,
c: C,
//d: C::Type,
e: D,
//f: <D as Trait>::Type,
d: D,
},
}
@@ -301,18 +285,14 @@ fn test_ser_enum_seq() {
let a = 1;
let b = 2;
let c = 3;
//let d = 4;
let mut e = 5;
//let f = 6;
let mut d = 4;
assert_ser_tokens(
&SerEnum::Seq(
a,
b,
&c,
//d,
&mut e,
//f,
&mut d,
),
&[
Token::EnumSeqStart("SerEnum", "Seq", 4),
@@ -327,7 +307,7 @@ fn test_ser_enum_seq() {
Token::I32(3),
Token::EnumSeqSep,
Token::I32(5),
Token::I32(4),
Token::EnumSeqEnd,
],
@@ -339,18 +319,14 @@ fn test_ser_enum_map() {
let a = 1;
let b = 2;
let c = 3;
//let d = 4;
let mut e = 5;
//let f = 6;
let mut d = 4;
assert_ser_tokens(
&SerEnum::Map {
a: a,
b: b,
c: &c,
//d: d,
e: &mut e,
//f: f,
d: &mut d,
},
&[
Token::EnumMapStart("SerEnum", "Map", 4),
@@ -368,8 +344,8 @@ fn test_ser_enum_map() {
Token::I32(3),
Token::EnumMapSep,
Token::Str("e"),
Token::I32(5),
Token::Str("d"),
Token::I32(4),
Token::EnumMapEnd,
],
@@ -391,18 +367,14 @@ fn test_de_enum_seq() {
let a = 1;
let b = 2;
let c = 3;
//let d = 4;
let e = 5;
//let f = 6;
let d = 4;
assert_tokens(
&DeEnum::Seq(
a,
b,
c,
//d,
e,
//f,
d,
),
&[
Token::EnumSeqStart("DeEnum", "Seq", 4),
@@ -417,7 +389,7 @@ fn test_de_enum_seq() {
Token::I32(3),
Token::EnumSeqSep,
Token::I32(5),
Token::I32(4),
Token::EnumSeqEnd,
],
@@ -429,18 +401,14 @@ fn test_de_enum_map() {
let a = 1;
let b = 2;
let c = 3;
//let d = 4;
let e = 5;
//let f = 6;
let d = 4;
assert_tokens(
&DeEnum::Map {
a: a,
b: b,
c: c,
//d: d,
e: e,
//f: f,
d: d,
},
&[
Token::EnumMapStart("DeEnum", "Map", 4),
@@ -458,8 +426,8 @@ fn test_de_enum_map() {
Token::I32(3),
Token::EnumMapSep,
Token::Str("e"),
Token::I32(5),
Token::Str("d"),
Token::I32(4),
Token::EnumMapEnd,
],
@@ -632,3 +600,28 @@ fn test_default_ty_param() {
]
);
}
#[test]
fn test_enum_state_field() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum SomeEnum {
Key { key: char, state: bool },
}
assert_tokens(
&SomeEnum::Key { key: 'a', state: true },
&[
Token::EnumMapStart("SomeEnum", "Key", 2),
Token::EnumMapSep,
Token::Str("key"),
Token::Char('a'),
Token::EnumMapSep,
Token::Str("state"),
Token::Bool(true),
Token::EnumMapEnd,
]
);
}
+43 -1
View File
@@ -2,6 +2,7 @@ use std::collections::{BTreeMap, HashMap, HashSet};
use std::net;
use std::path::{Path, PathBuf};
use std::str;
use std::time::Duration;
extern crate serde_test;
use self::serde_test::{
@@ -29,12 +30,20 @@ struct Struct {
c: i32,
}
#[derive(Serialize)]
#[derive(Serialize, PartialEq, Debug)]
enum Enum {
Unit,
One(i32),
Seq(i32, i32),
Map { a: i32, b: i32 },
#[serde(skip_serializing)]
SkippedUnit,
#[serde(skip_serializing)]
SkippedOne(i32),
#[serde(skip_serializing)]
SkippedSeq(i32, i32),
#[serde(skip_serializing)]
SkippedMap { _a: i32, _b: i32 },
}
//////////////////////////////////////////////////////////////////////////
@@ -324,6 +333,19 @@ declare_ser_tests! {
Token::SeqEnd,
],
}
test_duration {
Duration::new(1, 2) => &[
Token::StructStart("Duration", 2),
Token::StructSep,
Token::Str("secs"),
Token::U64(1),
Token::StructSep,
Token::Str("nanos"),
Token::U32(2),
Token::StructEnd,
],
}
test_net_ipv4addr {
"1.2.3.4".parse::<net::Ipv4Addr>().unwrap() => &[Token::Str("1.2.3.4")],
}
@@ -374,3 +396,23 @@ fn test_cannot_serialize_paths() {
&[],
Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned()));
}
#[test]
fn test_enum_skipped() {
assert_ser_tokens_error(
&Enum::SkippedUnit,
&[],
Error::InvalidValue("The enum variant Enum::SkippedUnit cannot be serialized".to_owned()));
assert_ser_tokens_error(
&Enum::SkippedOne(42),
&[],
Error::InvalidValue("The enum variant Enum::SkippedOne cannot be serialized".to_owned()));
assert_ser_tokens_error(
&Enum::SkippedSeq(1, 2),
&[],
Error::InvalidValue("The enum variant Enum::SkippedSeq cannot be serialized".to_owned()));
assert_ser_tokens_error(
&Enum::SkippedMap { _a: 1, _b: 2 },
&[],
Error::InvalidValue("The enum variant Enum::SkippedMap cannot be serialized".to_owned()));
}