Compare commits

...

269 Commits

Author SHA1 Message Date
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
David Tolnay fa51083a12 Merge pull request #446 from serde-rs/unstable
Rename feature nightly-testing to unstable-testing
2016-07-17 18:26:20 -07:00
David Tolnay aaca4f06c6 Release 0.8.0-rc2 2016-07-17 18:07:40 -07:00
David Tolnay cc8a5a79ab See whether relative paths help cargo find the unstable-testing feature 2016-07-17 13:40:39 -07:00
David Tolnay 4f79829849 Rename feature nightly-testing to unstable-testing 2016-07-17 13:34:23 -07:00
David Tolnay 6c18896cf5 Unpin the clippy dependency 2016-07-17 13:32:40 -07:00
David Tolnay ac738632ef Merge pull request #445 from serde-rs/pubdep
Remove public dependency on Syntex
2016-07-17 13:15:42 -07:00
David Tolnay 8d06f36d71 Remove public dependency on Syntex 2016-07-17 13:00:39 -07:00
David Tolnay e404de85b2 Remove serde-syntex-example from travis until serde_json 0.8.0 2016-07-17 12:59:04 -07:00
David Tolnay 6fe01bc8e3 Release 0.8.0-rc1
This prerelease contains the Serializer API changes intended for 0.8.0. It
allows us to start merging PRs that use the new API.
2016-07-17 11:46:03 -07:00
David Tolnay 855f3d99bb Do not release any more 0.7 releases from master 2016-07-15 17:00:09 -07:00
David Tolnay 9d015a2942 Merge pull request #437 from oli-obk/map_seq_ser
Revamp Map/Seq serialization
2016-07-15 16:59:45 -07:00
Oliver Schneider 42c41922ce adjust tests for new interface 2016-07-15 12:59:30 +02:00
Oliver Schneider 984181c558 Merge remote-tracking branch 'serde/master' into map_seq_ser 2016-07-15 10:59:46 +02:00
David Tolnay ed603d4580 Merge pull request #442 from serde-rs/override
Use cargo override instead of relative paths
2016-07-15 01:56:14 -07:00
Oliver Schneider 70c83768b7 Merge pull request #1 from serde-rs/dtolnay/serializer
David's take on Serializer
2016-07-15 10:38:22 +02:00
David Tolnay 7220029055 Use cargo override instead of relative paths
This makes it possible to use `cargo clone` + `cargo build`.
2016-07-15 01:17:23 -07:00
David Tolnay 35676305da Merge pull request #401 from erickt/contributing
Add a contribution guide
2016-07-15 01:06:54 -07:00
David Tolnay fbad194042 Restore 'static requirement for names 2016-07-15 00:59:56 -07:00
David Tolnay 2e4cc0b443 Restore serialize_seq_fixed_size 2016-07-15 00:58:48 -07:00
David Tolnay 9217517532 Update impls 2016-07-15 00:55:38 -07:00
David Tolnay 0feeb7a341 David's take on Serializer 2016-07-15 00:01:31 -07:00
Oliver Schneider 2901344722 this time really fix ranges 2016-07-14 16:16:20 +02:00
Oliver Schneider 54c80ad677 fix range serialization 2016-07-14 15:37:05 +02:00
Oliver Schneider 16ba32dbe1 stateful map/seq serialization 2016-07-14 15:36:47 +02:00
Oliver Schneider 60938913b2 face -> palm 2016-07-13 19:18:01 +02:00
Oliver Schneider 26528fbbb4 silence lint about a: ref a patterns 2016-07-12 16:53:38 +02:00
Oliver Schneider 6adcaa55e5 json needs more info 2016-07-12 16:53:20 +02:00
Oliver Schneider fb575225bc simplify! 2016-07-12 16:16:48 +02:00
Oliver Schneider ee4e7413b0 whoops 2016-07-12 15:50:41 +02:00
Oliver Schneider a6f8bd5aac nightly 2016-07-12 15:49:41 +02:00
Oliver Schneider 3766633f4a adjust codegen to work with the revamped map/seq serializer 2016-07-12 15:44:19 +02:00
Dawid Ciężarkiewicz 99038b044e Eliminate Visitor pattern
Visitor is "pull", while `MapSerializer` and `SeqSerializer`
are "push" like the rest of the API.
2016-07-12 11:46:44 +02:00
David Tolnay 4ec0a7e672 Merge pull request #433 from softprops/add_envy
add envy
2016-07-10 20:59:50 -07:00
softprops a41dae45a5 add envy 2016-07-10 23:55:32 -04:00
David Tolnay cb9e1cfb54 Merge pull request #431 from serde-rs/version
Drop support for 1.7.0
2016-07-10 14:40:15 -07:00
David Tolnay 54ce7f2e90 Drop support for 1.7.0 2016-07-10 14:25:17 -07:00
David Tolnay ddbd139793 Merge pull request #430 from serde-rs/bump
Update syntex to 0.38
2016-07-09 11:51:38 -07:00
David Tolnay a070de28e2 Update syntex to 0.38 2016-07-09 11:37:01 -07:00
David Tolnay 57aeb26728 Merge pull request #428 from erickt/readme
Rewrite readme to front-load stable rust usage
2016-07-07 20:26:00 -07:00
Erick Tryzelaar a592828808 Rewrite readme to front-load stable rust usage 2016-07-07 14:31:24 -07:00
David Tolnay 67d86dcc4f Merge pull request #426 from serde-rs/display
impl Display for de::Type
2016-07-07 00:59:17 -07:00
David Tolnay 15764cb955 impl Display for de::Type 2016-07-06 23:33:59 -07:00
David Tolnay 97bc1e08e7 Release 0.7.13 2016-07-05 20:06:10 -07:00
Oliver Schneider 7ffb74f5bb Merge pull request #423 from dtolnay/seq
Close the seq before failing on invalid length
2016-07-05 22:44:52 +02:00
David Tolnay f25e6d3ea9 Close the seq before failing on invalid length
Equivalent to what 0f9a930 does for maps.
2016-07-05 10:08:36 -07:00
David Tolnay 431cbe48b7 Merge pull request #422 from serde-rs/missing
Close the map before checking for missing fields
2016-07-05 07:11:03 -07:00
Homu 5405ab319d Auto merge of #421 - serde-rs:length, r=oli-obk
Invalid-length when enum seq is too short

Fixes https://github.com/serde-rs/json/issues/96.
2016-07-05 18:27:33 +09:00
David Tolnay 0f9a930c4f Close the map before checking for missing fields 2016-07-05 01:42:38 -07:00
David Tolnay 1a449bb3d0 Invalid-length when enum seq is too short 2016-07-05 01:35:20 -07:00
David Tolnay c0e8164792 Merge pull request #418 from serde-rs/expninfo
Record expansion info
2016-07-04 15:22:09 -07:00
David Tolnay a3a7e4085f Add run-pass test for expansion info 2016-07-04 15:02:15 -07:00
David Tolnay 149c87d7c2 Record expansion info 2016-07-03 10:53:33 -07:00
Erick Tryzelaar 18e077eda9 Add a contributing guide 2016-06-22 07:04:13 -07:00
74 changed files with 3793 additions and 6255 deletions
+6 -16
View File
@@ -1,37 +1,27 @@
sudo: false
language: rust
rust:
- 1.10.0
- 1.11.0
- stable
- beta
- nightly
- 1.7.0
- 1.8.0
addons:
apt:
packages:
- libcurl4-openssl-dev
- libelf-dev
- libdw-dev
before_script:
- pip install 'travis-cargo<0.2' --user
- export PATH=$HOME/.local/bin:$PATH
script:
- (cd serde && travis-cargo build)
- (cd serde && travis-cargo --skip nightly test)
- (cd serde && travis-cargo --only nightly test -- --features nightly-testing)
- (cd serde && travis-cargo --only nightly test -- --features unstable-testing)
- (cd serde && travis-cargo build -- --no-default-features)
- (cd serde && travis-cargo --only nightly build -- --no-default-features --features alloc)
- (cd serde && travis-cargo --only nightly build -- --no-default-features --features collections)
- (cd testing && travis-cargo --skip nightly test)
- (cd testing && travis-cargo --only nightly test -- --features nightly-testing)
- (cd serde_macros && travis-cargo --only nightly test -- --features nightly-testing)
- (cd testing && travis-cargo --only nightly test -- --features unstable-testing)
- (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 nightly)
- (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=
+45
View File
@@ -0,0 +1,45 @@
# Contributing to Serde
Serde welcomes contribution from everyone. Here are the guidelines if you are
thinking of helping us:
## Contributions
Contributions to Serde or its dependencies should be made in the form of GitHub
pull requests. Each pull request will be reviewed by a core contributor
(someone with permission to land patches) and either landed in the main tree or
given feedback for changes that would be required. All contributions should
follow this format, even those from core contributors.
Should you wish to work on an issue, please claim it first by commenting on
the GitHub issue that you want to work on it. This is to prevent duplicated
efforts from contributors on the same issue.
## Pull Request Checklist
- Branch from the master branch and, if needed, rebase to the current master
branch before submitting your pull request. If it doesn't merge cleanly with
master you may be asked to rebase your changes.
- Commits should be as small as possible, while ensuring that each commit is
correct independently (i.e., each commit should compile and pass tests).
- If your patch is not getting reviewed or you need a specific person to review
it, you can @-reply a reviewer asking for a review in the pull request or a
comment, or you can ask for a review in `#serde` on `irc.mozilla.org`.
- Add tests relevant to the fixed bug or new feature.
## Conduct
In all Serde-related forums, we follow the [Rust Code of
Conduct](https://www.rust-lang.org/conduct.html). For escalation or moderation
issues, please contact Erick (erick.tryzelaar@gmail.com) instead of the Rust
moderation team.
## Communication
Beyond opening tickets on the
[serde-rs/serde](https://github.com/serde-rs/serde) project, Serde contributors
frequent the `#serde` channel on
[`irc.mozilla.org`](https://wiki.mozilla.org/IRC).
+38 -713
View File
@@ -1,50 +1,24 @@
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 is available at:
You may be looking for:
* [serde](https://serde-rs.github.io/serde/serde/index.html)
- [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/)
Using Serde with Nightly Rust and serde\_macros
===============================================
Here is a simple example that demonstrates how to use Serde by serializing and
deserializing to JSON. Serde comes with some powerful code generation libraries
that work with Stable and Nightly Rust that eliminate much of the complexity of
hand rolling serialization and deserialization for a given type. First lets see
how we would use Nightly Rust, which is currently a bit simpler than Stable
Rust:
`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 = "*"
```
`src/main.rs`
## Serde in action
```rust
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
@@ -56,691 +30,42 @@ struct Point {
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);
// 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);
}
```
When run, it produces:
## Getting help
```
% cargo run
{"x":1,"y":2}
Point { x: 1, y: 2 }
```
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.
Using Serde with Stable Rust and serde\_codegen
===============================================
## License
Stable Rust is a little more complicated because it does not yet support
compiler plugins. Instead we need to use `serde_codegen` which is based on the
code generation library [syntex](https://github.com/serde-rs/syntex):
Serde is licensed under either of
```toml
[package]
name = "serde_example"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
build = "build.rs"
* 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)
[build-dependencies]
serde_codegen = "*"
at your option.
[dependencies]
serde = "*"
serde_json = "*"
```
### Contribution
`src/main.rs`:
```rust,ignore
extern crate serde;
extern crate serde_json;
include!(concat!(env!("OUT_DIR"), "/main.rs"));
```
`src/main.rs.in`:
```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);
}
```
`build.rs`
```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();
}
```
This also produces:
```
% cargo run
{"x":1,"y":2}
Point { x: 1, y: 2 }
```
While this works well with Stable Rust, be aware that the error locations
currently are reported in the generated file instead of in the source file. You
may find it easier to develop with Nightly Rust and `serde\_macros`, then
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 };
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}";
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
println!("{:?}", deserialized);
}
```
Design Considerations and tradeoffs for Serializers and Deserializers
=====================================================================
Serde serialization and deserialization implementations are written in such a
way that they err on being able to represent more values, and also provide
better error messages when they are passed an incorrect type to deserialize
from. For example, by default, it is a syntax error to deserialize a `String`
into an `Option<String>`. This is implemented such that it is possible to
distinguish between the values `None` and `Some(())`, if the serialization
format supports option types.
However, many formats do not have option types, and represents optional values
as either a `null`, or some other value. Serde `Serializer`s and
`Deserializer`s can opt-in support for this. For serialization, this is pretty
easy. Simply implement these methods:
```rust,ignore
...
fn visit_none(&mut self) -> Result<(), Self::Error> {
self.visit_unit()
}
fn visit_some<T>(&mut self, value: T) -> Result<(), Self::Error> {
value.serialize(self)
}
...
```
For deserialization, this can be implemented by way of the
`Deserializer::visit_option` hook, which presumes that there is some ability to peek at what is the
next value in the serialized token stream. This following example is from
[serde_tests::TokenDeserializer](https://github.com/serde-rs/serde/blob/master/serde_tests/tests/token.rs#L435-L454),
where it checks to see if the next value is an `Option`, a `()`, or some other
value:
```rust,ignore
...
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.tokens.peek() {
Some(&Token::Option(false)) => {
self.tokens.next();
visitor.visit_none()
}
Some(&Token::Option(true)) => {
self.tokens.next();
visitor.visit_some(self)
}
Some(&Token::Unit) => {
self.tokens.next();
visitor.visit_none()
}
Some(_) => visitor.visit_some(self),
None => Err(Error::EndOfStreamError),
}
}
...
```
Annotations
===========
`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) |
| 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
View File
@@ -1,5 +0,0 @@
paths = [
"../serde",
"../serde_codegen",
"../serde_macros",
]
+5 -5
View File
@@ -6,12 +6,12 @@ build = "build.rs"
[features]
default = ["serde_codegen"]
nightly = ["serde_macros"]
unstable = ["serde_derive"]
[build-dependencies]
serde_codegen = { version = "^0.7.12", optional = true }
serde_codegen = { version = "^0.8", optional = true, path = "../../serde_codegen" }
[dependencies]
serde = "^0.7.12"
serde_json = "^0.7.0"
serde_macros = { version = "^0.7.12", 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"));
+6 -5
View File
@@ -1,11 +1,12 @@
[package]
name = "serde"
version = "0.7.12"
version = "0.8.17"
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"]
@@ -14,10 +15,10 @@ include = ["Cargo.toml", "src/**/*.rs"]
default = ["std"]
std = []
nightly = []
alloc = ["nightly"]
unstable = []
alloc = ["unstable"]
collections = ["alloc"]
nightly-testing = ["clippy", "nightly", "std"]
unstable-testing = ["clippy", "unstable", "std"]
[dependencies]
clippy = { version = "^0.*", optional = true }
+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))
}
}
+225 -112
View File
@@ -2,7 +2,7 @@
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(all(feature = "nightly", feature = "collections", not(feature = "std")))]
#[cfg(all(feature = "unstable", feature = "collections", not(feature = "std")))]
use collections::borrow::Cow;
#[cfg(all(feature = "collections", not(feature = "std")))]
@@ -27,9 +27,9 @@ use std::collections::{
VecDeque,
};
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(all(feature = "unstable", feature = "collections"))]
use collections::enum_set::{CLike, EnumSet};
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(all(feature = "unstable", feature = "collections"))]
use collections::borrow::ToOwned;
use core::hash::{Hash, BuildHasher};
@@ -42,21 +42,24 @@ use core::str;
#[cfg(feature = "std")]
use std::rc::Rc;
#[cfg(all(feature = "nightly", feature = "alloc", not(feature = "std")))]
#[cfg(all(feature = "unstable", feature = "alloc", not(feature = "std")))]
use alloc::rc::Rc;
#[cfg(feature = "std")]
use std::sync::Arc;
#[cfg(all(feature = "nightly", feature = "alloc", not(feature = "std")))]
#[cfg(all(feature = "unstable", feature = "alloc", not(feature = "std")))]
use alloc::arc::Arc;
#[cfg(all(feature = "nightly", feature = "alloc", not(feature = "std")))]
#[cfg(all(feature = "unstable", feature = "alloc", not(feature = "std")))]
use alloc::boxed::Box;
#[cfg(feature = "nightly")]
#[cfg(feature = "std")]
use std::time::Duration;
#[cfg(feature = "unstable")]
use core::nonzero::{NonZero, Zeroable};
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
use core::num::Zero;
use de::{
@@ -356,7 +359,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 +370,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,
{
@@ -461,7 +464,7 @@ seq_impl!(
BTreeSet::new(),
BTreeSet::insert);
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(all(feature = "unstable", feature = "collections"))]
seq_impl!(
EnumSet<T>,
EnumSetVisitor<T: Deserialize + CLike>,
@@ -509,27 +512,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 +539,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 +566,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 +582,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 +590,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 +652,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 +662,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 +675,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 +762,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 +780,7 @@ map_impl!(
///////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "nightly", 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 +913,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,7 +956,136 @@ impl<'a, T: ?Sized> Deserialize for Cow<'a, T> where T: ToOwned, T::Owned: Deser
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "nightly")]
// 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 {
let value = try!(Deserialize::deserialize(deserializer));
+130 -194
View File
@@ -8,6 +8,10 @@ use error;
#[cfg(all(not(feature = "std"), feature = "collections"))]
use collections::{String, Vec};
use core::fmt;
///////////////////////////////////////////////////////////////////////////////
pub mod impls;
pub mod value;
mod from_primitive;
@@ -169,6 +173,46 @@ pub enum Type {
Bytes,
}
impl fmt::Display for Type {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let display = match *self {
Type::Bool => "bool",
Type::Usize => "usize",
Type::U8 => "u8",
Type::U16 => "u16",
Type::U32 => "u32",
Type::U64 => "u64",
Type::Isize => "isize",
Type::I8 => "i8",
Type::I16 => "i16",
Type::I32 => "i32",
Type::I64 => "i64",
Type::F32 => "f32",
Type::F64 => "f64",
Type::Char => "char",
Type::Str => "str",
Type::String => "string",
Type::Unit => "unit",
Type::Option => "option",
Type::Seq => "seq",
Type::Map => "map",
Type::UnitStruct => "unit struct",
Type::NewtypeStruct => "newtype struct",
Type::TupleStruct => "tuple struct",
Type::Struct => "struct",
Type::FieldName => "field name",
Type::Tuple => "tuple",
Type::Enum => "enum",
Type::VariantName => "variant name",
Type::StructVariant => "struct variant",
Type::TupleVariant => "tuple variant",
Type::UnitVariant => "unit variant",
Type::Bytes => "bytes",
};
display.fmt(formatter)
}
}
///////////////////////////////////////////////////////////////////////////////
/// `Deserialize` represents a type that can be deserialized.
@@ -201,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;
}
///////////////////////////////////////////////////////////////////////////////
@@ -483,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))
}
@@ -518,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))
}
@@ -553,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))
}
@@ -567,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))
}
@@ -582,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))
}
@@ -608,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()
}
@@ -622,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))
}
@@ -828,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 {
+366 -14
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,8 +26,10 @@ use collections::{
btree_set,
vec,
};
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::borrow::Cow;
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(all(feature = "unstable", feature = "collections"))]
use collections::borrow::ToOwned;
use core::hash::Hash;
@@ -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
}
}
+2 -2
View File
@@ -4,7 +4,7 @@ use core::fmt::{Debug, Display};
/// A stand-in for `std::error::Error`, which requires no allocation.
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
pub trait Error: Debug + Display + ::core::marker::Reflect {
/// A short description of the error.
///
@@ -24,7 +24,7 @@ pub trait Error: Debug + Display + ::core::marker::Reflect {
}
/// A stand-in for `std::error::Error`, which requires no allocation.
#[cfg(not(feature = "nightly"))]
#[cfg(not(feature = "unstable"))]
pub trait Error: Debug + Display {
/// A short description of the error.
///
+13 -10
View File
@@ -5,35 +5,35 @@
//! 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 = "nightly", feature(reflect_marker, unicode, nonzero, plugin, step_trait, zero_one))]
#![cfg_attr(feature = "unstable", feature(reflect_marker, unicode, nonzero, plugin, step_trait, zero_one))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "collections", feature(collections, enumset))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", allow(linkedlist))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", allow(linkedlist))]
#![cfg_attr(any(not(feature = "std"), feature = "nightly"), allow(unused_variables, unused_imports, unused_features, dead_code))]
#![cfg_attr(any(not(feature = "std"), feature = "unstable"), allow(unused_variables, unused_imports, unused_features, dead_code))]
#![deny(missing_docs)]
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(all(feature = "unstable", feature = "collections"))]
extern crate collections;
#[cfg(all(feature = "nightly", feature = "alloc"))]
#[cfg(all(feature = "unstable", feature = "alloc"))]
extern crate alloc;
#[cfg(feature = "std")]
mod core {
pub use std::{ops, hash, fmt, cmp, marker, mem, i8, i16, i32, i64, u8, u16, u32, u64, isize,
usize, f32, f64, char, str, num, slice, iter};
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
extern crate core;
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
pub use self::core::nonzero;
}
@@ -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})*
};
}
+98 -274
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;
@@ -26,19 +30,19 @@ use collections::{
Vec,
};
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(all(feature = "unstable", feature = "collections"))]
use collections::enum_set::{CLike, EnumSet};
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(all(feature = "unstable", feature = "collections"))]
use collections::borrow::ToOwned;
use core::hash::{Hash, BuildHasher};
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
use core::iter;
#[cfg(feature = "std")]
use std::net;
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
use core::num;
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
use core::ops;
#[cfg(feature = "std")]
use std::path;
@@ -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;
@@ -57,15 +63,13 @@ use alloc::boxed::Box;
use core::marker::PhantomData;
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
use core::nonzero::{NonZero, Zeroable};
use super::{
Error,
Serialize,
Serializer,
SeqVisitor,
MapVisitor,
};
///////////////////////////////////////////////////////////////////////////////
@@ -133,26 +137,6 @@ impl<T> Serialize for Option<T> where T: Serialize {
}
}
impl<T> SeqVisitor for Option<T> where T: Serialize {
#[inline]
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer,
{
match self.take() {
Some(value) => {
try!(serializer.serialize_seq_elt(value));
Ok(Some(()))
}
None => Ok(None),
}
}
#[inline]
fn len(&self) -> Option<usize> {
Some(if self.is_some() { 1 } else { 0 })
}
}
///////////////////////////////////////////////////////////////////////////////
impl<T> Serialize for PhantomData<T> {
@@ -164,69 +148,6 @@ impl<T> Serialize for PhantomData<T> {
}
}
///////////////////////////////////////////////////////////////////////////////
/// A `serde::Visitor` for sequence iterators.
///
/// # Examples
///
/// ```
/// use serde::{Serialize, Serializer};
/// use serde::ser::impls::SeqIteratorVisitor;
///
/// struct Seq(Vec<u32>);
///
/// impl Serialize for Seq {
/// fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
/// where S: Serializer,
/// {
/// ser.serialize_seq(SeqIteratorVisitor::new(
/// self.0.iter(),
/// Some(self.0.len()),
/// ))
/// }
/// }
/// ```
pub struct SeqIteratorVisitor<Iter> {
iter: Iter,
len: Option<usize>,
}
impl<T, Iter> SeqIteratorVisitor<Iter>
where Iter: Iterator<Item=T>
{
/// Construct a new `SeqIteratorVisitor<Iter>`.
#[inline]
pub fn new(iter: Iter, len: Option<usize>) -> SeqIteratorVisitor<Iter> {
SeqIteratorVisitor {
iter: iter,
len: len,
}
}
}
impl<T, Iter> SeqVisitor for SeqIteratorVisitor<Iter>
where T: Serialize,
Iter: Iterator<Item=T>,
{
#[inline]
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer,
{
match self.iter.next() {
Some(value) => {
try!(serializer.serialize_seq_elt(value));
Ok(Some(()))
}
None => Ok(None),
}
}
#[inline]
fn len(&self) -> Option<usize> {
self.len
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -237,7 +158,11 @@ impl<T> Serialize for [T]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
let mut state = try!(serializer.serialize_seq(Some(self.len())));
for e in self {
try!(serializer.serialize_seq_elt(&mut state, e));
}
serializer.serialize_seq_end(state)
}
}
@@ -250,8 +175,11 @@ macro_rules! array_impls {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
let visitor = SeqIteratorVisitor::new(self.iter(), Some($len));
serializer.serialize_fixed_size_array(visitor)
let mut state = try!(serializer.serialize_seq_fixed_size($len));
for e in self {
try!(serializer.serialize_seq_elt(&mut state, e));
}
serializer.serialize_seq_end(state)
}
}
}
@@ -293,40 +221,40 @@ array_impls!(32);
///////////////////////////////////////////////////////////////////////////////
macro_rules! serialize_seq {
() => {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
let mut state = try!(serializer.serialize_seq(Some(self.len())));
for e in self {
try!(serializer.serialize_seq_elt(&mut state, e));
}
serializer.serialize_seq_end(state)
}
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for BinaryHeap<T>
where T: Serialize + Ord
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
serialize_seq!();
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for BTreeSet<T>
where T: Serialize + Ord,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
serialize_seq!();
}
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(all(feature = "unstable", feature = "collections"))]
impl<T> Serialize for EnumSet<T>
where T: Serialize + CLike
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
serialize_seq!();
}
#[cfg(feature = "std")]
@@ -334,27 +262,27 @@ impl<T, H> Serialize for HashSet<T, H>
where T: Serialize + Eq + Hash,
H: BuildHasher,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
serialize_seq!();
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for LinkedList<T>
where T: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
serialize_seq!();
}
#[cfg(feature = "nightly")]
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for Vec<T> where T: Serialize {
serialize_seq!();
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for VecDeque<T> where T: Serialize {
serialize_seq!();
}
#[cfg(feature = "unstable")]
impl<A> Serialize for ops::Range<A>
where A: Serialize + Clone + iter::Step + num::One,
for<'a> &'a A: ops::Add<&'a A, Output = A>,
@@ -364,27 +292,11 @@ impl<A> Serialize for ops::Range<A>
where S: Serializer,
{
let len = iter::Step::steps_between(&self.start, &self.end, &A::one());
serializer.serialize_seq(SeqIteratorVisitor::new(self.clone(), len))
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for Vec<T> where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
(&self[..]).serialize(serializer)
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for VecDeque<T> where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
let mut state = try!(serializer.serialize_seq(len));
for e in self.clone() {
try!(serializer.serialize_seq_elt(&mut state, e));
}
serializer.serialize_seq_end(state)
}
}
@@ -401,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),+) {
@@ -413,52 +320,18 @@ macro_rules! tuple_impls {
}
)+) => {
$(
/// A tuple visitor.
pub struct $TupleVisitor<'a, $($T: 'a),+> {
tuple: &'a ($($T,)+),
state: u8,
}
impl<'a, $($T: 'a),+> $TupleVisitor<'a, $($T),+> {
/// Construct a new, empty `TupleVisitor`.
pub fn new(tuple: &'a ($($T,)+)) -> $TupleVisitor<'a, $($T),+> {
$TupleVisitor {
tuple: tuple,
state: 0,
}
}
}
impl<'a, $($T),+> SeqVisitor for $TupleVisitor<'a, $($T),+>
where $($T: Serialize),+
{
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer,
{
match self.state {
$(
$state => {
self.state += 1;
Ok(Some(try!(serializer.serialize_tuple_elt(&e!(self.tuple.$idx)))))
}
)+
_ => {
Ok(None)
}
}
}
fn len(&self) -> Option<usize> {
Some($len)
}
}
impl<$($T),+> Serialize for ($($T,)+)
where $($T: Serialize),+
{
#[inline]
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
serializer.serialize_tuple($TupleVisitor::new(self))
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
let mut state = try!(serializer.serialize_tuple($len));
$(
try!(serializer.serialize_tuple_elt(&mut state, &self.$idx));
)+
serializer.serialize_tuple_end(state)
}
}
)+
@@ -638,83 +511,28 @@ tuple_impls! {
///////////////////////////////////////////////////////////////////////////////
/// A `serde::Visitor` for (key, value) map iterators.
///
/// # Examples
///
/// ```
/// use std::collections::HashMap;
/// use serde::{Serialize, Serializer};
/// use serde::ser::impls::MapIteratorVisitor;
///
/// struct Map(HashMap<u32, u32>);
///
/// impl Serialize for Map {
/// fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
/// where S: Serializer,
/// {
/// ser.serialize_map(MapIteratorVisitor::new(
/// self.0.iter(),
/// Some(self.0.len()),
/// ))
/// }
/// }
/// ```
pub struct MapIteratorVisitor<Iter> {
iter: Iter,
len: Option<usize>,
}
impl<K, V, Iter> MapIteratorVisitor<Iter>
where Iter: Iterator<Item=(K, V)>
{
/// Construct a new `MapIteratorVisitor<Iter>`.
#[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)) => {
try!(serializer.serialize_map_elt(key, value));
Ok(Some(()))
macro_rules! serialize_map {
() => {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
let mut state = try!(serializer.serialize_map(Some(self.len())));
for (k, v) in self {
try!(serializer.serialize_map_key(&mut state, k));
try!(serializer.serialize_map_value(&mut state, v));
}
None => Ok(None)
serializer.serialize_map_end(state)
}
}
#[inline]
fn len(&self) -> Option<usize> {
self.len
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))]
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())))
}
serialize_map!();
}
#[cfg(feature = "std")]
@@ -723,12 +541,7 @@ impl<K, V, H> Serialize for HashMap<K, V, H>
V: Serialize,
H: BuildHasher,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
serialize_map!();
}
///////////////////////////////////////////////////////////////////////////////
@@ -808,15 +621,26 @@ impl<T, E> Serialize for Result<T, E> where T: Serialize, E: Serialize {
///////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "std", feature = "nightly"))]
#[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)
}
}
@@ -893,7 +717,7 @@ impl Serialize for path::PathBuf {
}
}
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
impl<T> Serialize for NonZero<T> where T: Serialize + Zeroable {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
(**self).serialize(serializer)
+318 -289
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,343 +51,362 @@ 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;
/// A state object that is initialized by `serialize_seq`, passed to
/// `serialize_seq_elt`, and consumed by `serialize_seq_end`. Use `()` if no
/// state is required.
type SeqState;
/// A state object that is initialized by `serialize_tuple`, passed to
/// `serialize_tuple_elt`, and consumed by `serialize_tuple_end`. Use `()`
/// if no state is required.
type TupleState;
/// A state object that is initialized by `serialize_tuple_struct`, passed
/// to `serialize_tuple_struct_elt`, and consumed by
/// `serialize_tuple_struct_end`. Use `()` if no state is required.
type TupleStructState;
/// A state object that is initialized by `serialize_tuple_variant`, passed
/// to `serialize_tuple_variant_elt`, and consumed by
/// `serialize_tuple_variant_end`. Use `()` if no state is required.
type TupleVariantState;
/// A state object that is initialized by `serialize_map`, passed to
/// `serialize_map_elt`, and consumed by `serialize_map_end`. Use `()` if no
/// state is required.
type MapState;
/// A state object that is initialized by `serialize_struct`, passed to
/// `serialize_struct_elt`, and consumed by `serialize_struct_end`. Use `()`
/// if no state is required.
type StructState;
/// A state object that is initialized by `serialize_struct_variant`, passed
/// to `serialize_struct_variant_elt`, and consumed by
/// `serialize_struct_variant_end`. Use `()` if no state is required.
type StructVariantState;
/// Serializes a `bool` value.
fn serialize_bool(&mut self, v: bool) -> Result<(), Self::Error>;
/// Serializes a `isize` value. By default it casts the value to a `i64` and
/// passes it to the `serialize_i64` method.
#[inline]
fn serialize_isize(&mut self, v: isize) -> Result<(), Self::Error> {
self.serialize_i64(v as i64)
}
/// Serializes an `isize` value. If the format does not differentiate
/// between `isize` and `i64`, a reasonable implementation would be to cast
/// the value to `i64` and forward to `serialize_i64`.
fn serialize_isize(&mut self, v: isize) -> Result<(), Self::Error>;
/// Serializes a `i8` value. By default it casts the value to a `i64` and
/// passes it to the `serialize_i64` method.
#[inline]
fn serialize_i8(&mut self, v: i8) -> Result<(), Self::Error> {
self.serialize_i64(v as i64)
}
/// Serializes an `i8` value. If the format does not differentiate between
/// `i8` and `i64`, a reasonable implementation would be to cast the value
/// to `i64` and forward to `serialize_i64`.
fn serialize_i8(&mut self, v: i8) -> Result<(), Self::Error>;
/// Serializes a `i16` value. By default it casts the value to a `i64` and
/// passes it to the `serialize_i64` method.
#[inline]
fn serialize_i16(&mut self, v: i16) -> Result<(), Self::Error> {
self.serialize_i64(v as i64)
}
/// Serializes an `i16` value. If the format does not differentiate between
/// `i16` and `i64`, a reasonable implementation would be to cast the value
/// to `i64` and forward to `serialize_i64`.
fn serialize_i16(&mut self, v: i16) -> Result<(), Self::Error>;
/// Serializes a `i32` value. By default it casts the value to a `i64` and
/// passes it to the `serialize_i64` method.
#[inline]
fn serialize_i32(&mut self, v: i32) -> Result<(), Self::Error> {
self.serialize_i64(v as i64)
}
/// Serializes an `i32` value. If the format does not differentiate between
/// `i32` and `i64`, a reasonable implementation would be to cast the value
/// to `i64` and forward to `serialize_i64`.
fn serialize_i32(&mut self, v: i32) -> Result<(), Self::Error>;
/// Serializes a `i64` value.
#[inline]
/// Serializes an `i64` value.
fn serialize_i64(&mut self, v: i64) -> Result<(), Self::Error>;
/// Serializes a `usize` value. By default it casts the value to a `u64` and
/// passes it to the `serialize_u64` method.
#[inline]
fn serialize_usize(&mut self, v: usize) -> Result<(), Self::Error> {
self.serialize_u64(v as u64)
}
/// Serializes a `usize` value. If the format does not differentiate between
/// `usize` and `u64`, a reasonable implementation would be to cast the
/// value to `u64` and forward to `serialize_u64`.
fn serialize_usize(&mut self, v: usize) -> Result<(), Self::Error>;
/// Serializes a `u8` value. By default it casts the value to a `u64` and passes
/// it to the `serialize_u64` method.
#[inline]
fn serialize_u8(&mut self, v: u8) -> Result<(), Self::Error> {
self.serialize_u64(v as u64)
}
/// Serializes a `u8` value. If the format does not differentiate between
/// `u8` and `u64`, a reasonable implementation would be to cast the value
/// to `u64` and forward to `serialize_u64`.
fn serialize_u8(&mut self, v: u8) -> Result<(), Self::Error>;
/// Serializes a `u32` value. By default it casts the value to a `u64` and passes
/// it to the `serialize_u64` method.
#[inline]
fn serialize_u16(&mut self, v: u16) -> Result<(), Self::Error> {
self.serialize_u64(v as u64)
}
/// Serializes a `u16` value. If the format does not differentiate between
/// `u16` and `u64`, a reasonable implementation would be to cast the value
/// to `u64` and forward to `serialize_u64`.
fn serialize_u16(&mut self, v: u16) -> Result<(), Self::Error>;
/// Serializes a `u32` value. By default it casts the value to a `u64` and passes
/// it to the `serialize_u64` method.
#[inline]
fn serialize_u32(&mut self, v: u32) -> Result<(), Self::Error> {
self.serialize_u64(v as u64)
}
/// Serializes a `u32` value. If the format does not differentiate between
/// `u32` and `u64`, a reasonable implementation would be to cast the value
/// to `u64` and forward to `serialize_u64`.
fn serialize_u32(&mut self, v: u32) -> Result<(), Self::Error>;
/// `Serializes a `u64` value.
#[inline]
fn serialize_u64(&mut self, v: u64) -> Result<(), Self::Error>;
/// Serializes a `f32` value. By default it casts the value to a `f64` and passes
/// it to the `serialize_f64` method.
#[inline]
fn serialize_f32(&mut self, v: f32) -> Result<(), Self::Error> {
self.serialize_f64(v as f64)
}
/// Serializes an `f32` value. If the format does not differentiate between
/// `f32` and `f64`, a reasonable implementation would be to cast the value
/// to `f64` and forward to `serialize_f64`.
fn serialize_f32(&mut self, v: f32) -> Result<(), Self::Error>;
/// Serializes a `f64` value.
/// Serializes an `f64` value.
fn serialize_f64(&mut self, v: f64) -> Result<(), Self::Error>;
/// Serializes a character. By default it serializes it as a `&str` containing a
/// single character.
#[inline]
fn serialize_char(&mut self, v: char) -> Result<(), Self::Error> {
self.serialize_str(::utils::encode_utf8(v).as_str())
}
/// 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`.
fn serialize_str(&mut self, value: &str) -> Result<(), Self::Error>;
/// Enables those serialization formats that support serializing
/// byte slices separately from generic arrays. By default it serializes as a regular array.
#[inline]
fn serialize_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error> {
self.serialize_seq(impls::SeqIteratorVisitor::new(value.iter(), Some(value.len())))
}
/// 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`. 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.
///
/// By default, unit structs are serialized as a `()`.
#[inline]
fn serialize_unit_struct(&mut self, _name: &'static str) -> Result<(), Self::Error> {
self.serialize_unit()
}
/// Serializes a unit struct value. A reasonable implementation would be to
/// forward to `serialize_unit`.
fn serialize_unit_struct(
&mut self,
name: &'static str,
) -> Result<(), Self::Error>;
/// Serializes a unit variant, otherwise known as a variant with no arguments.
///
/// By default, unit variants are serialized as a `()`.
#[inline]
fn serialize_unit_variant(&mut self,
_name: &'static str,
_variant_index: usize,
_variant: &'static str) -> Result<(), Self::Error> {
self.serialize_unit()
}
/// Serializes a unit variant, otherwise known as a variant with no
/// arguments. A reasonable implementation would be to forward to
/// `serialize_unit`.
fn serialize_unit_variant(
&mut self,
name: &'static str,
variant_index: usize,
variant: &'static str,
) -> Result<(), Self::Error>;
/// Allows a tuple struct with a single element, also known as a
/// newtyped value, to be more efficiently serialized than a tuple struct with multiple items.
/// By default it just serializes the value as a tuple struct sequence.
#[inline]
fn serialize_newtype_struct<T>(&mut self,
name: &'static str,
value: T) -> Result<(), Self::Error>
where T: Serialize,
{
self.serialize_tuple_struct(name, Some(value))
}
/// 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` or to just serialize the inner value without wrapping.
fn serialize_newtype_struct<T: Serialize>(
&mut self,
name: &'static str,
value: T,
) -> Result<(), Self::Error>;
/// Allows a variant with a single item to be more efficiently
/// serialized than a variant with multiple items. By default it just serializes the value as a
/// tuple variant sequence.
#[inline]
fn serialize_newtype_variant<T>(&mut self,
name: &'static str,
variant_index: usize,
variant: &'static str,
value: T) -> Result<(), Self::Error>
where T: Serialize,
{
self.serialize_tuple_variant(
name,
variant_index,
variant,
Some(value))
}
/// Allows a variant with a single item to be more efficiently serialized
/// than a variant with multiple items. A reasonable implementation would be
/// to forward to `serialize_tuple_variant`.
fn serialize_newtype_variant<T: Serialize>(
&mut self,
name: &'static str,
variant_index: usize,
variant: &'static str,
value: T,
) -> Result<(), Self::Error>;
/// Serializes a `None` value..serialize
/// Serializes a `None` value.
fn serialize_none(&mut self) -> Result<(), Self::Error>;
/// Serializes a `Some(...)` value.
fn serialize_some<V>(&mut self, value: V) -> Result<(), Self::Error>
where V: Serialize;
fn serialize_some<T: Serialize>(
&mut self,
value: T,
) -> Result<(), Self::Error>;
/// Serializes a sequence.
///
/// Callees of this method need to construct a `SeqVisitor`, which iterates through each item
/// in the sequence.
fn serialize_seq<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor;
/// Begins to serialize a sequence. This call must be followed by zero or
/// more calls to `serialize_seq_elt`, then a call to `serialize_seq_end`.
fn serialize_seq(
&mut self,
len: Option<usize>,
) -> Result<Self::SeqState, Self::Error>;
/// Serializes a sequence element.
fn serialize_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize;
/// Serializes a sequence element. Must have previously called
/// `serialize_seq`.
fn serialize_seq_elt<T: Serialize>(
&mut self,
state: &mut Self::SeqState,
value: T,
) -> Result<(), Self::Error>;
/// Serializes a tuple.
///
/// By default this serializes a tuple as a sequence.
#[inline]
fn serialize_tuple<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.serialize_seq(visitor)
}
/// Finishes serializing a sequence.
fn serialize_seq_end(
&mut self,
state: Self::SeqState,
) -> Result<(), Self::Error>;
/// Serializes a tuple element.
///
/// By default, tuples are serialized as a sequence.
#[inline]
fn serialize_tuple_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize
{
self.serialize_seq_elt(value)
}
/// Begins to serialize a sequence whose length will be known at
/// deserialization time. This call must be followed by zero or more calls
/// to `serialize_seq_elt`, then a call to `serialize_seq_end`. A reasonable
/// implementation would be to forward to `serialize_seq`.
fn serialize_seq_fixed_size(
&mut self,
size: usize,
) -> Result<Self::SeqState, Self::Error>;
/// Serializes a fixed-size array.
///
/// By default this serializes an array as a sequence.
#[inline]
fn serialize_fixed_size_array<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.serialize_seq(visitor)
}
/// Begins to serialize a tuple. This call must be followed by zero or more
/// calls to `serialize_tuple_elt`, then a call to `serialize_tuple_end`. A
/// reasonable implementation would be to forward to `serialize_seq`.
fn serialize_tuple(
&mut self,
len: usize,
) -> Result<Self::TupleState, Self::Error>;
/// Serializes a tuple struct.
///
/// By default, tuple structs are serialized as a tuple.
#[inline]
fn serialize_tuple_struct<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.serialize_tuple(visitor)
}
/// Serializes a tuple element. Must have previously called
/// `serialize_tuple`.
fn serialize_tuple_elt<T: Serialize>(
&mut self,
state: &mut Self::TupleState,
value: T,
) -> Result<(), Self::Error>;
/// Serializes a tuple struct element.
///
/// By default, tuple struct elements are serialized as a tuple element.
#[inline]
fn serialize_tuple_struct_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize
{
self.serialize_tuple_elt(value)
}
/// Finishes serializing a tuple.
fn serialize_tuple_end(
&mut self,
state: Self::TupleState,
) -> Result<(), Self::Error>;
/// Serializes a tuple variant.
///
/// By default, tuple variants are serialized as a tuple struct.
#[inline]
fn serialize_tuple_variant<V>(&mut self,
_name: &'static str,
_variant_index: usize,
variant: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.serialize_tuple_struct(variant, visitor)
}
/// Begins to serialize a tuple struct. This call must be followed by zero
/// or more calls to `serialize_tuple_struct_elt`, then a call to
/// `serialize_tuple_struct_end`. A reasonable implementation would be to
/// forward to `serialize_tuple`.
fn serialize_tuple_struct(
&mut self,
name: &'static str,
len: usize,
) -> Result<Self::TupleStructState, Self::Error>;
/// Serializes a tuple element.
///
/// By default, tuples are serialized as a sequence.
#[inline]
fn serialize_tuple_variant_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize
{
self.serialize_tuple_struct_elt(value)
}
/// Serializes a tuple struct element. Must have previously called
/// `serialize_tuple_struct`.
fn serialize_tuple_struct_elt<T: Serialize>(
&mut self,
state: &mut Self::TupleStructState,
value: T,
) -> Result<(), Self::Error>;
/// Serializes a map.
///
/// Callees of this method need to construct a `MapVisitor`, which iterates through each item
/// in the map.
fn serialize_map<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: MapVisitor;
/// Finishes serializing a tuple struct.
fn serialize_tuple_struct_end(
&mut self,
state: Self::TupleStructState,
) -> Result<(), Self::Error>;
/// Serializes a map element (key-value pair).
fn serialize_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
where K: Serialize,
V: Serialize;
/// Begins to serialize a tuple variant. This call must be followed by zero
/// or more calls to `serialize_tuple_variant_elt`, then a call to
/// `serialize_tuple_variant_end`. A reasonable implementation would be to
/// forward to `serialize_tuple_struct`.
fn serialize_tuple_variant(
&mut self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize,
) -> Result<Self::TupleVariantState, Self::Error>;
/// Serializes a struct.
///
/// By default, structs are serialized as a map with the field name as the key.
#[inline]
fn serialize_struct<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: MapVisitor,
{
self.serialize_map(visitor)
}
/// Serializes a tuple variant element. Must have previously called
/// `serialize_tuple_variant`.
fn serialize_tuple_variant_elt<T: Serialize>(
&mut self,
state: &mut Self::TupleVariantState,
value: T,
) -> Result<(), Self::Error>;
/// Serializes an element of a struct.
///
/// By default, struct elements are serialized as a map element with the field name as the key.
#[inline]
fn serialize_struct_elt<V>(&mut self,
key: &'static str,
value: V) -> Result<(), Self::Error>
where V: Serialize,
{
self.serialize_map_elt(key, value)
}
/// Finishes serializing a tuple variant.
fn serialize_tuple_variant_end(
&mut self,
state: Self::TupleVariantState,
) -> Result<(), Self::Error>;
/// Serializes a struct variant.
///
/// By default, struct variants are serialized as a struct.
#[inline]
fn serialize_struct_variant<V>(&mut self,
_name: &'static str,
_variant_index: usize,
variant: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: MapVisitor,
{
self.serialize_struct(variant, visitor)
}
/// Begins to serialize a map. This call must be followed by zero or more
/// 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>;
/// Serializes an element of a struct variant.
///
/// By default, struct variant elements are serialized as a struct element.
#[inline]
fn serialize_struct_variant_elt<V>(&mut self,
key: &'static str,
value: V) -> Result<(), Self::Error>
where V: Serialize,
{
self.serialize_struct_elt(key, value)
}
}
/// A trait that is used by a `Serialize` to iterate through a sequence.
#[cfg_attr(feature = "nightly-testing", allow(len_without_is_empty))]
pub trait SeqVisitor {
/// Serializes a sequence item in the serializer.
///
/// This returns `Ok(Some(()))` when there are more items to serialize, or `Ok(None)` when
/// complete.
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer;
/// Return the length of the sequence if known.
#[inline]
fn len(&self) -> Option<usize> {
None
}
}
/// A trait that is used by a `Serialize` to iterate through a map.
#[cfg_attr(feature = "nightly-testing", allow(len_without_is_empty))]
pub trait MapVisitor {
/// Serializes a map item in the serializer.
///
/// This returns `Ok(Some(()))` when there are more items to serialize, or `Ok(None)` when
/// complete.
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer;
/// Return the length of the map if known.
#[inline]
fn len(&self) -> Option<usize> {
None
}
/// Serialize a map key. Must have previously called `serialize_map`.
fn serialize_map_key<T: Serialize>(
&mut self,
state: &mut Self::MapState,
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.
fn serialize_map_end(
&mut self,
state: Self::MapState,
) -> Result<(), Self::Error>;
/// Begins to serialize a struct. This call must be followed by zero or more
/// calls to `serialize_struct_elt`, then a call to `serialize_struct_end`.
fn serialize_struct(
&mut self,
name: &'static str,
len: usize,
) -> Result<Self::StructState, Self::Error>;
/// Serializes a struct field. Must have previously called
/// `serialize_struct`.
fn serialize_struct_elt<V: Serialize>(
&mut self,
state: &mut Self::StructState,
key: &'static str,
value: V,
) -> Result<(), Self::Error>;
/// Finishes serializing a struct.
fn serialize_struct_end(
&mut self,
state: Self::StructState,
) -> Result<(), Self::Error>;
/// Begins to serialize a struct variant. This call must be followed by zero
/// or more calls to `serialize_struct_variant_elt`, then a call to
/// `serialize_struct_variant_end`.
fn serialize_struct_variant(
&mut self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize,
) -> Result<Self::StructVariantState, Self::Error>;
/// Serialize a struct variant element. Must have previously called
/// `serialize_struct_variant`.
fn serialize_struct_variant_elt<V: Serialize>(
&mut self,
state: &mut Self::StructVariantState,
key: &'static str,
value: V,
) -> Result<(), Self::Error>;
/// Finishes serializing a struct variant.
fn serialize_struct_variant_end(
&mut self,
state: Self::StructVariantState,
) -> Result<(), Self::Error>;
}
+13 -20
View File
@@ -1,37 +1,30 @@
[package]
name = "serde_codegen"
version = "0.7.12"
version = "0.8.17"
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"]
nightly = ["quasi_macros"]
nightly-testing = ["clippy"]
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.14.0", optional = true }
syntex = { version = "^0.37.0", optional = true }
with-syn = []
[dependencies]
aster = { version = "^0.20.0", default-features = false }
clippy = { version = "^0.*", optional = true }
quasi = { version = "^0.14.0", default-features = false }
quasi_macros = { version = "^0.14.0", optional = true }
serde_codegen_internals = { version = "^0.2.0", path = "../serde_codegen_internals", default-features = false }
syntex = { version = "^0.37.0", optional = true }
syntex_syntax = { version = "^0.37.0", optional = true }
post-expansion = "0.1.0"
quote = "0.3"
serde_codegen_internals = { version = "=0.10.0", default-features = false, path = "../serde_codegen_internals" }
syn = { version = "0.9", features = ["aster", "visit"] }
syntex = { version = "^0.48.0", optional = true }
syntex_syntax = { version = "^0.48.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
}
+435 -612
View File
File diff suppressed because it is too large Load Diff
+176 -27
View File
@@ -1,12 +1,12 @@
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(feature = "nightly-testing", allow(too_many_arguments))]
#![cfg_attr(feature = "nightly-testing", allow(used_underscore_binding))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "clippy", allow(used_underscore_binding))]
#![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")]
@@ -23,30 +23,25 @@ extern crate syntax;
#[cfg(not(feature = "with-syntex"))]
extern crate rustc_plugin;
extern crate syn;
#[macro_use]
extern crate quote;
#[cfg(feature = "with-syn")]
extern crate post_expansion;
#[cfg(feature = "with-syntex")]
use std::path::Path;
#[cfg(not(feature = "with-syntex"))]
use syntax::feature_gate::AttributeType;
#[cfg(feature = "with-syntex")]
include!(concat!(env!("OUT_DIR"), "/lib.rs"));
#[cfg(not(feature = "with-syntex"))]
include!("lib.rs.in");
mod bound;
mod de;
mod ser;
#[cfg(feature = "with-syntex")]
pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
where S: AsRef<Path>,
D: AsRef<Path>,
{
let mut registry = syntex::Registry::new();
register(&mut registry);
registry.expand("", src.as_ref(), dst.as_ref())
}
#[cfg(feature = "with-syntex")]
pub fn register(reg: &mut syntex::Registry) {
fn syntex_registry() -> syntex::Registry {
use syntax::{ast, fold};
/// Strip the serde attributes from the crate.
@@ -73,13 +68,43 @@ pub fn register(reg: &mut syntex::Registry) {
fold::Folder::fold_crate(&mut StripAttributeFolder, krate)
}
let mut reg = syntex::Registry::new();
reg.add_attr("feature(custom_derive)");
reg.add_attr("feature(custom_attribute)");
reg.add_decorator("derive_Serialize", ser::expand_derive_serialize);
reg.add_decorator("derive_Deserialize", de::expand_derive_deserialize);
reg.add_decorator("derive_Serialize", expand_derive_serialize);
reg.add_decorator("derive_Deserialize", expand_derive_deserialize);
reg.add_post_expansion_pass(strip_attributes);
reg
}
#[cfg(feature = "with-syntex")]
pub fn expand_str(src: &str) -> Result<String, syntex::Error> {
let src = src.to_owned();
let expand_thread = move || {
syntex_registry().expand_str("", "", &src)
};
syntex::with_extra_stack(expand_thread)
}
#[cfg(feature = "with-syntex")]
pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
where S: AsRef<Path>,
D: AsRef<Path>,
{
let src = src.as_ref().to_owned();
let dst = dst.as_ref().to_owned();
let expand_thread = move || {
syntex_registry().expand("", src, dst)
};
syntex::with_extra_stack(expand_thread)
}
#[cfg(not(feature = "with-syntex"))]
@@ -87,12 +112,136 @@ 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)));
Box::new(expand_derive_serialize)));
reg.register_syntax_extension(
syntax::parse::token::intern("derive_Deserialize"),
syntax::ext::base::MultiDecorator(
Box::new(de::expand_derive_deserialize)));
Box::new(expand_derive_deserialize)));
reg.register_attribute("serde".to_owned(), AttributeType::Normal);
}
macro_rules! shim {
($name:ident $pkg:ident :: $func:ident) => {
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) {
match attr.node.value.node {
ast::MetaItemKind::List(ref name, _) if name == "serde" => {
attr::mark_used(attr);
}
_ => {}
}
}
}
visit::walk_item(&mut MarkSerdeAttributesUsed, item);
use syntax::print::pprust;
let s = pprust::item_to_string(item);
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()));
}
};
}
shim!(Serialize ser::expand_derive_serialize);
shim!(Deserialize de::expand_derive_deserialize);
#[cfg(feature = "with-syn")]
pub fn expand_single_item(item: &str) -> Result<String, String> {
let syn_item = syn::parse_macro_input(item).unwrap();
let (ser, de, syn_item) = strip_serde_derives(syn_item);
let expanded_ser = if ser {
Some(try!(ser::expand_derive_serialize(&syn_item)))
} else {
None
};
let expanded_de = if de {
Some(try!(de::expand_derive_deserialize(&syn_item)))
} else {
None
};
let syn_item = post_expansion::strip_attrs_later(syn_item, &["serde"], "serde");
return Ok(quote!(#expanded_ser #expanded_de #syn_item).to_string());
fn strip_serde_derives(item: syn::MacroInput) -> (bool, bool, syn::MacroInput) {
let mut ser = false;
let mut de = false;
let item = syn::MacroInput {
attrs: item.attrs.into_iter().flat_map(|attr| {
if attr.is_sugared_doc || attr.style != syn::AttrStyle::Outer {
return Some(attr);
}
let (name, nested) = match attr.value {
syn::MetaItem::List(name, nested) => (name, nested),
_ => return Some(attr)
};
if name != "derive" {
return Some(syn::Attribute {
style: syn::AttrStyle::Outer,
value: syn::MetaItem::List(name, nested),
is_sugared_doc: false,
});
}
let rest: Vec<_> = nested.into_iter().filter(|nested| {
match *nested {
syn::MetaItem::Word(ref word) if word == "Serialize" => {
ser = true;
false
}
syn::MetaItem::Word(ref word) if word == "Deserialize" => {
de = true;
false
}
_ => true,
}
}).collect();
if rest.is_empty() {
None
} else {
Some(syn::Attribute {
style: syn::AttrStyle::Outer,
value: syn::MetaItem::List(name, rest),
is_sugared_doc: false,
})
}
}).collect(),
..item
};
(ser, de, item)
}
}
-3
View File
@@ -1,3 +0,0 @@
mod bound;
mod de;
mod ser;
+284 -548
View File
File diff suppressed because it is too large Load Diff
+5 -7
View File
@@ -1,20 +1,18 @@
[package]
name = "serde_codegen_internals"
version = "0.2.0"
version = "0.10.0"
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"]
nightly-testing = ["clippy"]
with-syntex = ["syntex_syntax", "syntex_errors"]
unstable-testing = ["clippy"]
[dependencies]
clippy = { version = "^0.*", optional = true }
syntex_syntax = { version = "^0.37.0", optional = true }
syntex_errors = { version = "^0.37.0", optional = true }
syn = "0.9"
+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,
}
+153 -282
View File
@@ -1,14 +1,5 @@
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;
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
// are `attr::Item::from_ast`, `attr::Variant::from_ast`, and
@@ -18,13 +9,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,
@@ -32,47 +24,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 {
@@ -82,18 +67,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()
}
}
@@ -103,35 +88,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);
syn::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" => {
syn::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);
@@ -139,20 +121,20 @@ impl Item {
}
// Parse `#[serde(deny_unknown_fields)]`
ast::MetaItemKind::Word(ref name) if name == &"deny_unknown_fields" => {
deny_unknown_fields.set_true(span);
syn::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);
syn::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" => {
syn::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);
@@ -160,10 +142,8 @@ impl Item {
}
_ => {
cx.span_err(
meta_item.span,
&format!("unknown serde container attribute `{}`",
meta_item_to_string(meta_item)));
cx.error(format!("unknown serde container attribute `{}`",
meta_item.name()));
}
}
}
@@ -171,8 +151,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(),
@@ -188,11 +168,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[..])
}
}
@@ -204,26 +184,23 @@ pub struct Variant {
}
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 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);
syn::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" => {
syn::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);
@@ -231,10 +208,8 @@ impl Variant {
}
_ => {
cx.span_err(
meta_item.span,
&format!("unknown serde variant attribute `{}`",
meta_item_to_string(meta_item)));
cx.error(format!("unknown serde variant attribute `{}`",
meta_item.name()));
}
}
}
@@ -242,8 +217,8 @@ 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()),
},
}
}
@@ -259,12 +234,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.
@@ -275,14 +250,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");
@@ -295,24 +270,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);
syn::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" => {
syn::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);
@@ -320,58 +294,58 @@ impl Field {
}
// Parse `#[serde(default)]`
ast::MetaItemKind::Word(ref name) if name == &"default" => {
default.set(span, FieldDefault::Default);
syn::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));
syn::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);
syn::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);
syn::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);
syn::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);
syn::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);
syn::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);
syn::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" => {
syn::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);
@@ -379,10 +353,8 @@ impl Field {
}
_ => {
cx.span_err(
meta_item.span,
&format!("unknown serde field attribute `{}`",
meta_item_to_string(meta_item)));
cx.error(format!("unknown serde field attribute `{}`",
meta_item.name()));
}
}
}
@@ -390,8 +362,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 {
@@ -422,7 +394,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()
}
@@ -430,207 +402,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::MetaItem],
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 {
syn::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);
syn::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::MetaItem],
) -> 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::MetaItem],
) -> 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::MetaItem>> {
match attr.value {
syn::MetaItem::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, delimed) => {
TokenTree::Delimited(
self.new_span(span),
tokenstream::Delimited {
delim: delimed.delim,
open_span: delimed.open_span,
tts: self.fold_tts(delimed.tts),
close_span: delimed.close_span,
}
)
}
TokenTree::Sequence(span, seq) => {
TokenTree::Sequence(
self.new_span(span),
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"
}
}
+5 -16
View File
@@ -1,21 +1,10 @@
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private, plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(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;
+30
View File
@@ -0,0 +1,30 @@
[package]
name = "serde_derive"
version = "0.8.17"
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]
post-expansion = "0.1.0"
[dependencies.serde_codegen]
version = "=0.8.17"
path = "../serde_codegen"
default-features = false
features = ["with-syn"]
[dev-dependencies]
compiletest_rs = "^0.2.0"
fnv = "1.0"
serde = { version = "0.8.17", path = "../serde" }
serde_test = { version = "0.8.17", path = "../serde_test" }
+30
View File
@@ -0,0 +1,30 @@
#![feature(proc_macro, proc_macro_lib)]
#![cfg(not(test))]
extern crate proc_macro;
extern crate serde_codegen;
#[macro_use]
extern crate post_expansion;
use proc_macro::TokenStream;
#[proc_macro_derive(Serialize)]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
let item = format!("#[derive(Serialize)]\n{}", input);
match serde_codegen::expand_single_item(&item) {
Ok(expanded) => expanded.parse().unwrap(),
Err(msg) => panic!(msg),
}
}
#[proc_macro_derive(Deserialize)]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
let item = format!("#[derive(Deserialize)]\n{}", input);
match serde_codegen::expand_single_item(&item) {
Ok(expanded) => expanded.parse().unwrap(),
Err(msg) => panic!(msg),
}
}
register_post_expansion!(PostExpansion_serde);
@@ -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() { }
@@ -20,6 +20,11 @@ fn run_mode(mode: &'static str) {
}
#[test]
fn compile_test() {
fn compile_fail() {
run_mode("compile-fail");
}
#[test]
fn run_pass() {
run_mode("run-pass");
}
@@ -0,0 +1,13 @@
#![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.
#[derive(Serialize)]
struct A { b: u8 }
fn main() {}
+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
-36
View File
@@ -1,36 +0,0 @@
[package]
name = "serde_macros"
version = "0.7.12"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
repository = "https://github.com/serde-rs/serde"
documentation = "https://github.com/serde-rs/serde"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[lib]
name = "serde_macros"
plugin = true
[features]
nightly-testing = ["clippy", "serde/nightly-testing", "serde_codegen/nightly-testing"]
[dependencies]
clippy = { version = "^0.*", optional = true }
serde_codegen = { version = "^0.7.12", path = "../serde_codegen", default-features = false, features = ["nightly"] }
[dev-dependencies]
compiletest_rs = "^0.2.0"
fnv = "1.0"
rustc-serialize = "^0.3.16"
serde = { version = "^0.7.12", path = "../serde" }
serde_test = { version = "^0.7.12", path = "../serde_test" }
[[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 -3
View File
@@ -1,14 +1,15 @@
[package]
name = "serde_test"
version = "0.7.12"
version = "0.8.17"
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 = { version = "0.7.12", path = "../serde" }
serde = { version = "0.8.17", path = "../serde" }
+98 -6
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,
{
@@ -135,15 +224,18 @@ impl<I> de::Deserializer for Deserializer<I>
Some(Token::Option(true)) => visitor.visit_some(self),
Some(Token::Unit) => visitor.visit_unit(),
Some(Token::UnitStruct(name)) => visitor.visit_unit_struct(name),
Some(Token::SeqStart(len)) | Some(Token::TupleStructStart(_, len)) => {
Some(Token::SeqStart(len)) => {
self.visit_seq(len, visitor)
}
Some(Token::SeqArrayStart(len)) => {
Some(Token::SeqArrayStart(len))| Some(Token::TupleStructStart(_, len)) => {
self.visit_seq(Some(len), visitor)
}
Some(Token::MapStart(len)) | Some(Token::StructStart(_, len)) => {
Some(Token::MapStart(len)) => {
self.visit_map(len, visitor)
}
Some(Token::StructStart(_, len)) => {
self.visit_map(Some(len), visitor)
}
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
}
@@ -238,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,
@@ -745,7 +837,7 @@ impl<'a, I> VariantVisitor for DeserializerVariantVisitor<'a, I>
where V: Visitor,
{
match self.de.tokens.peek() {
Some(&Token::EnumSeqStart(_, _, Some(enum_len))) => {
Some(&Token::EnumSeqStart(_, _, enum_len)) => {
let token = self.de.tokens.next().unwrap();
if len == enum_len {
@@ -776,7 +868,7 @@ impl<'a, I> VariantVisitor for DeserializerVariantVisitor<'a, I>
where V: Visitor,
{
match self.de.tokens.peek() {
Some(&Token::EnumMapStart(_, _, Some(enum_len))) => {
Some(&Token::EnumMapStart(_, _, enum_len)) => {
let token = self.de.tokens.next().unwrap();
if fields.len() == enum_len {
+89 -116
View File
@@ -2,8 +2,6 @@ use std::marker::PhantomData;
use serde::ser::{
self,
MapVisitor,
SeqVisitor,
Serialize,
};
@@ -30,32 +28,19 @@ impl<'a, I> Serializer<'a, I>
pub fn next_token(&mut self) -> Option<&'a Token<'a>> {
self.tokens.next()
}
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::SeqEnd));
Ok(())
}
fn visit_map<V>(&mut self, mut visitor: V) -> Result<(), Error>
where V: MapVisitor
{
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::MapEnd));
Ok(())
}
}
impl<'a, I> ser::Serializer for Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
{
type Error = Error;
type MapState = ();
type SeqState = ();
type TupleState = ();
type TupleStructState = ();
type TupleVariantState = ();
type StructState = ();
type StructVariantState = ();
fn serialize_unit(&mut self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Unit));
@@ -174,177 +159,165 @@ impl<'a, I> ser::Serializer for Serializer<'a, I>
value.serialize(self)
}
fn serialize_seq<V>(&mut self, visitor: V) -> Result<(), Error>
where V: SeqVisitor
fn serialize_seq<'b>(&'b mut self, len: Option<usize>) -> Result<(), Error>
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::SeqStart(len)));
self.visit_seq(visitor)
Ok(())
}
fn serialize_fixed_size_array<V>(&mut self, visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
let len = visitor.len().expect("arrays must have a length");
assert_eq!(self.tokens.next(), Some(&Token::SeqArrayStart(len)));
self.visit_seq(visitor)
}
fn serialize_seq_elt<T>(&mut self, value: T) -> Result<(), Error>
fn serialize_seq_elt<T>(&mut self, _: &mut (), value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::SeqSep));
value.serialize(self)
}
fn serialize_tuple<V>(&mut self, mut visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
let len = visitor.len().expect("arrays must have a length");
assert_eq!(self.tokens.next(), Some(&Token::TupleStart(len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::TupleEnd));
fn serialize_seq_end(&mut self, _: ()) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::SeqEnd));
Ok(())
}
fn serialize_tuple_elt<T>(&mut self, value: T) -> Result<(), Error>
fn serialize_seq_fixed_size(&mut self, len: usize) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::SeqArrayStart(len)));
Ok(())
}
fn serialize_tuple(&mut self, len: usize) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::TupleStart(len)));
Ok(())
}
fn serialize_tuple_elt<T>(&mut self, _: &mut (), value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::TupleSep));
value.serialize(self)
}
fn serialize_tuple_end(&mut self, _: ()) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleEnd));
Ok(())
}
fn serialize_newtype_struct<T>(&mut self,
name: &'static str,
value: T) -> Result<(), Error>
name: &'static str,
value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::StructNewType(name)));
value.serialize(self)
}
fn serialize_tuple_struct<V>(&mut self, name: &str, mut visitor: V) -> Result<(), Error>
where V: SeqVisitor
fn serialize_tuple_struct(&mut self, name: &'static str, len: usize) -> Result<(), Error>
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::TupleStructStart(name, len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::TupleStructEnd));
Ok(())
}
fn serialize_tuple_struct_elt<T>(&mut self, value: T) -> Result<(), Error>
where T: Serialize,
fn serialize_tuple_struct_elt<T>(&mut self, _: &mut (), value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::TupleStructSep));
value.serialize(self)
}
fn serialize_tuple_variant<V>(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
mut visitor: V) -> Result<(), Error>
where V: SeqVisitor
fn serialize_tuple_struct_end(&mut self, _: ()) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleStructEnd));
Ok(())
}
fn serialize_tuple_variant(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
len: usize) -> Result<(), Error>
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqStart(name, variant, len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqEnd));
Ok(())
}
fn serialize_tuple_variant_elt<T>(&mut self, value: T) -> Result<(), Error>
where T: Serialize,
fn serialize_tuple_variant_elt<T>(&mut self, _: &mut (), value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqSep));
value.serialize(self)
}
fn serialize_map<V>(&mut self, visitor: V) -> Result<(), Error>
where V: MapVisitor
{
let len = visitor.len();
fn serialize_tuple_variant_end(&mut self, _: ()) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqEnd));
Ok(())
}
fn serialize_map(&mut self, len: Option<usize>) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::MapStart(len)));
self.visit_map(visitor)
Ok(())
}
fn serialize_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), 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));
key.serialize(self)
}
try!(key.serialize(self));
fn serialize_map_value<T>(&mut self, _: &mut (), value: T) -> Result<(), Self::Error> where T: Serialize {
value.serialize(self)
}
fn serialize_struct<V>(&mut self, name: &str, mut visitor: V) -> Result<(), Error>
where V: MapVisitor
{
let len = visitor.len();
fn serialize_map_end(&mut self, _: ()) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::MapEnd));
Ok(())
}
fn serialize_struct(&mut self, name: &str, len: usize) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::StructStart(name, len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::StructEnd));
Ok(())
}
fn serialize_struct_elt<T>(&mut self, key: &'static str, value: T) -> Result<(), Error>
where T: Serialize,
{
fn serialize_struct_elt<V>(&mut self, _: &mut (), key: &'static str, value: V) -> Result<(), Self::Error> where V: Serialize {
assert_eq!(self.tokens.next(), Some(&Token::StructSep));
try!(key.serialize(self));
value.serialize(self)
}
fn serialize_struct_variant<V>(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
mut visitor: V) -> Result<(), Error>
where V: MapVisitor
{
let len = visitor.len();
fn serialize_struct_end(&mut self, _: ()) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::StructEnd));
Ok(())
}
fn serialize_struct_variant(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
len: usize) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::EnumMapStart(name, variant, len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::EnumMapEnd));
Ok(())
}
fn serialize_struct_variant_elt<T>(&mut self, key: &'static str, value: T) -> Result<(), Error>
where T: Serialize,
{
fn serialize_struct_variant_elt<V>(&mut self, _: &mut (), key: &'static str, value: V) -> Result<(), Self::Error> where V: Serialize {
assert_eq!(self.tokens.next(), Some(&Token::EnumMapSep));
try!(key.serialize(self));
value.serialize(self)
}
fn serialize_struct_variant_end(&mut self, _: ()) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumMapEnd));
Ok(())
}
fn serialize_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error> {
let mut state = try!(self.serialize_seq(Some(value.len())));
for c in value {
try!(self.serialize_seq_elt(&mut state, c));
}
self.serialize_seq_end(state)
}
}
+4 -4
View File
@@ -38,7 +38,7 @@ pub enum Token<'a> {
TupleSep,
TupleEnd,
TupleStructStart(&'a str, Option<usize>),
TupleStructStart(&'a str, usize),
TupleStructSep,
TupleStructEnd,
@@ -46,15 +46,15 @@ pub enum Token<'a> {
MapSep,
MapEnd,
StructStart(&'a str, Option<usize>),
StructStart(&'a str, usize),
StructSep,
StructEnd,
EnumSeqStart(&'a str, &'a str, Option<usize>),
EnumSeqStart(&'a str, &'a str, usize),
EnumSeqSep,
EnumSeqEnd,
EnumMapStart(&'a str, &'a str, Option<usize>),
EnumMapStart(&'a str, &'a str, usize),
EnumMapSep,
EnumMapEnd,
}
+7 -10
View File
@@ -1,26 +1,27 @@
[package]
name = "serde_testing"
version = "0.7.12"
version = "0.8.17"
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"
[features]
nightly-testing = ["clippy", "serde/nightly-testing", "serde_codegen/nightly-testing"]
unstable-testing = ["clippy", "serde/unstable-testing", "serde_codegen/unstable-testing"]
[build-dependencies]
serde_codegen = { version = "*", path = "../serde_codegen", features = ["with-syntex"] }
serde_codegen = { path = "../serde_codegen", features = ["with-syntex"] }
[dev-dependencies]
fnv = "1.0"
rustc-serialize = "^0.3.16"
serde = { version = "*", path = "../serde" }
serde_test = { version = "*", path = "../serde_test" }
serde = { path = "../serde" }
serde_test = { path = "../serde_test" }
[dependencies]
clippy = { version = "^0.*", optional = true }
@@ -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 = "nightly", feature(plugin))]
#![cfg_attr(feature = "nightly", 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 -2
View File
@@ -1,4 +1,4 @@
#![cfg_attr(feature = "nightly", feature(plugin))]
#![cfg_attr(feature = "nightly", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
include!(concat!(env!("OUT_DIR"), "/test.rs"));
+2
View File
@@ -1,3 +1,5 @@
extern crate serde;
#[macro_use]
mod macros;
+61 -33
View File
@@ -82,7 +82,7 @@ fn test_default_struct() {
assert_de_tokens(
&DefaultStruct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 },
&[
Token::StructStart("DefaultStruct", Some(3)),
Token::StructStart("DefaultStruct", 3),
Token::StructSep,
Token::Str("a1"),
@@ -111,7 +111,7 @@ fn test_default_struct() {
assert_de_tokens(
&DefaultStruct { a1: 1, a2: 0, a3: 123, a4: 0, a5: 123 },
&[
Token::StructStart("DefaultStruct", Some(1)),
Token::StructStart("DefaultStruct", 1),
Token::StructSep,
Token::Str("a1"),
@@ -145,7 +145,7 @@ fn test_default_enum() {
assert_de_tokens(
&DefaultEnum::Struct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 },
&[
Token::EnumMapStart("DefaultEnum", "Struct", Some(5)),
Token::EnumMapStart("DefaultEnum", "Struct", 5),
Token::EnumMapSep,
Token::Str("a1"),
@@ -174,7 +174,7 @@ fn test_default_enum() {
assert_de_tokens(
&DefaultEnum::Struct { a1: 1, a2: 0, a3: 123, a4: 0, a5: 123 },
&[
Token::EnumMapStart("DefaultEnum", "Struct", Some(5)),
Token::EnumMapStart("DefaultEnum", "Struct", 5),
Token::EnumMapSep,
Token::Str("a1"),
@@ -208,7 +208,7 @@ fn test_no_std_default() {
assert_de_tokens(
&ContainsNoStdDefault { a: NoStdDefault(123) },
&[
Token::StructStart("ContainsNoStdDefault", Some(1)),
Token::StructStart("ContainsNoStdDefault", 1),
Token::StructEnd,
]
);
@@ -216,7 +216,7 @@ fn test_no_std_default() {
assert_de_tokens(
&ContainsNoStdDefault { a: NoStdDefault(8) },
&[
Token::StructStart("ContainsNoStdDefault", Some(1)),
Token::StructStart("ContainsNoStdDefault", 1),
Token::StructSep,
Token::Str("a"),
@@ -281,7 +281,7 @@ fn test_elt_not_deserialize() {
e: NotDeserializeEnum::Trouble,
},
&[
Token::StructStart("ContainsNotDeserialize", Some(3)),
Token::StructStart("ContainsNotDeserialize", 3),
Token::StructEnd,
]
);
@@ -299,7 +299,7 @@ fn test_ignore_unknown() {
assert_de_tokens(
&DefaultStruct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 },
&[
Token::StructStart("DefaultStruct", Some(5)),
Token::StructStart("DefaultStruct", 5),
Token::StructSep,
Token::Str("whoops1"),
@@ -334,7 +334,7 @@ fn test_ignore_unknown() {
assert_de_tokens_error::<DenyUnknown>(
&[
Token::StructStart("DenyUnknown", Some(2)),
Token::StructStart("DenyUnknown", 2),
Token::StructSep,
Token::Str("a1"),
@@ -368,7 +368,7 @@ fn test_rename_struct() {
assert_tokens(
&RenameStruct { a1: 1, a2: 2 },
&[
Token::StructStart("Superhero", Some(2)),
Token::StructStart("Superhero", 2),
Token::StructSep,
Token::Str("a1"),
@@ -385,7 +385,7 @@ fn test_rename_struct() {
assert_ser_tokens(
&RenameStructSerializeDeserialize { a1: 1, a2: 2 },
&[
Token::StructStart("SuperheroSer", Some(2)),
Token::StructStart("SuperheroSer", 2),
Token::StructSep,
Token::Str("a1"),
@@ -402,7 +402,7 @@ fn test_rename_struct() {
assert_de_tokens(
&RenameStructSerializeDeserialize { a1: 1, a2: 2 },
&[
Token::StructStart("SuperheroDe", Some(2)),
Token::StructStart("SuperheroDe", 2),
Token::StructSep,
Token::Str("a1"),
@@ -465,7 +465,7 @@ fn test_rename_enum() {
assert_tokens(
&RenameEnum::WonderWoman(0, 1),
&[
Token::EnumSeqStart("Superhero", "diana_prince", Some(2)),
Token::EnumSeqStart("Superhero", "diana_prince", 2),
Token::EnumSeqSep,
Token::I8(0),
@@ -480,7 +480,7 @@ fn test_rename_enum() {
assert_tokens(
&RenameEnum::Flash { a: 1 },
&[
Token::EnumMapStart("Superhero", "barry_allan", Some(1)),
Token::EnumMapStart("Superhero", "barry_allan", 1),
Token::EnumMapSep,
Token::Str("b"),
@@ -496,7 +496,7 @@ fn test_rename_enum() {
b: String::new(),
},
&[
Token::EnumMapStart("SuperheroSer", "dick_grayson", Some(2)),
Token::EnumMapStart("SuperheroSer", "dick_grayson", 2),
Token::EnumMapSep,
Token::Str("a"),
@@ -516,7 +516,7 @@ fn test_rename_enum() {
b: String::new(),
},
&[
Token::EnumMapStart("SuperheroDe", "jason_todd", Some(2)),
Token::EnumMapStart("SuperheroDe", "jason_todd", 2),
Token::EnumMapSep,
Token::Str("a"),
@@ -550,7 +550,7 @@ fn test_skip_serializing_struct() {
c: 3,
},
&[
Token::StructStart("SkipSerializingStruct", Some(2)),
Token::StructStart("SkipSerializingStruct", 2),
Token::StructSep,
Token::Str("a"),
@@ -571,7 +571,7 @@ fn test_skip_serializing_struct() {
c: 123,
},
&[
Token::StructStart("SkipSerializingStruct", Some(1)),
Token::StructStart("SkipSerializingStruct", 1),
Token::StructSep,
Token::Str("a"),
@@ -603,7 +603,7 @@ fn test_skip_serializing_enum() {
c: 3,
},
&[
Token::EnumMapStart("SkipSerializingEnum", "Struct", Some(2)),
Token::EnumMapStart("SkipSerializingEnum", "Struct", 2),
Token::EnumMapSep,
Token::Str("a"),
@@ -624,7 +624,7 @@ fn test_skip_serializing_enum() {
c: 123,
},
&[
Token::EnumMapStart("SkipSerializingEnum", "Struct", Some(1)),
Token::EnumMapStart("SkipSerializingEnum", "Struct", 1),
Token::EnumMapSep,
Token::Str("a"),
@@ -671,7 +671,7 @@ fn test_elt_not_serialize() {
d: NotSerializeEnum::Trouble,
},
&[
Token::StructStart("ContainsNotSerialize", Some(2)),
Token::StructStart("ContainsNotSerialize", 2),
Token::StructSep,
Token::Str("a"),
@@ -703,7 +703,7 @@ fn test_serialize_with_struct() {
b: 2,
},
&[
Token::StructStart("SerializeWithStruct", Some(2)),
Token::StructStart("SerializeWithStruct", 2),
Token::StructSep,
Token::Str("a"),
@@ -723,7 +723,7 @@ fn test_serialize_with_struct() {
b: 123,
},
&[
Token::StructStart("SerializeWithStruct", Some(2)),
Token::StructStart("SerializeWithStruct", 2),
Token::StructSep,
Token::Str("a"),
@@ -756,7 +756,7 @@ fn test_serialize_with_enum() {
b: 2,
},
&[
Token::EnumMapStart("SerializeWithEnum", "Struct", Some(2)),
Token::EnumMapStart("SerializeWithEnum", "Struct", 2),
Token::EnumMapSep,
Token::Str("a"),
@@ -776,7 +776,7 @@ fn test_serialize_with_enum() {
b: 123,
},
&[
Token::EnumMapStart("SerializeWithEnum", "Struct", Some(2)),
Token::EnumMapStart("SerializeWithEnum", "Struct", 2),
Token::EnumMapSep,
Token::Str("a"),
@@ -806,7 +806,7 @@ fn test_deserialize_with_struct() {
b: 2,
},
&[
Token::StructStart("DeserializeWithStruct", Some(2)),
Token::StructStart("DeserializeWithStruct", 2),
Token::StructSep,
Token::Str("a"),
@@ -826,7 +826,7 @@ fn test_deserialize_with_struct() {
b: 123,
},
&[
Token::StructStart("DeserializeWithStruct", Some(2)),
Token::StructStart("DeserializeWithStruct", 2),
Token::StructSep,
Token::Str("a"),
@@ -858,7 +858,7 @@ fn test_deserialize_with_enum() {
b: 2,
},
&[
Token::EnumMapStart("DeserializeWithEnum", "Struct", Some(2)),
Token::EnumMapStart("DeserializeWithEnum", "Struct", 2),
Token::EnumMapSep,
Token::Str("a"),
@@ -878,7 +878,7 @@ fn test_deserialize_with_enum() {
b: 123,
},
&[
Token::EnumMapStart("DeserializeWithEnum", "Struct", Some(2)),
Token::EnumMapStart("DeserializeWithEnum", "Struct", 2),
Token::EnumMapSep,
Token::Str("a"),
@@ -897,7 +897,7 @@ fn test_deserialize_with_enum() {
fn test_missing_renamed_field_struct() {
assert_de_tokens_error::<RenameStruct>(
&[
Token::StructStart("Superhero", Some(2)),
Token::StructStart("Superhero", 2),
Token::StructSep,
Token::Str("a1"),
@@ -910,7 +910,7 @@ fn test_missing_renamed_field_struct() {
assert_de_tokens_error::<RenameStructSerializeDeserialize>(
&[
Token::StructStart("SuperheroDe", Some(2)),
Token::StructStart("SuperheroDe", 2),
Token::StructSep,
Token::Str("a1"),
@@ -926,7 +926,7 @@ fn test_missing_renamed_field_struct() {
fn test_missing_renamed_field_enum() {
assert_de_tokens_error::<RenameEnum>(
&[
Token::EnumMapStart("Superhero", "barry_allan", Some(1)),
Token::EnumMapStart("Superhero", "barry_allan", 1),
Token::EnumMapEnd,
],
@@ -935,7 +935,7 @@ fn test_missing_renamed_field_enum() {
assert_de_tokens_error::<RenameEnumSerializeDeserialize<i8>>(
&[
Token::EnumMapStart("SuperheroDe", "jason_todd", Some(2)),
Token::EnumMapStart("SuperheroDe", "jason_todd", 2),
Token::EnumMapSep,
Token::Str("a"),
@@ -946,3 +946,31 @@ fn test_missing_renamed_field_enum() {
Error::MissingField("d"),
);
}
#[derive(Debug, PartialEq, Deserialize)]
enum InvalidLengthEnum {
A(i32, i32, i32),
B(#[serde(skip_deserializing)] i32, i32, i32),
}
#[test]
fn test_invalid_length_enum() {
assert_de_tokens_error::<InvalidLengthEnum>(
&[
Token::EnumSeqStart("InvalidLengthEnum", "A", 3),
Token::EnumSeqSep,
Token::I32(1),
Token::EnumSeqEnd,
],
Error::InvalidLength(1),
);
assert_de_tokens_error::<InvalidLengthEnum>(
&[
Token::EnumSeqStart("InvalidLengthEnum", "B", 3),
Token::EnumSeqSep,
Token::I32(1),
Token::EnumSeqEnd,
],
Error::InvalidLength(1),
);
}
+296 -21
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,17 +51,64 @@ impl BytesSerializer {
}
}
impl serde::Serializer for BytesSerializer {
impl Serializer for BytesSerializer {
type Error = Error;
type SeqState = ();
type MapState = ();
type TupleState = ();
type TupleStructState = ();
type TupleVariantState = ();
type StructState = ();
type StructVariantState = ();
fn serialize_unit(&mut self) -> Result<(), Error> {
Err(Error)
}
fn serialize_unit_struct(&mut self, _name: &'static str) -> Result<(), Error> {
Err(Error)
}
fn serialize_unit_variant(&mut self, _: &'static str, _: usize, _: &'static str) -> Result<(), Error> {
Err(Error)
}
fn serialize_bool(&mut self, _v: bool) -> Result<(), Error> {
Err(Error)
}
fn serialize_isize(&mut self, _v: isize) -> Result<(), Error> {
Err(Error)
}
fn serialize_usize(&mut self, _v: usize) -> Result<(), Error> {
Err(Error)
}
fn serialize_i8(&mut self, _v: i8) -> Result<(), Error> {
Err(Error)
}
fn serialize_u8(&mut self, _v: u8) -> Result<(), Error> {
Err(Error)
}
fn serialize_i16(&mut self, _v: i16) -> Result<(), Error> {
Err(Error)
}
fn serialize_u16(&mut self, _v: u16) -> Result<(), Error> {
Err(Error)
}
fn serialize_i32(&mut self, _v: i32) -> Result<(), Error> {
Err(Error)
}
fn serialize_u32(&mut self, _v: u32) -> Result<(), Error> {
Err(Error)
}
fn serialize_i64(&mut self, _v: i64) -> Result<(), Error> {
Err(Error)
}
@@ -90,32 +138,142 @@ 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_seq<V>(&mut self, _visitor: V) -> Result<(), Error>
where V: serde::ser::SeqVisitor,
fn serialize_newtype_struct<V>(&mut self, _: &'static str, _value: V) -> Result<(), Error>
where V: Serialize,
{
Err(Error)
}
fn serialize_seq_elt<T>(&mut self, _value: T) -> Result<(), Error>
where T: serde::Serialize
fn serialize_newtype_variant<V>(&mut self, _: &'static str, _: usize, _: &'static str, _value: V) -> Result<(), Error>
where V: Serialize,
{
Err(Error)
}
fn serialize_map<V>(&mut self, _visitor: V) -> Result<(), Error>
where V: serde::ser::MapVisitor,
fn serialize_seq(&mut self, _len: Option<usize>) -> Result<(), Error>
{
Err(Error)
}
fn serialize_map_elt<K, V>(&mut self, _key: K, _value: V) -> Result<(), Error>
where K: serde::Serialize,
V: serde::Serialize,
fn serialize_seq_fixed_size(&mut self, _len: usize) -> Result<(), Error>
{
Err(Error)
}
fn serialize_seq_elt<T>(&mut self, _: &mut (), _value: T) -> Result<(), Error>
where T: Serialize
{
Err(Error)
}
fn serialize_seq_end(&mut self, _: ()) -> Result<(), Error>
{
Err(Error)
}
fn serialize_tuple(&mut self, _len: usize) -> Result<(), Error>
{
Err(Error)
}
fn serialize_tuple_elt<T>(&mut self, _: &mut (), _value: T) -> Result<(), Error>
where T: Serialize
{
Err(Error)
}
fn serialize_tuple_end(&mut self, _: ()) -> Result<(), Error>
{
Err(Error)
}
fn serialize_tuple_struct(&mut self, _: &'static str, _len: usize) -> Result<(), Error>
{
Err(Error)
}
fn serialize_tuple_struct_elt<T>(&mut self, _: &mut (), _value: T) -> Result<(), Error>
where T: Serialize
{
Err(Error)
}
fn serialize_tuple_struct_end(&mut self, _: ()) -> Result<(), Error>
{
Err(Error)
}
fn serialize_tuple_variant(&mut self, _: &'static str, _: usize, _: &'static str, _len: usize) -> Result<(), Error>
{
Err(Error)
}
fn serialize_tuple_variant_elt<T>(&mut self, _: &mut (), _value: T) -> Result<(), Error>
where T: Serialize
{
Err(Error)
}
fn serialize_tuple_variant_end(&mut self, _: ()) -> Result<(), Error>
{
Err(Error)
}
fn serialize_map(&mut self, _: Option<usize>) -> Result<(), Error>
{
Err(Error)
}
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)
}
fn serialize_map_end(&mut self, _: ()) -> Result<(), Error>
{
Err(Error)
}
fn serialize_struct(&mut self, _: &'static str, _: usize) -> Result<(), Error>
{
Err(Error)
}
fn serialize_struct_elt<V>(&mut self, _: &mut (), _key: &'static str, _value: V) -> Result<(), Error>
where V: Serialize,
{
Err(Error)
}
fn serialize_struct_end(&mut self, _: ()) -> Result<(), Error>
{
Err(Error)
}
fn serialize_struct_variant(&mut self, _: &'static str, _: usize, _: &'static str, _: usize) -> Result<(), Error>
{
Err(Error)
}
fn serialize_struct_variant_elt<V>(&mut self, _: &mut (), _key: &'static str, _value: V) -> Result<(), Error>
where V: Serialize,
{
Err(Error)
}
fn serialize_struct_variant_end(&mut self, _: ()) -> Result<(), Error>
{
Err(Error)
}
@@ -140,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)
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -176,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])));
}
+45 -23
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;
@@ -81,9 +81,9 @@ fn assert_de_tokens_ignore(ignorable_tokens: &[Token<'static>]) {
struct IgnoreBase {
a: i32,
}
let expected = IgnoreBase{a: 1};
// Embed the tokens to be ignored in the normal token
// stream for an IgnoreBase type
let concated_tokens : Vec<Token<'static>> = vec![
@@ -91,7 +91,7 @@ fn assert_de_tokens_ignore(ignorable_tokens: &[Token<'static>]) {
Token::MapSep,
Token::Str("a"),
Token::I32(1),
Token::MapSep,
Token::Str("ignored")
]
@@ -101,17 +101,17 @@ fn assert_de_tokens_ignore(ignorable_tokens: &[Token<'static>]) {
Token::MapEnd,
].into_iter())
.collect();
let mut de = serde_test::Deserializer::new(concated_tokens.into_iter());
let v: Result<IgnoreBase, Error> = Deserialize::deserialize(&mut de);
// We run this test on every token stream for convenience, but
// some token streams don't make sense embedded as a map value,
// so we ignore those. SyntaxError is the real sign of trouble.
if let Err(Error::UnexpectedToken(_)) = v {
return;
}
assert_eq!(v.as_ref(), Ok(&expected));
assert_eq!(de.next_token(), None);
}
@@ -197,7 +197,7 @@ declare_tests! {
Token::SeqEnd,
],
() => &[
Token::TupleStructStart("Anything", Some(0)),
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
],
}
@@ -241,7 +241,7 @@ declare_tests! {
Token::SeqEnd,
],
TupleStruct(1, 2, 3) => &[
Token::TupleStructStart("TupleStruct", Some(3)),
Token::TupleStructStart("TupleStruct", 3),
Token::TupleStructSep,
Token::I32(1),
@@ -253,7 +253,7 @@ declare_tests! {
Token::TupleStructEnd,
],
TupleStruct(1, 2, 3) => &[
Token::TupleStructStart("TupleStruct", None),
Token::TupleStructStart("TupleStruct", 3),
Token::TupleStructSep,
Token::I32(1),
@@ -299,7 +299,7 @@ declare_tests! {
Token::UnitStruct("Anything"),
],
BTreeSet::<isize>::new() => &[
Token::TupleStructStart("Anything", Some(0)),
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
],
}
@@ -327,7 +327,7 @@ declare_tests! {
Token::UnitStruct("Anything"),
],
HashSet::<isize>::new() => &[
Token::TupleStructStart("Anything", Some(0)),
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
],
hashset![FnvHasher @ 1, 2, 3] => &[
@@ -377,7 +377,7 @@ declare_tests! {
Token::UnitStruct("Anything"),
],
Vec::<isize>::new() => &[
Token::TupleStructStart("Anything", Some(0)),
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
],
}
@@ -441,7 +441,7 @@ declare_tests! {
Token::UnitStruct("Anything"),
],
[0; 0] => &[
Token::TupleStructStart("Anything", Some(0)),
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
],
}
@@ -533,7 +533,7 @@ declare_tests! {
Token::UnitStruct("Anything"),
],
BTreeMap::<isize, isize>::new() => &[
Token::StructStart("Anything", Some(0)),
Token::StructStart("Anything", 0),
Token::MapEnd,
],
}
@@ -587,7 +587,7 @@ declare_tests! {
Token::UnitStruct("Anything"),
],
HashMap::<isize, isize>::new() => &[
Token::StructStart("Anything", Some(0)),
Token::StructStart("Anything", 0),
Token::MapEnd,
],
hashmap![FnvHasher @ 1 => 2, 3 => 4] => &[
@@ -615,7 +615,7 @@ declare_tests! {
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::StructStart("Struct", Some(3)),
Token::StructStart("Struct", 3),
Token::StructSep,
Token::Str("a"),
Token::I32(1),
@@ -656,7 +656,7 @@ declare_tests! {
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::StructStart("Struct", Some(3)),
Token::StructStart("Struct", 3),
Token::StructSep,
Token::Str("a"),
Token::I32(1),
@@ -688,7 +688,7 @@ declare_tests! {
}
test_enum_seq {
Enum::Seq(1, 2, 3) => &[
Token::EnumSeqStart("Enum", "Seq", Some(3)),
Token::EnumSeqStart("Enum", "Seq", 3),
Token::EnumSeqSep,
Token::I32(1),
@@ -702,7 +702,7 @@ declare_tests! {
}
test_enum_map {
Enum::Map { a: 1, b: 2, c: 3 } => &[
Token::EnumMapStart("Enum", "Map", Some(3)),
Token::EnumMapStart("Enum", "Map", 3),
Token::EnumMapSep,
Token::Str("a"),
Token::I32(1),
@@ -746,6 +746,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")],
}
@@ -764,7 +786,7 @@ declare_tests! {
}
}
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
#[test]
fn test_net_ipaddr() {
assert_de_tokens(
@@ -803,7 +825,7 @@ declare_error_tests! {
}
test_duplicate_field_enum<Enum> {
&[
Token::EnumMapStart("Enum", "Map", Some(3)),
Token::EnumMapStart("Enum", "Map", 3),
Token::EnumMapSep,
Token::Str("a"),
Token::I32(1),
+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!()
}
}
+60 -67
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,
},
}
@@ -174,7 +158,7 @@ fn test_ser_named_tuple() {
assert_ser_tokens(
&SerNamedTuple(&a, &mut b, c),
&[
Token::TupleStructStart("SerNamedTuple", Some(3)),
Token::TupleStructStart("SerNamedTuple", 3),
Token::TupleStructSep,
Token::I32(5),
@@ -211,7 +195,7 @@ fn test_de_named_tuple() {
assert_de_tokens(
&DeNamedTuple(5, 6, 7),
&[
Token::TupleStructStart("DeNamedTuple", Some(3)),
Token::TupleStructStart("DeNamedTuple", 3),
Token::TupleStructSep,
Token::I32(5),
@@ -239,7 +223,7 @@ fn test_ser_named_map() {
c: c,
},
&[
Token::StructStart("SerNamedMap", Some(3)),
Token::StructStart("SerNamedMap", 3),
Token::StructSep,
Token::Str("a"),
@@ -267,7 +251,7 @@ fn test_de_named_map() {
c: 7,
},
&[
Token::StructStart("DeNamedMap", Some(3)),
Token::StructStart("DeNamedMap", 3),
Token::StructSep,
Token::Str("a"),
@@ -301,21 +285,17 @@ 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", Some(4)),
Token::EnumSeqStart("SerEnum", "Seq", 4),
Token::EnumSeqSep,
Token::I8(1),
@@ -327,7 +307,7 @@ fn test_ser_enum_seq() {
Token::I32(3),
Token::EnumSeqSep,
Token::I32(5),
Token::I32(4),
Token::EnumSeqEnd,
],
@@ -339,21 +319,17 @@ 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", Some(4)),
Token::EnumMapStart("SerEnum", "Map", 4),
Token::EnumMapSep,
Token::Str("a"),
@@ -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,21 +367,17 @@ 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", Some(4)),
Token::EnumSeqStart("DeEnum", "Seq", 4),
Token::EnumSeqSep,
Token::I8(1),
@@ -417,7 +389,7 @@ fn test_de_enum_seq() {
Token::I32(3),
Token::EnumSeqSep,
Token::I32(5),
Token::I32(4),
Token::EnumSeqEnd,
],
@@ -429,21 +401,17 @@ 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", Some(4)),
Token::EnumMapStart("DeEnum", "Map", 4),
Token::EnumMapSep,
Token::Str("a"),
@@ -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,
],
@@ -489,7 +457,7 @@ fn test_lifetimes() {
assert_ser_tokens(
&Lifetimes::LifetimeMap { a: &value },
&[
Token::EnumMapStart("Lifetimes", "LifetimeMap", Some(1)),
Token::EnumMapStart("Lifetimes", "LifetimeMap", 1),
Token::EnumMapSep,
Token::Str("a"),
@@ -502,7 +470,7 @@ fn test_lifetimes() {
assert_ser_tokens(
&Lifetimes::NoLifetimeMap { a: 5 },
&[
Token::EnumMapStart("Lifetimes", "NoLifetimeMap", Some(1)),
Token::EnumMapStart("Lifetimes", "NoLifetimeMap", 1),
Token::EnumMapSep,
Token::Str("a"),
@@ -518,7 +486,7 @@ fn test_generic_struct() {
assert_tokens(
&GenericStruct { x: 5u32 },
&[
Token::StructStart("GenericStruct", Some(1)),
Token::StructStart("GenericStruct", 1),
Token::StructSep,
Token::Str("x"),
@@ -545,7 +513,7 @@ fn test_generic_tuple_struct() {
assert_tokens(
&GenericTupleStruct(5u32, 6u32),
&[
Token::TupleStructStart("GenericTupleStruct", Some(2)),
Token::TupleStructStart("GenericTupleStruct", 2),
Token::TupleStructSep,
Token::U32(5),
@@ -584,7 +552,7 @@ fn test_generic_enum_seq() {
assert_tokens(
&GenericEnum::Seq::<u32, u32>(5, 6),
&[
Token::EnumSeqStart("GenericEnum", "Seq", Some(2)),
Token::EnumSeqStart("GenericEnum", "Seq", 2),
Token::EnumSeqSep,
Token::U32(5),
@@ -602,7 +570,7 @@ fn test_generic_enum_map() {
assert_tokens(
&GenericEnum::Map::<u32, u32> { x: 5, y: 6 },
&[
Token::EnumMapStart("GenericEnum", "Map", Some(2)),
Token::EnumMapStart("GenericEnum", "Map", 2),
Token::EnumMapSep,
Token::Str("x"),
@@ -622,7 +590,7 @@ fn test_default_ty_param() {
assert_tokens(
&DefaultTyParam::<i32> { phantom: PhantomData },
&[
Token::StructStart("DefaultTyParam", Some(1)),
Token::StructStart("DefaultTyParam", 1),
Token::StructSep,
Token::Str("phantom"),
@@ -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,
]
);
}
+19 -5
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::{
@@ -256,7 +257,7 @@ declare_ser_tests! {
}
test_tuple_struct {
TupleStruct(1, 2, 3) => &[
Token::TupleStructStart("TupleStruct", Some(3)),
Token::TupleStructStart("TupleStruct", 3),
Token::TupleStructSep,
Token::I32(1),
@@ -270,7 +271,7 @@ declare_ser_tests! {
}
test_struct {
Struct { a: 1, b: 2, c: 3 } => &[
Token::StructStart("Struct", Some(3)),
Token::StructStart("Struct", 3),
Token::StructSep,
Token::Str("a"),
Token::I32(1),
@@ -289,7 +290,7 @@ declare_ser_tests! {
Enum::Unit => &[Token::EnumUnit("Enum", "Unit")],
Enum::One(42) => &[Token::EnumNewType("Enum", "One"), Token::I32(42)],
Enum::Seq(1, 2) => &[
Token::EnumSeqStart("Enum", "Seq", Some(2)),
Token::EnumSeqStart("Enum", "Seq", 2),
Token::EnumSeqSep,
Token::I32(1),
@@ -298,7 +299,7 @@ declare_ser_tests! {
Token::EnumSeqEnd,
],
Enum::Map { a: 1, b: 2 } => &[
Token::EnumMapStart("Enum", "Map", Some(2)),
Token::EnumMapStart("Enum", "Map", 2),
Token::EnumMapSep,
Token::Str("a"),
Token::I32(1),
@@ -324,6 +325,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")],
}
@@ -347,7 +361,7 @@ declare_ser_tests! {
}
}
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
#[test]
fn test_net_ipaddr() {
assert_ser_tokens(