Compare commits

...

406 Commits

Author SHA1 Message Date
David Tolnay 59e48997dd Release 0.9.0-rc4 2017-01-25 10:14:43 -08:00
Oliver Schneider ffcd97834f Merge pull request #721 from serde-rs/size
Remove usize and isize from data model
2017-01-25 19:08:02 +01:00
David Tolnay e0c049dbf2 Remove usize and isize from data model 2017-01-25 09:08:06 -08:00
David Tolnay 8cb6607e82 Merge pull request #719 from serde-rs/rustdoc
Serde rustdoc
2017-01-24 20:59:26 -08:00
David Tolnay 1ffb0570b6 Do not require rustdoc tests to run on stable 2017-01-24 20:47:31 -08:00
David Tolnay 2c1dd60575 Serde rustdoc 2017-01-24 20:37:11 -08:00
David Tolnay 24f849da2d Remove unused #[macro_use]
I think this was for the quasi-quoting macros back in the day.
2017-01-24 09:28:00 -08:00
David Tolnay a5024a4238 Merge pull request #717 from serde-rs/badger
add travis badge to crates.io
2017-01-24 05:35:55 -08:00
Oliver Schneider b105423e5e add travis badge to crates.io 2017-01-24 10:30:10 +01:00
Oliver Schneider 42c1bc2907 Merge pull request #716 from serde-rs/ref
Serialize T by ref
2017-01-24 08:31:24 +01:00
David Tolnay c334c1c7b5 Release 0.9.0-rc3 2017-01-23 19:14:02 -08:00
David Tolnay 92668d7061 Serialize T by ref 2017-01-23 17:11:18 -08:00
David Tolnay b9d865d8e7 Merge pull request #715 from serde-rs/nostd
Support serde_derive on no_std
2017-01-23 16:13:25 -08:00
David Tolnay fc4e370ba9 Support serde_derive on no_std 2017-01-23 16:03:06 -08:00
Oliver Schneider a982d27536 Merge pull request #700 from serde-rs/usize
Restore visit_usize and visit_bytes for identifying variants
2017-01-23 11:27:06 +01:00
Oliver Schneider dc87826298 Merge pull request #699 from serde-rs/fields
Remove visit_usize from Duration impl
2017-01-23 11:26:18 +01:00
David Tolnay a09a8a039a All combinations of features compile without warnings 2017-01-23 01:45:54 -08:00
David Tolnay ea702755a2 Merge branch master into origin/usize
Conflicts:
    serde_codegen/src/de.rs
    testing/tests/test_de.rs
2017-01-23 01:36:49 -08:00
David Tolnay d161911c63 Merge branch master into origin/fields
Conflicts:
    serde/src/de/impls.rs
2017-01-23 01:28:01 -08:00
Oliver Schneider e27553d3df Merge pull request #710 from serde-rs/errors
Errors redesign
2017-01-23 10:25:48 +01:00
David Tolnay 48eaf988bc Add free-form option for Unexpected 2017-01-22 05:02:24 -08:00
David Tolnay 73a364d4fd Capture byte value for error message 2017-01-22 04:57:12 -08:00
David Tolnay 6dfdcb6ba1 Merge pull request #713 from serde-rs/zero
Suppress warning about using num::Zero
2017-01-21 19:20:57 -08:00
David Tolnay 089c7eb1d7 Suppress warning about using num::Zero 2017-01-21 19:14:56 -08:00
David Tolnay 1e05fc2145 Release 0.9.0-rc2 2017-01-21 16:30:13 -08:00
David Tolnay 977612d8dd Merge branch origin/missing into origin/errors 2017-01-21 16:28:24 -08:00
David Tolnay 5855078703 Fix backward invalid_length messages in value deserializer 2017-01-21 14:38:33 -08:00
David Tolnay 3c88a93fb2 Fix the filtered error messages 2017-01-21 12:34:04 -08:00
David Tolnay 530c29466e Merge pull request #711 from serde-rs/names
Filter the slice of expected field and variant names
2017-01-21 12:25:43 -08:00
David Tolnay ea99e8b686 Filter the slice of expected field and variant names 2017-01-21 12:18:55 -08:00
David Tolnay 2a148112d4 Fix Box<str> use on no_std 2017-01-21 10:17:48 -08:00
David Tolnay a4126e4c5a Errors 2017-01-21 09:13:01 -08:00
David Tolnay d1325862f7 Merge tag v0.8.23 into master
Conflicts:
    serde/Cargo.toml
    serde_codegen/Cargo.toml
    serde_derive/Cargo.toml
    serde_test/Cargo.toml
    testing/Cargo.toml
2017-01-20 15:29:32 -08:00
David Tolnay 1f65ce75ec Release 0.8.23 2017-01-20 15:25:57 -08:00
Jake Goulding 9536e52aa6 Add categories to Cargo.toml 2017-01-20 15:09:11 -08:00
Oliver Schneider be0c755731 Merge pull request #705 from serde-rs/inlineseed
Inline <PhantomData<T> as DeserializeSeed>::deserialize
2017-01-20 14:34:24 +01:00
David Tolnay 42bc63bed8 Standardize behavior of missing fields 2017-01-20 00:44:43 -08:00
David Tolnay e41b940a3d Inline <PhantomData<T> as DeserializeSeed>::deserialize 2017-01-19 16:17:27 -08:00
David Tolnay 88149fc0c3 Fix key and value seed variable names
Rename fail.
2017-01-19 13:44:18 -08:00
David Tolnay 5ecfb3b388 Update serde_test to use seeds 2017-01-19 01:24:33 -08:00
David Tolnay 13a9f929de Stateful deserialization 2017-01-19 01:17:59 -08:00
David Tolnay e40fbe0767 Restore visit_bytes for Duration impl 2017-01-18 21:13:51 -08:00
David Tolnay 0a10116bf5 Restore visit_bytes for identifying variants and fields 2017-01-18 21:11:51 -08:00
David Tolnay b1fbbfd3ce Restore visit_usize for identifying variants 2017-01-17 23:52:06 -08:00
David Tolnay 984ebcead0 Remove visit_usize and visit_bytes for Duration impl 2017-01-17 23:32:28 -08:00
David Tolnay aa88f01cdc Merge pull request #697 from serde-rs/vanity
cleanup some deprecation warnings
2017-01-17 09:26:44 -08:00
David Tolnay 13794c1b48 Stop testing on rust 1.12.0 2017-01-17 09:19:39 -08:00
Oliver Schneider b5e64abba1 cleanup some deprecation warnings 2017-01-17 14:29:33 +01:00
David Tolnay 503ce310f5 Merge pull request #692 from serde-rs/byte_buf
add missing `Vec<u8>` deserialization hint to `Deserializer`
2017-01-16 08:10:25 -08:00
Oliver Schneider b26f291d93 add missing Vec<u8> deserialization hint to Deserializer 2017-01-16 16:55:13 +01:00
David Tolnay bc6bc9e3f0 Remove LICENSE file in favor of LICENSE-MIT and LICENSE-APACHE
This repo no longer contains bench_log referenced in this file.
2017-01-15 10:16:57 -08:00
David Tolnay 3a52364f3e Release 0.9.0-rc1 2017-01-15 09:26:44 -08:00
David Tolnay 4d1627fc96 Merge pull request #687 from serde-rs/ser
Enforce correct use of Serialize trait
2017-01-15 09:22:30 -08:00
David Tolnay 7c04bf36d9 Merge pull request #686 from serde-rs/de
Enforce correct use of Deserialize trait
2017-01-15 07:30:14 -08:00
David Tolnay 4b06030666 Unabbreviated method naming 2017-01-14 21:39:37 -08:00
David Tolnay a5a04306f2 Update tests for Serializer changes 2017-01-14 16:07:43 -08:00
David Tolnay f9885c4826 Update serde_codegen for Serializer changes 2017-01-14 16:07:34 -08:00
David Tolnay 04f25eb122 Update serde_test for Serializer changes 2017-01-14 16:07:17 -08:00
David Tolnay 2fea5f3e1c Enforce correct use of Serialize trait 2017-01-14 15:21:31 -08:00
David Tolnay 905b2c3cf3 Expose VariantVisitor for the StrDeserializer 2017-01-14 14:17:46 -08:00
David Tolnay d5b428a087 Fix imports for stable compiler 2017-01-14 14:16:01 -08:00
David Tolnay b3b8056d93 Update tests for Deserializer changes 2017-01-14 13:42:49 -08:00
David Tolnay 137cf9bab8 Update serde_codegen for Deserializer changes 2017-01-14 13:42:48 -08:00
David Tolnay 7372f152bd Update serde_test for Deserializer changes 2017-01-14 13:42:45 -08:00
David Tolnay a43da15b74 Merge pull request #685 from mineo/patch-1
Typo: aggrergate -> aggregate
2017-01-14 13:36:49 -08:00
Wieland Hoffmann 212cbbd8bf Typo: aggrergate -> aggregate 2017-01-14 22:33:31 +01:00
David Tolnay 738aa31733 Enforce correct use of Deserialize trait 2017-01-14 12:16:08 -08:00
Oliver Schneider 787ecc6a82 Merge pull request #684 from serde-rs/end
Remove SeqVisitor::end() and MapVisitor::end()
2017-01-14 08:01:53 +01:00
David Tolnay 9fc8a86bcc Exclude serde-syntex-example until serde_json has been updated 2017-01-13 13:34:41 -08:00
David Tolnay 800442a75e Handle visitor that does not need to be mutable 2017-01-13 13:34:39 -08:00
David Tolnay 88debb3fb8 Remove SeqVisitor::end() and MapVisitor::end() 2017-01-13 13:34:38 -08:00
David Tolnay 88a4ed9cd7 Include missing_field in impl MapVisitor for &mut MapVisitor 2017-01-13 13:33:37 -08:00
David Tolnay bdba6fc5b0 Remove the proc_macro feature gate in serde-syntex-example 2017-01-13 10:27:51 -08:00
Oliver Schneider dec116311e Merge pull request #682 from serde-rs/unknown
Treat skipped fields as unknown
2017-01-13 10:46:18 +01:00
David Tolnay 8c49e6d6a5 Resolve conflict between rename changes and skip changes 2017-01-13 01:27:07 -08:00
David Tolnay 7cc24a43fb Merge branch master into unknown
Conflicts:
    serde_codegen/src/de.rs
2017-01-13 01:23:00 -08:00
David Tolnay c008c6d3a8 Merge pull request #681 from serde-rs/deserialize_struct_bug
fix various serde(rename) bugs
2017-01-13 01:21:46 -08:00
David Tolnay c9f5d08ed1 Add test for all variants skipped 2017-01-13 01:14:03 -08:00
David Tolnay fff6c9cb66 Add tests for all fields skipped 2017-01-13 01:12:31 -08:00
David Tolnay cb5e7c6264 Fix case of skipped variant followed by other variants 2017-01-12 23:35:39 -08:00
David Tolnay 4ef1128546 More explicit about argument to deserialize_field_visitor 2017-01-12 23:30:57 -08:00
David Tolnay 227bea1d0b Treat skipped fields as unknown 2017-01-12 23:17:45 -08:00
David Tolnay 766ede965e Eliminate collects in codegen for deserializing map 2017-01-12 21:52:56 -08:00
David Tolnay eb5a49e380 Use helper function to build __field{} 2017-01-12 21:49:20 -08:00
David Tolnay 2df529cac5 Simplify codegen logic in deserializing seq 2017-01-12 21:41:27 -08:00
David Tolnay 4b66463011 Eliminate collect in deserializing seq 2017-01-12 21:29:50 -08:00
David Tolnay b907cfef85 Eliminate collect in visitor generics 2017-01-12 21:28:09 -08:00
David Tolnay 506c8cc087 Simplify the trait paths used in bounds 2017-01-12 21:24:51 -08:00
David Tolnay 3951ef91c0 Don't need aster to construct syn::Ident 2017-01-12 21:15:13 -08:00
David Tolnay b0d20afdfb Merge pull request #680 from serde-rs/oli-obk-patch-1
make `ser::iterator` more general by taking `IntoIterator`
2017-01-12 16:45:39 -08:00
Oliver Schneider 5e6ee523d2 remove duplicate into_iter 2017-01-12 21:52:38 +01:00
Oliver Schneider a07b6bd9e7 also use the renamed variant names during deserialization 2017-01-12 20:21:59 +01:00
Oliver Schneider 8dd06eed2f type inference failure 2017-01-12 20:19:00 +01:00
Oliver Schneider 5b668ed87a attempt to test the field names, but deem it too complex and opt to at least improve the code 2017-01-12 20:17:55 +01:00
Oliver Schneider abe305dbfe fix deserialize_struct passing the original field names instead of the renamed ones 2017-01-12 20:17:02 +01:00
Oliver Schneider 2d1a60c056 Update the Serialize impl, too 2017-01-12 20:06:44 +01:00
Oliver Schneider 5edfdba940 use IntoIterator everywhere 2017-01-12 20:05:26 +01:00
Oliver Schneider 756bff534f make ser::iterator more general by taking IntoIterator 2017-01-12 19:24:35 +01:00
David Tolnay 110d36fa14 Merge pull request #679 from oli-obk/iterators
add wrapper to serde that allows serializing iterators as sequences
2017-01-12 10:19:09 -08:00
Oliver Schneider 8c576fe9fb rename IteratorSerializer to Iterator 2017-01-12 17:29:04 +01:00
Oliver Schneider b860d3cb1f fix tests on stable 2017-01-12 16:06:26 +01:00
Oliver Schneider dced4416a7 add wrapper to serde that allows serializing iterators as sequences 2017-01-12 15:31:40 +01:00
David Tolnay ca47eb929c Merge pull request #678 from serde-rs/empty
Handle various degenerate cases
2017-01-11 11:45:24 -08:00
David Tolnay b01c23b5ee Also provide a smarter alternative for the other impossible case 2017-01-11 11:34:47 -08:00
David Tolnay 3aaf29c846 Remove ref in top-level let pattern
Discouraged by Clippy.
2017-01-11 11:12:53 -08:00
David Tolnay d2eea87001 Handle various degenerate cases 2017-01-11 11:02:24 -08:00
David Tolnay 8242c64152 Merge branch v0.8 into master 2017-01-10 17:16:31 -08:00
David Tolnay 9e45bd8c87 Release 0.8.22 2017-01-10 17:10:26 -08:00
Oliver Schneider 405b534254 Merge pull request #674 from serde-rs/nonascii
Add test for non ascii idents
2017-01-10 11:16:19 +01:00
David Tolnay d34be74dfd Add test for non ascii idents 2017-01-10 01:20:01 -08:00
David Tolnay c475df8320 Encourage GitHub issues 2017-01-09 14:44:36 -08:00
Oliver Schneider 2b8a620807 Merge pull request #671 from serde-rs/fields
Stop generating visit_usize and visit_bytes for FieldVisitor
2017-01-09 13:09:18 +01:00
David Tolnay 1cd6aee562 Merge pull request #670 from serde-rs/error
Stop exporting serde::de::Error as serde::Error
2017-01-09 00:45:04 -08:00
David Tolnay 90d4d7b37b Restore the old FieldVisitor tests as error tests 2017-01-09 00:43:13 -08:00
David Tolnay 1f8b803607 Repetition for field visitor arms 2017-01-09 00:37:37 -08:00
David Tolnay 516cc8b04e Stop generating visit_usize and visit_bytes for FieldVisitor 2017-01-08 01:01:56 -08:00
David Tolnay 0676477cd7 Stop exporting serde::de::Error as serde::Error 2017-01-08 00:50:07 -08:00
David Tolnay 4193122472 Use the more concise paths in generated code 2017-01-08 00:47:44 -08:00
David Tolnay eb6fb1d40e Merge pull request #523 from serde-rs/enum
Enum deserialization API
2017-01-08 00:45:50 -08:00
David Tolnay bf873a7b3f Merge branch origin/master into origin/enum
Conflicts:
    serde/src/de/mod.rs
    serde_codegen/src/de.rs
    testing/tests/test_bytes.rs
2017-01-08 00:31:07 -08:00
David Tolnay fbd4a17467 Merge pull request #664 from serde-rs/visitor-value
Remove the Deserialize trait bound on Visitor::Value
2017-01-08 00:24:53 -08:00
David Tolnay ad34c14c8c Prepare for 0.9 breaking changes 2017-01-08 00:18:53 -08:00
David Tolnay e461a23798 Not intended to be published 2017-01-08 00:18:37 -08:00
David Tolnay 894a21bc1f Remove the proc_macro feature gate 2017-01-08 00:11:11 -08:00
David Tolnay 1ecf3730ee Update to syntex 0.54 2017-01-06 01:26:51 -08:00
David Tolnay 7a0e8f73b4 Remove the Deserialize trait bound on Visitor::Value 2017-01-03 01:50:10 -08:00
Erick Tryzelaar b6e8b58cb2 Stop testing on 1.11 2017-01-02 14:59:00 -08:00
Oliver Schneider a3f556959f Merge pull request #652 from serde-rs/bbstr
Support deserializing ByteBuf from string
2016-12-25 01:09:15 +01:00
David Tolnay 9338c4f1b9 Release 0.8.21 2016-12-24 13:10:24 -05:00
David Tolnay 28d67f4172 Format variant-skip message only if variant is skipped 2016-12-24 13:10:06 -05:00
David Tolnay 2401ae61a8 Update to syntex 0.52 2016-12-24 12:42:23 -05:00
David Tolnay 57d3fce0c6 Further simplify variant serialization patterns 2016-12-24 12:28:46 -05:00
David Tolnay a020cceed8 Simplify variant serialize patterns 2016-12-24 12:22:45 -05:00
David Tolnay 49e985eb90 Update message for skipped enum variant 2016-12-24 12:16:28 -05:00
David Tolnay 63def96c66 Merge pull request #653 from shinglyu/skip_se
Implement skip_serializing for enum variant
2016-12-24 11:40:21 -05:00
Shing Lyu 2fea8c9c28 Implement skip_serializing for enum variant 2016-12-24 22:34:22 +08:00
David Tolnay b7ea213926 Support nostd for ByteBuf from String 2016-12-23 23:30:27 -05:00
David Tolnay 871fb5adee Support deserializing ByteBuf from string 2016-12-23 23:17:42 -05:00
David Tolnay 2c984980a0 Link to release notes from readme 2016-12-22 21:52:37 -05:00
David Tolnay 36f07912b8 Remove no-longer-necessary cfg
This was fixed in Rust, allowing proc macro crates to be tested.
2016-12-17 17:32:11 -08:00
David Tolnay 7222cf7514 Ignore warning from unused enum variant 2016-12-17 17:31:11 -08:00
David Tolnay 08c59a2e0e Release 0.8.20 2016-12-16 07:58:52 -08:00
David Tolnay 4a0bf4de65 Merge pull request #641 from shinglyu/deser_enum
Implemented skip_deserializing for enum
2016-12-16 07:53:34 -08:00
Shing Lyu 95ffca9bbe Implemented skip_deserializing for enum 2016-12-16 20:29:21 +08:00
David Tolnay 5e47c87ba0 Add test for deserializing unit to string 2016-12-01 04:46:29 -08:00
David Tolnay c6d5d9be14 Merge pull request #635 from serde-rs/oli-obk-patch-1
Enable deserializing an empty `String` from a unit value
2016-12-01 07:46:07 -05:00
Oliver Schneider d63d09f4db Enable deserializing an empty String from a unit value 2016-12-01 11:23:12 +01:00
David Tolnay de6d00c306 Merge pull request #628 from serde-rs/str
Do not copy tokens to String after expanding
2016-11-24 17:33:19 -05:00
David Tolnay 5bda95ba81 Do not copy tokens to String after expanding 2016-11-24 13:07:47 -08:00
David Tolnay 36641e7b81 Release 0.8.19 2016-11-23 09:14:03 -08:00
David Tolnay 6eca34c45c Drop libsyntax 2016-11-23 09:13:21 -08:00
David Tolnay 7efa0153b0 Drop testing on rust 1.10 2016-11-19 15:24:40 -08:00
David Tolnay 8dba87661b Bump serde_codegen_internals because it failed to publish somehow 2016-11-19 11:47:19 -08:00
David Tolnay 17fb4cb503 Release 0.8.18 2016-11-19 11:40:00 -08:00
David Tolnay 5bd0386b8e Merge pull request #618 from serde-rs/up
Ask proc_macro_derive to ignore serde attributes
2016-11-19 14:19:15 -05:00
David Tolnay 8b484c9703 Hide the serde_codegen functions from docs 2016-11-15 21:37:19 -05:00
David Tolnay a16f07858b Ask proc_macro_derive to ignore serde attributes 2016-11-15 21:29:34 -05:00
David Tolnay 133d117bf4 Bump post-expansion dependency 2016-11-07 11:16:14 -08:00
David Tolnay e7f3a80867 Update serde codegen to syn 0.10 2016-11-02 22:58:55 -07:00
David Tolnay f8c3d225a3 Shorten the syn meta item matches 2016-11-02 22:56:27 -07:00
David Tolnay 6d40d9e8ec Update codegen internals to syn 0.10 2016-11-02 22:52:20 -07:00
David Tolnay c91fca19e1 Release 0.8.17 2016-11-02 09:26:04 -07:00
David Tolnay f13a805530 Merge pull request #605 from serde-rs/up
Bump syntex to 0.48
2016-11-02 09:24:55 -07:00
David Tolnay 54802983b8 Bump syntex to 0.48 2016-11-02 09:12:22 -07:00
David Tolnay f430d9d1c8 Remove unneeded type ascription 2016-10-23 21:06:50 -07:00
David Tolnay c9612a2f57 Release 0.8.16 2016-10-22 00:07:27 -07:00
David Tolnay 7ffea5a716 Bump syntex to 0.46 2016-10-21 23:38:27 -07:00
David Tolnay c8c9f7d96c Merge pull request #599 from TheCatPlusPlus/master
Explictly discard result of visiting IgnoredAny
2016-10-21 23:36:57 -07:00
Cat Plus Plus f75d286b90 Explictly discard result of visiting IgnoredAny
Makes the code generated by `derive(Deserialize)` compile cleanly when
`unused_results` lint is enabled.
2016-10-22 08:00:44 +02:00
David Tolnay 9acb17ab54 Release 0.8.15 2016-10-20 08:42:40 -07:00
David Tolnay f15ff1868e Merge pull request #597 from serde-rs/cov
Drop coveralls
2016-10-20 00:44:19 -07:00
David Tolnay 86f0d0382f Drop coveralls
Has not been uploading for months.
2016-10-20 00:33:03 -07:00
David Tolnay 8595b25763 Merge pull request #592 from serde-rs/post
Use post-expansion crate to let other custom derives see serde attrs
2016-10-20 00:18:23 -07:00
David Tolnay 49aca521f1 Bump post-expansion dependency 2016-10-20 00:01:14 -07:00
David Tolnay 4c38bd0180 Merge branch origin/master into origin/post 2016-10-19 23:59:53 -07:00
Homu 02c4ff7b7e Auto merge of #594 - serde-rs:expr, r=oli-obk
No longer need `e!`

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

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

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

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

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

Without this:

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

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

Fixes #534.

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

Fixes #522.

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

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

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

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

I don't think this negatively affects maintainability of the code in serde_codegen and I think there is some value in keeping our generated code relatively clear so that people can use it as a template when implementing Serialize manually with minor modifications.
2016-09-05 19:52:43 +09:00
David Tolnay d1ce4d62c9 Change to expression so that syntex keeps the semicolon 2016-09-02 18:07:26 -07:00
David Tolnay 869ebd9e4e Remove if !false { ... } from generated serialization code 2016-09-02 17:22:58 -07:00
David Tolnay 14446af537 Fix "variable does not need to be mutable" warning 2016-09-02 11:42:33 -07:00
David Tolnay 248d937f9a Release 0.8.6 2016-09-01 22:06:27 -07:00
David Tolnay ffa2f80186 Merge pull request #530 from serde-rs/derive
Macros 1.1
2016-09-01 21:59:32 -07:00
David Tolnay ac1128a647 Update serde_derive to 0.8.5 2016-09-01 21:28:58 -07:00
David Tolnay 88d845c4d1 Include! test suite for serde_derive 2016-09-01 21:28:40 -07:00
David Tolnay 87a402a751 Remove rustc_macro test crate 2016-09-01 11:17:35 -07:00
David Tolnay cdb0e6c899 Remove build script in favor of rust-lang/cargo#3064 2016-08-31 21:05:40 -07:00
David Tolnay 54cee86fd3 Bump to 0.8.5 2016-08-31 20:14:44 -07:00
David Tolnay 178edd1abc Merge branch origin/master into origin/derive 2016-08-31 20:12:46 -07:00
David Tolnay 4bb9279074 Bump syntex to 0.43 2016-08-31 12:53:27 -07:00
David Tolnay 3c45e5c7a5 Next iteration 2016-08-30 23:55:08 -07:00
David Tolnay d36f28971c Support no_std in forward_to_deserialize macro 2016-08-29 00:27:11 -07:00
David Tolnay d914fdf67b Macros 1.1 2016-08-28 22:21:25 -07:00
David Tolnay 7014c105b4 Remove coverage shield 2016-08-28 08:39:53 -07:00
David Tolnay f3d566af09 Remove clippy shield 2016-08-28 08:37:55 -07:00
David Tolnay 278e8eb720 Add deserialize_seq methods to MapDeserializer 2016-08-25 10:45:25 -04:00
David Tolnay e9b04de9a5 Impl SeqVisitor for MapDeserializer 2016-08-25 10:12:23 -04:00
David Tolnay 2a2891d54b Expose forward_to_deserialize macro 2016-08-24 00:16:22 -04:00
David Tolnay 85f1bf0259 Enum deserialization API 2016-08-23 22:17:28 -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
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
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 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
80 changed files with 6542 additions and 8140 deletions
-7
View File
@@ -1,7 +0,0 @@
paths = [
"serde",
"serde_codegen",
"serde_codegen_internals",
"serde_macros",
"serde_test",
]
+9 -19
View File
@@ -1,37 +1,27 @@
sudo: false
language: rust
rust:
- 1.13.0
- stable
- nightly
- 1.8.0
- 1.9.0
- beta
addons:
apt:
packages:
- libcurl4-openssl-dev
- libelf-dev
- libdw-dev
- nightly
before_script:
- pip install 'travis-cargo<0.2' --user
- export PATH=$HOME/.local/bin:$PATH
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 beta test)
- (cd serde && travis-cargo --only nightly test -- --features unstable-testing)
- (cd serde && travis-cargo build -- --no-default-features)
- (cd serde && travis-cargo --only nightly build -- --no-default-features --features alloc)
- (cd serde && travis-cargo --only nightly build -- --no-default-features --features collections)
- (cd testing && travis-cargo --skip nightly test)
- (cd testing && travis-cargo --only nightly test -- --features nightly-testing)
- (cd serde_macros && travis-cargo --only nightly test -- --features nightly-testing)
- (cd examples/serde-syntex-example && travis-cargo --skip nightly run)
- (cd examples/serde-syntex-example && travis-cargo --only nightly run -- --no-default-features --features nightly)
- (cd testing && travis-cargo --only nightly test -- --features unstable-testing)
- (cd serde_derive && travis-cargo --only nightly test)
- (cd serde_derive/no-std-tests && travis-cargo --only nightly build)
#- (cd examples/serde-syntex-example && travis-cargo --skip nightly run)
#- (cd examples/serde-syntex-example && travis-cargo --only nightly run -- --no-default-features --features unstable)
- (cd serde && travis-cargo --only stable doc)
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=
-33
View File
@@ -1,33 +0,0 @@
See LICENSE-APACHE and LICENSE-MIT.
----
bench_log is derived from https://github.com/cloudflare/goser, which has the
following license:
Copyright (c) 2013, CloudFlare, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+37 -797
View File
@@ -1,215 +1,23 @@
Serde Rust Serialization Framework
==================================
# Serde &emsp; [![Build Status](https://api.travis-ci.org/serde-rs/serde.svg?branch=master)](https://travis-ci.org/serde-rs/serde) [![Latest Version](https://img.shields.io/crates/v/serde.svg)](https://crates.io/crates/serde)
[![Build Status](https://api.travis-ci.org/serde-rs/serde.svg?branch=master)](https://travis-ci.org/serde-rs/serde)
[![Coverage Status](https://coveralls.io/repos/serde-rs/serde/badge.svg?branch=master&service=github)](https://coveralls.io/github/serde-rs/serde?branch=master)
[![Latest Version](https://img.shields.io/crates/v/serde.svg)](https://crates.io/crates/serde)
[![Clippy Linting Result](https://clippy.bashy.io/github/serde-rs/serde/master/badge.svg)](https://clippy.bashy.io/github/serde-rs/serde/master/log)
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
Serde is a powerful framework that enables serialization libraries to
generically serialize Rust data structures without the overhead of runtime type
information. In many situations, the handshake protocol between serializers and
serializees can be completely optimized away, leaving Serde to perform roughly
the same speed as a hand written serializer for a specific type.
---
[Documentation](https://serde-rs.github.io/serde/serde/index.html)
You may be looking for:
Simple Serde Example
====================
- [An overview of Serde](https://serde.rs/)
- [Data formats supported by Serde](https://serde.rs/#data-formats)
- [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/codegen.html)
- [Examples](https://serde.rs/examples.html)
- [API documentation](https://docs.serde.rs/serde/)
- [Release notes](https://github.com/serde-rs/serde/releases)
Here is a simple example that uses
[serde_json](https://github.com/serde-rs/json), which uses Serde under the
covers, to generate and parse JSON. First, lets start off with the `Cargo.toml`
file:
```toml
[package]
name = "serde_example"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
[dependencies]
serde_json = "*"
```
Next, the `src/main.rs` file itself:
```rust,ignore
extern crate serde_json;
use std::collections::HashMap;
use serde_json::Value;
use serde_json::builder::{ArrayBuilder, ObjectBuilder};
fn main() {
// Serde has support for many of the builtin Rust types, like arrays..:
let v = vec![1, 2];
let serialized = serde_json::to_string(&v).unwrap();
println!("serialized vec: {:?}", serialized);
let deserialized: Vec<u32> = serde_json::from_str(&serialized).unwrap();
println!("deserialized vec: {:?}", deserialized);
// ... and maps:
let mut map = HashMap::new();
map.insert("x".to_string(), 1);
map.insert("y".to_string(), 2);
let serialized = serde_json::to_string(&map).unwrap();
println!("serialized map: {:?}", serialized);
let deserialized: HashMap<String, u32> = serde_json::from_str(&serialized).unwrap();
println!("deserialized map: {:?}", deserialized);
// It also can handle complex objects:
let value = ObjectBuilder::new()
.insert("int", 1)
.insert("string", "a string")
.insert("array", ArrayBuilder::new()
.push(1)
.push(2)
.unwrap())
.unwrap();
let serialized = serde_json::to_string(&value).unwrap();
println!("serialized value: {:?}", serialized);
let deserialized: serde_json::Value = serde_json::from_str(&serialized).unwrap();
println!("deserialized value: {:?}", deserialized);
}
```
This produces the following output when run:
```
% cargo run
serialized vec: "[1,2]"
deserialized vec: [1, 2]
serialized map: "{\"y\":2,\"x\":1}"
deserialized map: {"y": 2, "x": 1}
serialized value: "{\"array\":[1,2],\"int\":1,\"string\":\"a string\"}"
deserialized value: {"array":[1,2],"int":1,"string":"a string"}
```
Using Serde with Stable Rust and serde\_codegen
===============================================
The example before used `serde_json::Value` as the in-memory representation of
the JSON value, but it's also possible for Serde to serialize to and from
regular Rust types. However, the code to do this can be a bit complicated to
write. So instead, Serde also has some powerful code generation libraries that
work with Stable and Nightly Rust that eliminate much of the complexity of hand
rolling serialization and deserialization for a given type.
First lets see how we would use Stable Rust, which is currently a tad more
complicated than Nightly Rust due to having to work around compiler plugins
being unstable. We will use `serde_codegen` which is based on the code
generation library [syntex](https://github.com/serde-rs/syntex). First we need
to setup the `Cargo.toml` that builds the project:
```toml
[package]
name = "serde_example"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
build = "build.rs"
[build-dependencies]
serde_codegen = "*"
[dependencies]
serde = "*"
serde_json = "*"
```
Next, we define our source file, `src/main.rs.in`. Note this is a different
extension than usual becaues we need to do code generation:
```rust,ignore
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
println!("{}", serialized);
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
println!("{:?}", deserialized);
}
```
To finish up the main source code, we define a very simple `src/main.rs` that
uses the generated code.
`src/main.rs`:
```rust,ignore
extern crate serde;
extern crate serde_json;
include!(concat!(env!("OUT_DIR"), "/main.rs"));
```
The last step is to actually drive the code generation, with the `build.rs` script:
```rust,ignore
extern crate serde_codegen;
use std::env;
use std::path::Path;
pub fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let src = Path::new("src/main.rs.in");
let dst = Path::new(&out_dir).join("main.rs");
serde_codegen::expand(&src, &dst).unwrap();
}
```
All this produces this when run:
```
% cargo run
{"x":1,"y":2}
Point { x: 1, y: 2 }
```
While this works well with Stable Rust, be aware that the error locations
currently are reported in the generated file instead of in the source file.
Using Serde with Nightly Rust and serde\_macros
===============================================
The prior example is a bit more complicated than it needs to be due to compiler
plugins being unstable. However, if you are already using Nightly Rust, you can
use `serde_macros`, which has a much simpler interface. First, here is the new
`Cargo.toml`:
```toml
[package]
name = "serde_example_nightly"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
[dependencies]
serde = "*"
serde_json = "*"
serde_macros = "*"
```
Note that it doesn't need a build script. Now the `src/main.rs`, which enables
the plugin feature, and registers the `serde_macros` plugin:
## Serde in action
```rust
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
@@ -222,610 +30,42 @@ struct Point {
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
println!("{}", serialized);
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
println!("{:?}", deserialized);
}
```
This also produces the same output:
```
% cargo run
{"x":1,"y":2}
Point { x: 1, y: 2 }
```
You may find it easier to develop with Nightly Rust and `serde\_macros`, then
deploy with Stable Rust and `serde_codegen`. It's possible to combine both
approaches in one setup:
`Cargo.toml`:
```toml
[package]
name = "serde_example"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
build = "build.rs"
[features]
default = ["serde_codegen"]
nightly = ["serde_macros"]
[build-dependencies]
serde_codegen = { version = "*", optional = true }
[dependencies]
serde = "*"
serde_json = "*"
serde_macros = { version = "*", optional = true }
```
`build.rs`:
```rust,ignore
#[cfg(not(feature = "serde_macros"))]
mod inner {
extern crate serde_codegen;
use std::env;
use std::path::Path;
pub fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let src = Path::new("src/main.rs.in");
let dst = Path::new(&out_dir).join("main.rs");
serde_codegen::expand(&src, &dst).unwrap();
}
}
#[cfg(feature = "serde_macros")]
mod inner {
pub fn main() {}
}
fn main() {
inner::main();
}
```
`src/main.rs`:
```rust,ignore
#![cfg_attr(feature = "serde_macros", feature(custom_derive, plugin))]
#![cfg_attr(feature = "serde_macros", plugin(serde_macros))]
extern crate serde;
extern crate serde_json;
#[cfg(feature = "serde_macros")]
include!("main.rs.in");
#[cfg(not(feature = "serde_macros"))]
include!(concat!(env!("OUT_DIR"), "/main.rs"));
```
The `src/main.rs.in` is the same as before.
Then to run with stable:
```
% cargo build
...
```
Or with nightly:
```
% cargo build --features nightly --no-default-features
...
```
Serialization without Macros
============================
Under the covers, Serde extensively uses the Visitor pattern to thread state
between the
[Serializer](http://serde-rs.github.io/serde/serde/serde/ser/trait.Serializer.html)
and
[Serialize](http://serde-rs.github.io/serde/serde/serde/ser/trait.Serialize.html)
without the two having specific information about each other's concrete type.
This has many of the same benefits as frameworks that use runtime type
information without the overhead. In fact, when compiling with optimizations,
Rust is able to remove most or all the visitor state, and generate code that's
nearly as fast as a hand written serializer format for a specific type.
To see it in action, lets look at how a simple type like `i32` is serialized.
The
[Serializer](http://serde-rs.github.io/serde/serde/serde/ser/trait.Serializer.html)
is threaded through the type:
```rust,ignore
impl serde::Serialize for i32 {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: serde::Serializer,
{
serializer.serialize_i32(*self)
}
}
```
As you can see it's pretty simple. More complex types like `BTreeMap` need to
pass a
[MapVisitor](http://serde-rs.github.io/serde/serde/serde/ser/trait.MapVisitor.html)
to the
[Serializer](http://serde-rs.github.io/serde/serde/serde/ser/trait.Serializer.html)
in order to walk through the type:
```rust,ignore
impl<K, V> Serialize for BTreeMap<K, V>
where K: Serialize + Ord,
V: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
pub struct MapIteratorVisitor<Iter> {
iter: Iter,
len: Option<usize>,
}
impl<K, V, Iter> MapIteratorVisitor<Iter>
where Iter: Iterator<Item=(K, V)>
{
#[inline]
pub fn new(iter: Iter, len: Option<usize>) -> MapIteratorVisitor<Iter> {
MapIteratorVisitor {
iter: iter,
len: len,
}
}
}
impl<K, V, I> MapVisitor for MapIteratorVisitor<I>
where K: Serialize,
V: Serialize,
I: Iterator<Item=(K, V)>,
{
#[inline]
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer,
{
match self.iter.next() {
Some((key, value)) => {
let value = try!(serializer.serialize_map_elt(key, value));
Ok(Some(value))
}
None => Ok(None)
}
}
#[inline]
fn len(&self) -> Option<usize> {
self.len
}
}
```
Serializing structs follow this same pattern. In fact, structs are represented
as a named map. Its visitor uses a simple state machine to iterate through all
the fields:
```rust
extern crate serde;
extern crate serde_json;
struct Point {
x: i32,
y: i32,
}
impl serde::Serialize for Point {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: serde::Serializer
{
serializer.serialize_struct("Point", PointMapVisitor {
value: self,
state: 0,
})
}
}
struct PointMapVisitor<'a> {
value: &'a Point,
state: u8,
}
impl<'a> serde::ser::MapVisitor for PointMapVisitor<'a> {
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: serde::Serializer
{
match self.state {
0 => {
self.state += 1;
Ok(Some(try!(serializer.serialize_struct_elt("x", &self.value.x))))
}
1 => {
self.state += 1;
Ok(Some(try!(serializer.serialize_struct_elt("y", &self.value.y))))
}
_ => {
Ok(None)
}
}
}
}
fn main() {
let point = Point { x: 1, y: 2 };
// Convert the Point to a JSON string.
let serialized = serde_json::to_string(&point).unwrap();
println!("{}", serialized);
}
```
Deserialization without Macros
==============================
Deserialization is a little more complicated since there's a bit more error
handling that needs to occur. Let's start with the simple `i32`
[Deserialize](http://serde-rs.github.io/serde/serde/serde/de/trait.Deserialize.html)
implementation. It passes a
[Visitor](http://serde-rs.github.io/serde/serde/serde/de/trait.Visitor.html) to the
[Deserializer](http://serde-rs.github.io/serde/serde/serde/de/trait.Deserializer.html).
The [Visitor](http://serde-rs.github.io/serde/serde/serde/de/trait.Visitor.html)
can create the `i32` from a variety of different types:
```rust,ignore
impl Deserialize for i32 {
fn deserialize<D>(deserializer: &mut D) -> Result<i32, D::Error>
where D: serde::Deserializer,
{
deserializer.deserialize(I32Visitor)
}
}
struct I32Visitor;
impl serde::de::Visitor for I32Visitor {
type Value = i32;
fn visit_i16<E>(&mut self, value: i16) -> Result<i32, E>
where E: Error,
{
self.visit_i32(value as i32)
}
fn visit_i32<E>(&mut self, value: i32) -> Result<i32, E>
where E: Error,
{
Ok(value)
}
...
```
Since it's possible for this type to get passed an unexpected type, we need a
way to error out. This is done by way of the
[Error](http://serde-rs.github.io/serde/serde/serde/de/trait.Error.html) trait,
which allows a
[Deserialize](http://serde-rs.github.io/serde/serde/serde/de/trait.Deserialize.html)
to generate an error for a few common error conditions. Here's how it could be used:
```rust,ignore
...
fn visit_string<E>(&mut self, _: String) -> Result<i32, E>
where E: Error,
{
Err(serde::de::Error::custom("expect a string"))
}
...
```
Maps follow a similar pattern as before, and use a
[MapVisitor](http://serde-rs.github.io/serde/serde/serde/de/trait.MapVisitor.html)
to walk through the values generated by the
[Deserializer](http://serde-rs.github.io/serde/serde/serde/de/trait.Deserializer.html).
```rust,ignore
impl<K, V> serde::Deserialize for BTreeMap<K, V>
where K: serde::Deserialize + Eq + Ord,
V: serde::Deserialize,
{
fn deserialize<D>(deserializer: &mut D) -> Result<BTreeMap<K, V>, D::Error>
where D: serde::Deserializer,
{
deserializer.deserialize(BTreeMapVisitor::new())
}
}
pub struct BTreeMapVisitor<K, V> {
marker: PhantomData<BTreeMap<K, V>>,
}
impl<K, V> BTreeMapVisitor<K, V> {
pub fn new() -> Self {
BTreeMapVisitor {
marker: PhantomData,
}
}
}
impl<K, V> serde::de::Visitor for BTreeMapVisitor<K, V>
where K: serde::de::Deserialize + Ord,
V: serde::de::Deserialize
{
type Value = BTreeMap<K, V>;
fn visit_unit<E>(&mut self) -> Result<BTreeMap<K, V>, E>
where E: Error,
{
Ok(BTreeMap::new())
}
fn visit_map<V_>(&mut self, mut visitor: V_) -> Result<BTreeMap<K, V>, V_::Error>
where V_: MapVisitor,
{
let mut values = BTreeMap::new();
while let Some((key, value)) = try!(visitor.visit()) {
values.insert(key, value);
}
try!(visitor.end());
Ok(values)
}
}
```
Deserializing structs goes a step further in order to support not allocating a
`String` to hold the field names. This is done by custom field enum that
deserializes an enum variant from a string. So for our `Point` example from
before, we need to generate:
```rust
extern crate serde;
extern crate serde_json;
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
enum PointField {
X,
Y,
}
impl serde::Deserialize for PointField {
fn deserialize<D>(deserializer: &mut D) -> Result<PointField, D::Error>
where D: serde::de::Deserializer
{
struct PointFieldVisitor;
impl serde::de::Visitor for PointFieldVisitor {
type Value = PointField;
fn visit_str<E>(&mut self, value: &str) -> Result<PointField, E>
where E: serde::de::Error
{
match value {
"x" => Ok(PointField::X),
"y" => Ok(PointField::Y),
_ => Err(serde::de::Error::custom("expected x or y")),
}
}
}
deserializer.deserialize(PointFieldVisitor)
}
}
impl serde::Deserialize for Point {
fn deserialize<D>(deserializer: &mut D) -> Result<Point, D::Error>
where D: serde::de::Deserializer
{
static FIELDS: &'static [&'static str] = &["x", "y"];
deserializer.deserialize_struct("Point", FIELDS, PointVisitor)
}
}
struct PointVisitor;
impl serde::de::Visitor for PointVisitor {
type Value = Point;
fn visit_map<V>(&mut self, mut visitor: V) -> Result<Point, V::Error>
where V: serde::de::MapVisitor
{
let mut x = None;
let mut y = None;
loop {
match try!(visitor.visit_key()) {
Some(PointField::X) => { x = Some(try!(visitor.visit_value())); }
Some(PointField::Y) => { y = Some(try!(visitor.visit_value())); }
None => { break; }
}
}
let x = match x {
Some(x) => x,
None => try!(visitor.missing_field("x")),
};
let y = match y {
Some(y) => y,
None => try!(visitor.missing_field("y")),
};
try!(visitor.end());
Ok(Point{ x: x, y: y })
}
}
fn main() {
let serialized = "{\"x\":1,\"y\":2}";
// Prints serialized = {"x":1,"y":2}
println!("serialized = {}", serialized);
// Convert the JSON string back to a Point.
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
println!("{:?}", deserialized);
// Prints deserialized = Point { x: 1, y: 2 }
println!("deserialized = {:?}", deserialized);
}
```
Design Considerations and tradeoffs for Serializers and Deserializers
=====================================================================
## Getting help
Serde serialization and deserialization implementations are written in such a
way that they err on being able to represent more values, and also provide
better error messages when they are passed an incorrect type to deserialize
from. For example, by default, it is a syntax error to deserialize a `String`
into an `Option<String>`. This is implemented such that it is possible to
distinguish between the values `None` and `Some(())`, if the serialization
format supports option types.
Serde developers live in the #serde channel on
[`irc.mozilla.org`](https://wiki.mozilla.org/IRC). The #rust channel is also a
good resource with generally faster response time but less specific knowledge
about Serde. If IRC is not your thing or you don't get a good response, we are
happy to respond to [GitHub issues](https://github.com/serde-rs/serde/issues/new)
as well.
However, many formats do not have option types, and represents optional values
as either a `null`, or some other value. Serde `Serializer`s and
`Deserializer`s can opt-in support for this. For serialization, this is pretty
easy. Simply implement these methods:
## License
```rust,ignore
...
Serde is licensed under either of
fn visit_none(&mut self) -> Result<(), Self::Error> {
self.visit_unit()
}
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
http://opensource.org/licenses/MIT)
fn visit_some<T>(&mut self, value: T) -> Result<(), Self::Error> {
value.serialize(self)
}
...
```
at your option.
For deserialization, this can be implemented by way of the
`Deserializer::visit_option` hook, which presumes that there is some ability to peek at what is the
next value in the serialized token stream. This following example is from
[serde_tests::TokenDeserializer](https://github.com/serde-rs/serde/blob/master/serde_tests/tests/token.rs#L435-L454),
where it checks to see if the next value is an `Option`, a `()`, or some other
value:
### Contribution
```rust,ignore
...
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.tokens.peek() {
Some(&Token::Option(false)) => {
self.tokens.next();
visitor.visit_none()
}
Some(&Token::Option(true)) => {
self.tokens.next();
visitor.visit_some(self)
}
Some(&Token::Unit) => {
self.tokens.next();
visitor.visit_none()
}
Some(_) => visitor.visit_some(self),
None => Err(Error::EndOfStreamError),
}
}
...
```
Annotations
===========
`serde_codegen` and `serde_macros` support annotations that help to customize
how types are serialized. Here are the supported annotations:
Container Annotations:
| Annotation | Function |
| ---------- | -------- |
| `#[serde(rename="name")]` | Serialize and deserialize this container with the given name |
| `#[serde(rename(serialize="name1"))]` | Serialize this container with the given name |
| `#[serde(rename(deserialize="name1"))]` | Deserialize this container with the given name |
| `#[serde(deny_unknown_fields)]` | Always error during serialization when encountering unknown fields. When absent, unknown fields are ignored for self-describing formats like JSON. |
| `#[serde(bound="T: MyTrait")]` | Where-clause for the Serialize and Deserialize impls. This replaces any bounds inferred by Serde. |
| `#[serde(bound(serialize="T: MyTrait"))]` | Where-clause for the Serialize impl. |
| `#[serde(bound(deserialize="T: MyTrait"))]` | Where-clause for the Deserialize impl. |
Variant Annotations:
| Annotation | Function |
| ---------- | -------- |
| `#[serde(rename="name")]` | Serialize and deserialize this variant with the given name |
| `#[serde(rename(serialize="name1"))]` | Serialize this variant with the given name |
| `#[serde(rename(deserialize="name1"))]` | Deserialize this variant with the given name |
Field Annotations:
| Annotation | Function |
| ---------- | -------- |
| `#[serde(rename="name")]` | Serialize and deserialize this field with the given name |
| `#[serde(rename(serialize="name1"))]` | Serialize this field with the given name |
| `#[serde(rename(deserialize="name1"))]` | Deserialize this field with the given name |
| `#[serde(default)]` | If the value is not specified, use the `Default::default()` |
| `#[serde(default="$path")]` | Call the path to a function `fn() -> T` to build the value |
| `#[serde(skip_serializing)]` | Do not serialize this value |
| `#[serde(skip_deserializing)]` | Always use `Default::default()` or `#[serde(default="$path")]` instead of deserializing this value |
| `#[serde(skip_serializing_if="$path")]` | Do not serialize this value if this function `fn(&T) -> bool` returns `true` |
| `#[serde(serialize_with="$path")]` | Call a function `fn<S>(&T, &mut S) -> Result<(), S::Error> where S: Serializer` to serialize this value of type `T` |
| `#[serde(deserialize_with="$path")]` | Call a function `fn<D>(&mut D) -> Result<T, D::Error> where D: Deserializer` to deserialize this value of type `T` |
| `#[serde(bound="T: MyTrait")]` | Where-clause for the Serialize and Deserialize impls. This replaces any bounds inferred by Serde for the current field. |
| `#[serde(bound(serialize="T: MyTrait"))]` | Where-clause for the Serialize impl. |
| `#[serde(bound(deserialize="T: MyTrait"))]` | Where-clause for the Deserialize impl. |
Using in `no_std` crates
========================
The core `serde` package defines a number of features to enable usage in a
variety of freestanding environments. Enable any or none of the following
features, and use `default-features = false` in your `Cargo.toml`:
- `alloc` (implies `nightly`)
- `collections` (implies `alloc` and `nightly`)
- `std` (default)
If you only use `default-features = false`, you will receive a stock `no_std`
serde with no support for any of the collection types.
Upgrading from Serde 0.6
========================
* `#[serde(skip_serializing_if_none)]` was replaced with `#[serde(skip_serializing_if="Option::is_none")]`.
* `#[serde(skip_serializing_if_empty)]` was replaced with `#[serde(skip_serializing_if="Vec::is_empty")]`.
Serialization Formats Using Serde
=================================
| Format | Name |
| ------ | ---- |
| Bincode | [bincode](https://crates.io/crates/bincode) |
| env vars | [envy](https://crates.io/crates/envy) |
| JSON | [serde\_json](https://crates.io/crates/serde_json) |
| MessagePack | [rmp](https://crates.io/crates/rmp) |
| XML | [serde\_xml](https://github.com/serde-rs/xml) |
| YAML | [serde\_yaml](https://github.com/dtolnay/serde-yaml) |
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.
+6 -5
View File
@@ -3,15 +3,16 @@ name = "serde-syntex-example"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
build = "build.rs"
publish = false
[features]
default = ["serde_codegen"]
nightly = ["serde_macros"]
unstable = ["serde_derive"]
[build-dependencies]
serde_codegen = { version = "^0.7", optional = true }
serde_codegen = { version = "^0.8", optional = true, path = "../../serde_codegen" }
[dependencies]
serde = "^0.7"
serde_json = "^0.7"
serde_macros = { version = "^0.7", optional = true }
serde = "^0.8"
serde_derive = { version = "^0.8", optional = true, path = "../../serde_derive" }
serde_json = "^0.8"
+1 -1
View File
@@ -16,5 +16,5 @@ Point { x: 1, y: 2 }
On nightly, it can use a plugin with:
```
% rustup run nightly cargo run --features nightly --no-default-features
% rustup run nightly cargo run --features unstable --no-default-features
```
+2 -2
View File
@@ -1,4 +1,4 @@
#[cfg(not(feature = "serde_macros"))]
#[cfg(not(feature = "serde_derive"))]
mod inner {
extern crate serde_codegen;
@@ -15,7 +15,7 @@ mod inner {
}
}
#[cfg(feature = "serde_macros")]
#[cfg(feature = "serde_derive")]
mod inner {
pub fn main() {}
}
+5 -4
View File
@@ -1,11 +1,12 @@
#![cfg_attr(feature = "serde_macros", feature(custom_derive, plugin))]
#![cfg_attr(feature = "serde_macros", plugin(serde_macros))]
#[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"));
+13 -5
View File
@@ -1,23 +1,31 @@
[package]
name = "serde"
version = "0.7.15"
version = "0.9.0-rc4"
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"]
categories = ["encoding"]
include = ["Cargo.toml", "src/**/*.rs"]
[badges]
travis-ci = { repository = "serde-rs/serde" }
[features]
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 }
[dev-dependencies]
serde_derive = "0.9.0-rc3"
+111 -41
View File
@@ -1,4 +1,20 @@
//! Helper module to enable serializing bytes more efficiently
//! Wrapper types to enable optimized handling of `&[u8]` and `Vec<u8>`.
//!
//! Without specialization, Rust forces us to treat `&[u8]` just like any other
//! slice and `Vec<u8>` just like any other vector. In reality this particular
//! slice and vector can often be serialized and deserialized in a more
//! efficient, compact representation in many formats.
//!
//! When working with such a format, you can opt into specialized handling of
//! `&[u8]` by wrapping it in `bytes::Bytes` and `Vec<u8>` by wrapping it in
//! `bytes::ByteBuf`.
//!
//! Rust support for specialization is being tracked in
//! [rust-lang/rust#31844][specialization]. Once it lands in the stable compiler
//! we will be deprecating these wrapper types in favor of optimizing `&[u8]`
//! and `Vec<u8>` out of the box.
//!
//! [specialization]: https://github.com/rust-lang/rust/issues/31844
use core::{ops, fmt, char, iter, slice};
use core::fmt::Write;
@@ -6,19 +22,50 @@ use core::fmt::Write;
use ser;
#[cfg(any(feature = "std", feature = "collections"))]
pub use self::bytebuf::{ByteBuf, ByteBufVisitor};
pub use self::bytebuf::ByteBuf;
#[cfg(any(feature = "std", feature = "collections"))]
#[doc(hidden)] // does anybody need this?
pub use self::bytebuf::ByteBufVisitor;
#[cfg(feature = "collections")]
use collections::Vec;
///////////////////////////////////////////////////////////////////////////////
/// `Bytes` wraps a `&[u8]` in order to serialize into a byte array.
/// Wraps a `&[u8]` in order to serialize in an efficient way. Does not support
/// deserialization.
///
/// ```rust
/// # #[macro_use] extern crate serde_derive;
/// # extern crate serde;
/// # use std::net::IpAddr;
/// #
/// use serde::bytes::Bytes;
///
/// # #[allow(dead_code)]
/// #[derive(Serialize)]
/// struct Packet<'a> {
/// destination: IpAddr,
/// payload: Bytes<'a>,
/// }
/// #
/// # fn main() {}
/// ```
#[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
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 +78,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)
}
}
@@ -60,7 +103,7 @@ impl<'a> ops::Deref for Bytes<'a> {
impl<'a> ser::Serialize for Bytes<'a> {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: ser::Serializer
{
serializer.serialize_bytes(self.bytes)
@@ -79,9 +122,27 @@ mod bytebuf {
use de;
#[cfg(feature = "collections")]
use collections::Vec;
use collections::{String, Vec};
/// `ByteBuf` wraps a `Vec<u8>` and serializes as a byte array.
/// Wraps a `Vec<u8>` in order to serialize and deserialize in an efficient
/// way.
///
/// ```rust
/// # #[macro_use] extern crate serde_derive;
/// # extern crate serde;
/// # use std::net::IpAddr;
/// #
/// use serde::bytes::ByteBuf;
///
/// # #[allow(dead_code)]
/// #[derive(Serialize, Deserialize)]
/// struct Packet {
/// destination: IpAddr,
/// payload: ByteBuf,
/// }
/// #
/// # fn main() {}
/// ```
#[derive(Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct ByteBuf {
bytes: Vec<u8>,
@@ -90,15 +151,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 +185,7 @@ mod bytebuf {
impl From<Vec<u8>> for ByteBuf {
fn from(bytes: Vec<u8>) -> Self {
ByteBuf {
bytes: bytes,
}
ByteBuf::from(bytes)
}
}
@@ -162,7 +224,7 @@ mod bytebuf {
}
impl ser::Serialize for ByteBuf {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: ser::Serializer
{
serializer.serialize_bytes(self)
@@ -175,17 +237,19 @@ mod bytebuf {
impl de::Visitor for ByteBufVisitor {
type Value = ByteBuf;
#[inline]
fn visit_unit<E>(&mut self) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf {
bytes: Vec::new(),
})
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("byte array")
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<ByteBuf, V::Error>
fn visit_unit<E>(self) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf::new())
}
#[inline]
fn visit_seq<V>(self, mut visitor: V) -> Result<ByteBuf, V::Error>
where V: de::SeqVisitor,
{
let (len, _) = visitor.size_hint();
@@ -195,36 +259,42 @@ mod bytebuf {
values.push(value);
}
try!(visitor.end());
Ok(ByteBuf {
bytes: values,
})
Ok(ByteBuf::from(values))
}
#[inline]
fn visit_bytes<E>(&mut self, v: &[u8]) -> Result<ByteBuf, E>
fn visit_bytes<E>(self, v: &[u8]) -> Result<ByteBuf, E>
where E: de::Error,
{
self.visit_byte_buf(v.to_vec())
Ok(ByteBuf::from(v))
}
#[inline]
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<ByteBuf, E>
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf {
bytes: v,
})
Ok(ByteBuf::from(v))
}
fn visit_str<E>(self, v: &str) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf::from(v))
}
fn visit_string<E>(self, v: String) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf::from(v))
}
}
impl de::Deserialize for ByteBuf {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<ByteBuf, D::Error>
fn deserialize<D>(deserializer: D) -> Result<ByteBuf, D::Error>
where D: de::Deserializer
{
deserializer.deserialize_bytes(ByteBufVisitor)
deserializer.deserialize_byte_buf(ByteBufVisitor)
}
}
}
+424 -296
View File
File diff suppressed because it is too large Load Diff
+1288 -621
View File
File diff suppressed because it is too large Load Diff
+39
View File
@@ -0,0 +1,39 @@
use core::marker::PhantomData;
use de::{Deserialize, Deserializer, Error, Visitor};
/// If the missing field is of type `Option<T>` then treat is as `None`,
/// otherwise it is an error.
pub fn missing_field<V, E>(field: &'static str) -> Result<V, E>
where V: Deserialize,
E: Error
{
struct MissingFieldDeserializer<E>(&'static str, PhantomData<E>);
impl<E> Deserializer for MissingFieldDeserializer<E>
where E: Error
{
type Error = E;
fn deserialize<V>(self, _visitor: V) -> Result<V::Value, E>
where V: Visitor
{
Err(Error::missing_field(self.0))
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, E>
where V: Visitor
{
visitor.visit_none()
}
forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
seq_fixed_size bytes byte_buf map unit_struct newtype_struct
tuple_struct struct struct_field tuple enum ignored_any
}
}
let deserializer = MissingFieldDeserializer(field, PhantomData);
Deserialize::deserialize(deserializer)
}
+526 -235
View File
File diff suppressed because it is too large Load Diff
-29
View File
@@ -1,30 +1,7 @@
//! A stand-in for `std::error`
use core::any::TypeId;
use core::fmt::{Debug, Display};
/// A stand-in for `std::error::Error`, which requires no allocation.
#[cfg(feature = "nightly")]
pub trait Error: Debug + Display + ::core::marker::Reflect {
/// A short description of the error.
///
/// The description should not contain newlines or sentence-ending
/// punctuation, to facilitate embedding in larger user-facing
/// strings.
fn description(&self) -> &str;
/// The lower-level cause of this error, if any.
fn cause(&self) -> Option<&Error> { None }
/// Get the `TypeId` of `self`
#[doc(hidden)]
fn type_id(&self) -> TypeId where Self: 'static {
TypeId::of::<Self>()
}
}
/// A stand-in for `std::error::Error`, which requires no allocation.
#[cfg(not(feature = "nightly"))]
pub trait Error: Debug + Display {
/// A short description of the error.
///
@@ -35,10 +12,4 @@ pub trait Error: Debug + Display {
/// The lower-level cause of this error, if any.
fn cause(&self) -> Option<&Error> { None }
/// Stubbed! Returns type_id of `()`
#[doc(hidden)]
fn type_id(&self) -> TypeId where Self: 'static {
TypeId::of::<()>()
}
}
+33
View File
@@ -0,0 +1,33 @@
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::String;
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::borrow::Cow;
pub use core::default::Default;
pub use core::fmt;
pub use core::marker::PhantomData;
pub use core::result::Result;
#[cfg(any(feature = "collections", feature = "std"))]
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
String::from_utf8_lossy(bytes)
}
// The generated code calls this like:
//
// let value = &_serde::export::from_utf8_lossy(bytes);
// Err(_serde::de::Error::unknown_variant(value, VARIANTS))
//
// so it is okay for the return type to be different from the std case as long
// as the above works.
#[cfg(not(any(feature = "collections", feature = "std")))]
pub fn from_utf8_lossy(bytes: &[u8]) -> &str {
use core::str;
// Three unicode replacement characters if it fails. They look like a
// white-on-black question mark. The user will recognize it as invalid
// UTF-8.
str::from_utf8(bytes).unwrap_or("\u{fffd}\u{fffd}\u{fffd}")
}
+81 -29
View File
@@ -1,55 +1,107 @@
//! Serde Serialization Framework
//! # Serde
//!
//! 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.
//!
//! For a detailed tutorial on the different ways to use serde please check out the
//! [github repository](https://github.com/serde-rs/serde)
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website https://serde.rs/ for additional documentation and
//! usage examples.
//!
//! ### Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's code
//! generation to automatically derive implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform roughly the same speed as a handwritten serializer
//! for the specific selection of data structure and data format.
//!
//! ### Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON](https://github.com/serde-rs/json), the ubiquitous JavaScript Object
//! Notation used by many HTTP APIs.
//! - [Bincode](https://github.com/TyOverby/bincode), a compact binary format
//! used for IPC within the Servo rendering engine.
//! - [CBOR](https://github.com/pyfisch/cbor), a Concise Binary Object
//! Representation designed for small message size without the need for
//! version negotiation.
//! - [YAML](https://github.com/dtolnay/serde-yaml), a popular human-friendly
//! configuration language that ain't markup language.
//! - [MessagePack](https://github.com/3Hren/msgpack-rust), an efficient binary
//! format that resembles a compact JSON.
//! - [TOML](https://github.com/alexcrichton/toml-rs), a minimal configuration
//! format used by [Cargo](http://doc.crates.io/manifest.html).
//! - [Pickle](https://github.com/birkenfeld/serde-pickle), a format common in
//! the Python world.
//! - [Hjson](https://github.com/laktak/hjson-rust), a variant of JSON designed
//! to be readable and writable by humans.
//! - [BSON](https://github.com/zonyitoo/bson-rs), the data storage and network
//! transfer format used by MongoDB.
//! - [URL](https://github.com/nox/serde_urlencoded), the x-www-form-urlencoded
//! format.
//! - [XML](https://github.com/serde-rs/xml), the flexible machine-friendly W3C
//! standard. *(deserialization only)*
//! - [Envy](https://github.com/softprops/envy), a way to deserialize
//! environment variables into Rust structs. *(deserialization only)*
//! - [Redis](https://github.com/OneSignal/serde-redis), deserialize values from
//! Redis when using [redis-rs](https://crates.io/crates/redis).
//! *(deserialization only)*
#![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(nonzero, inclusive_range, zero_one))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "collections", feature(collections, enumset))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", allow(linkedlist))]
#![cfg_attr(any(not(feature = "std"), feature = "nightly"), allow(unused_variables, unused_imports, unused_features, dead_code))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", allow(linkedlist, type_complexity))]
#![deny(missing_docs)]
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(feature = "collections")]
extern crate collections;
#[cfg(all(feature = "nightly", feature = "alloc"))]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "unstable")]
extern crate core as actual_core;
#[cfg(feature = "std")]
mod core {
pub use std::{ops, hash, fmt, cmp, marker, mem, i8, i16, i32, i64, u8, u16, u32, u64, isize,
usize, f32, f64, char, str, num, slice, iter};
#[cfg(feature = "nightly")]
extern crate core;
#[cfg(feature = "nightly")]
pub use self::core::nonzero;
usize, f32, f64, char, str, num, slice, iter, cell, default, result};
#[cfg(feature = "unstable")]
pub use actual_core::nonzero;
}
pub use ser::{Serialize, Serializer};
pub use de::{Deserialize, Deserializer, Error};
pub use de::{Deserialize, Deserializer};
#[cfg(not(feature = "std"))]
macro_rules! format {
($s:expr, $($rest:tt)*) => ($s)
}
#[macro_use]
mod macros;
pub mod bytes;
pub mod de;
#[cfg(feature = "std")]
#[doc(hidden)]
pub mod iter;
pub mod ser;
#[cfg(not(feature = "std"))]
#[cfg_attr(feature = "std", doc(hidden))]
pub mod error;
mod utils;
// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;
+190
View File
@@ -0,0 +1,190 @@
#[cfg(feature = "std")]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_method {
($func:ident($($arg:ty),*)) => {
#[inline]
fn $func<__V>(self, $(_: $arg,)* visitor: __V) -> ::std::result::Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor
{
self.deserialize(visitor)
}
};
}
#[cfg(not(feature = "std"))]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_method {
($func:ident($($arg:ty),*)) => {
#[inline]
fn $func<__V>(self, $(_: $arg,)* visitor: __V) -> ::core::result::Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor
{
self.deserialize(visitor)
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_helper {
(bool) => {
forward_to_deserialize_method!{deserialize_bool()}
};
(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()}
};
(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()}
};
(byte_buf) => {
forward_to_deserialize_method!{deserialize_byte_buf()}
};
(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)}
};
(enum) => {
forward_to_deserialize_method!{deserialize_enum(&'static str, &'static [&'static str])}
};
(ignored_any) => {
forward_to_deserialize_method!{deserialize_ignored_any()}
};
}
// Super explicit first paragraph because this shows up at the top level and
// trips up people who are just looking for basic Serialize / Deserialize
// documentation.
//
/// Helper macro when implementing the `Deserializer` part of a new data format
/// for Serde.
///
/// Some `Deserializer` implementations for self-describing formats do not care
/// what hint the `Visitor` gives them, they just want to blindly call the
/// `Visitor` method corresponding to the data they can tell is in the input.
/// This requires repetitive implementations of all the `Deserializer` trait
/// methods.
///
/// ```rust
/// # #[macro_use] extern crate serde;
/// # use serde::de::{value, Deserializer, Visitor};
/// # pub struct MyDeserializer;
/// # impl Deserializer for MyDeserializer {
/// # type Error = value::Error;
/// # fn deserialize<V>(self, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor
/// # { unimplemented!() }
/// #
/// #[inline]
/// fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor
/// {
/// self.deserialize(visitor)
/// }
/// # forward_to_deserialize! {
/// # u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
/// # seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
/// # tuple_struct struct struct_field tuple enum ignored_any
/// # }
/// # }
/// # fn main() {}
/// ```
///
/// The `forward_to_deserialize!` macro implements these simple forwarding
/// methods so that they forward directly to `Deserializer::deserialize`. You
/// can choose which methods to forward.
///
/// ```rust
/// # #[macro_use] extern crate serde;
/// # use serde::de::{value, Deserializer, Visitor};
/// # pub struct MyDeserializer;
/// impl Deserializer for MyDeserializer {
/// # type Error = value::Error;
/// fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor
/// {
/// /* ... */
/// # let _ = visitor;
/// # unimplemented!()
/// }
///
/// forward_to_deserialize! {
/// bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
/// seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
/// tuple_struct struct struct_field tuple enum ignored_any
/// }
/// }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! forward_to_deserialize {
($($func:ident)*) => {
$(forward_to_deserialize_helper!{$func})*
};
}
+203 -312
View File
@@ -1,5 +1,3 @@
//! Implementations for all of Rust's builtin types.
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(all(feature = "collections", not(feature = "std")))]
@@ -26,19 +24,18 @@ use collections::{
Vec,
};
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(feature = "collections")]
use collections::enum_set::{CLike, EnumSet};
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(feature = "collections")]
use collections::borrow::ToOwned;
#[cfg(feature = "std")]
use core::hash::{Hash, BuildHasher};
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
use core::iter;
#[cfg(feature = "std")]
use std::net;
#[cfg(feature = "nightly")]
use core::num;
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
use core::ops;
#[cfg(feature = "std")]
use std::path;
@@ -46,6 +43,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,39 +56,43 @@ use alloc::boxed::Box;
use core::marker::PhantomData;
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
use core::nonzero::{NonZero, Zeroable};
use super::{
Error,
Serialize,
SerializeSeq,
SerializeTuple,
Serializer,
SeqVisitor,
MapVisitor,
};
#[cfg(any(feature = "std", feature = "unstable"))]
use super::Error;
#[cfg(feature = "unstable")]
use super::Iterator;
///////////////////////////////////////////////////////////////////////////////
macro_rules! impl_visit {
($ty:ty, $method:ident) => {
($ty:ty, $method:ident $($cast:tt)*) => {
impl Serialize for $ty {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
serializer.$method(*self)
serializer.$method(*self $($cast)*)
}
}
}
}
impl_visit!(bool, serialize_bool);
impl_visit!(isize, serialize_isize);
impl_visit!(isize, serialize_i64 as i64);
impl_visit!(i8, serialize_i8);
impl_visit!(i16, serialize_i16);
impl_visit!(i32, serialize_i32);
impl_visit!(i64, serialize_i64);
impl_visit!(usize, serialize_usize);
impl_visit!(usize, serialize_u64 as u64);
impl_visit!(u8, serialize_u8);
impl_visit!(u16, serialize_u16);
impl_visit!(u32, serialize_u32);
@@ -102,7 +105,7 @@ impl_visit!(char, serialize_char);
impl Serialize for str {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
serializer.serialize_str(self)
@@ -112,7 +115,7 @@ impl Serialize for str {
#[cfg(any(feature = "std", feature = "collections"))]
impl Serialize for String {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
(&self[..]).serialize(serializer)
@@ -121,9 +124,11 @@ impl Serialize for String {
///////////////////////////////////////////////////////////////////////////////
impl<T> Serialize for Option<T> where T: Serialize {
impl<T> Serialize for Option<T>
where T: Serialize
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
match *self {
@@ -133,100 +138,17 @@ 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> {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
serializer.serialize_unit_struct("PhantomData")
}
}
///////////////////////////////////////////////////////////////////////////////
/// 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
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -234,10 +156,14 @@ impl<T> Serialize for [T]
where T: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
let mut seq = try!(serializer.serialize_seq(Some(self.len())));
for e in self {
try!(seq.serialize_element(e));
}
seq.end()
}
}
@@ -247,11 +173,14 @@ macro_rules! array_impls {
($len:expr) => {
impl<T> Serialize for [T; $len] where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
let visitor = SeqIteratorVisitor::new(self.iter(), Some($len));
serializer.serialize_fixed_size_array(visitor)
let mut seq = try!(serializer.serialize_seq_fixed_size($len));
for e in self {
try!(seq.serialize_element(e));
}
seq.end()
}
}
}
@@ -293,40 +222,67 @@ array_impls!(32);
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")]
impl<'a, I> Serialize for Iterator<I>
where I: IntoIterator, <I as IntoIterator>::Item: Serialize
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
// FIXME: use specialization to prevent invalidating the object in case of clonable iterators?
let iter = match self.0.borrow_mut().take() {
Some(iter) => iter.into_iter(),
None => return Err(Error::custom("Iterator used twice")),
};
let size = match iter.size_hint() {
(lo, Some(hi)) if lo == hi => Some(lo),
_ => None,
};
let mut seq = try!(serializer.serialize_seq(size));
for e in iter {
try!(seq.serialize_element(&e));
}
seq.end()
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! serialize_seq {
() => {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
let mut seq = try!(serializer.serialize_seq(Some(self.len())));
for e in self {
try!(seq.serialize_element(&e));
}
seq.end()
}
}
}
#[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(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,57 +290,61 @@ 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>,
where ops::Range<A>: ExactSizeIterator + iter::Iterator<Item = A> + Clone,
A: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
let len = iter::Step::steps_between(&self.start, &self.end, &A::one());
serializer.serialize_seq(SeqIteratorVisitor::new(self.clone(), len))
let mut seq = try!(serializer.serialize_seq(Some(self.len())));
for e in self.clone() {
try!(seq.serialize_element(&e));
}
seq.end()
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for Vec<T> where T: Serialize {
#[cfg(feature = "unstable")]
impl<A> Serialize for ops::RangeInclusive<A>
where ops::RangeInclusive<A>: ExactSizeIterator + iter::Iterator<Item = A> + Clone,
A: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, 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 seq = try!(serializer.serialize_seq(Some(self.len())));
for e in self.clone() {
try!(seq.serialize_element(&e));
}
seq.end()
}
}
@@ -392,7 +352,7 @@ impl<T> Serialize for VecDeque<T> where T: Serialize {
impl Serialize for () {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
serializer.serialize_unit()
@@ -401,11 +361,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 +368,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: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
let mut tuple = try!(serializer.serialize_tuple($len));
$(
try!(tuple.serialize_element(&self.$idx));
)+
tuple.end()
}
}
)+
@@ -638,83 +559,29 @@ 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: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
use super::SerializeMap;
let mut map = try!(serializer.serialize_map(Some(self.len())));
for (k, v) in self {
try!(map.serialize_key(k));
try!(map.serialize_value(v));
}
None => Ok(None)
map.end()
}
}
#[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,19 +590,14 @@ 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!();
}
///////////////////////////////////////////////////////////////////////////////
impl<'a, T: ?Sized> Serialize for &'a T where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
(**self).serialize(serializer)
@@ -744,7 +606,7 @@ impl<'a, T: ?Sized> Serialize for &'a T where T: Serialize {
impl<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
(**self).serialize(serializer)
@@ -752,9 +614,11 @@ impl<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize {
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: ?Sized> Serialize for Box<T> where T: Serialize {
impl<T: ?Sized> Serialize for Box<T>
where T: Serialize
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
(**self).serialize(serializer)
@@ -762,9 +626,11 @@ impl<T: ?Sized> Serialize for Box<T> where T: Serialize {
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T> Serialize for Rc<T> where T: Serialize, {
impl<T> Serialize for Rc<T>
where T: Serialize
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
(**self).serialize(serializer)
@@ -772,9 +638,11 @@ impl<T> Serialize for Rc<T> where T: Serialize, {
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T> Serialize for Arc<T> where T: Serialize, {
impl<T> Serialize for Arc<T>
where T: Serialize
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
(**self).serialize(serializer)
@@ -782,9 +650,11 @@ impl<T> Serialize for Arc<T> where T: Serialize, {
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned, {
impl<'a, T: ?Sized> Serialize for Cow<'a, T>
where T: Serialize + ToOwned
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
(**self).serialize(serializer)
@@ -793,8 +663,13 @@ impl<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned, {
///////////////////////////////////////////////////////////////////////////////
impl<T, E> Serialize for Result<T, E> where T: Serialize, E: Serialize {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
impl<T, E> Serialize for Result<T, E>
where T: Serialize,
E: Serialize
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
match *self {
Result::Ok(ref value) => {
serializer.serialize_newtype_variant("Result", 0, "Ok", value)
@@ -808,21 +683,33 @@ impl<T, E> Serialize for Result<T, E> where T: Serialize, E: Serialize {
///////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "std", feature = "nightly"))]
impl Serialize for net::IpAddr {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
#[cfg(feature = "std")]
impl Serialize for Duration {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
match *self {
net::IpAddr::V4(ref addr) => addr.serialize(serializer),
net::IpAddr::V6(ref addr) => addr.serialize(serializer),
}
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("Duration", 2));
try!(state.serialize_field("secs", &self.as_secs()));
try!(state.serialize_field("nanos", &self.subsec_nanos()));
state.end()
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl Serialize for net::IpAddr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
self.to_string().serialize(serializer)
}
}
#[cfg(feature = "std")]
impl Serialize for net::Ipv4Addr {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
self.to_string().serialize(serializer)
@@ -831,7 +718,7 @@ impl Serialize for net::Ipv4Addr {
#[cfg(feature = "std")]
impl Serialize for net::Ipv6Addr {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
self.to_string().serialize(serializer)
@@ -842,7 +729,7 @@ impl Serialize for net::Ipv6Addr {
#[cfg(feature = "std")]
impl Serialize for net::SocketAddr {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
match *self {
@@ -854,7 +741,7 @@ impl Serialize for net::SocketAddr {
#[cfg(feature = "std")]
impl Serialize for net::SocketAddrV4 {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
self.to_string().serialize(serializer)
@@ -863,7 +750,7 @@ impl Serialize for net::SocketAddrV4 {
#[cfg(feature = "std")]
impl Serialize for net::SocketAddrV6 {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
self.to_string().serialize(serializer)
@@ -874,28 +761,32 @@ impl Serialize for net::SocketAddrV6 {
#[cfg(feature = "std")]
impl Serialize for path::Path {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
match self.to_str() {
Some(s) => s.serialize(serializer),
None => Err(Error::invalid_value("Path contains invalid UTF-8 characters")),
None => Err(Error::custom("path contains invalid UTF-8 characters")),
}
}
}
#[cfg(feature = "std")]
impl Serialize for path::PathBuf {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
self.as_path().serialize(serializer)
}
}
#[cfg(feature = "nightly")]
impl<T> Serialize for NonZero<T> where T: Serialize + Zeroable {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
#[cfg(feature = "unstable")]
impl<T> Serialize for NonZero<T>
where T: Serialize + Zeroable
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
(**self).serialize(serializer)
}
}
+731 -317
View File
File diff suppressed because it is too large Load Diff
+15 -20
View File
@@ -1,37 +1,32 @@
[package]
name = "serde_codegen"
version = "0.7.15"
version = "0.9.0-rc4"
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.16.0", optional = true }
syntex = { version = "^0.39.0", optional = true }
with-syn = []
[dependencies]
aster = { version = "^0.22.0", default-features = false }
clippy = { version = "^0.*", optional = true }
quasi = { version = "^0.16.0", default-features = false }
quasi_macros = { version = "^0.16.0", optional = true }
serde_codegen_internals = { version = "^0.4.0", default-features = false }
syntex = { version = "^0.39.0", optional = true }
syntex_syntax = { version = "^0.39.0", optional = true }
quote = "0.3.8"
serde_codegen_internals = { version = "=0.11.3", default-features = false, path = "../serde_codegen_internals" }
syn = { version = "0.10", features = ["aster", "visit"] }
syntex = { version = "^0.54.0", optional = true }
syntex_syntax = { version = "^0.54.0", optional = true }
[badges]
travis-ci = { repository = "serde-rs/serde" }
-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
}
+569 -740
View File
File diff suppressed because it is too large Load Diff
+123 -50
View File
@@ -1,52 +1,32 @@
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(feature = "nightly-testing", allow(too_many_arguments))]
#![cfg_attr(feature = "nightly-testing", allow(used_underscore_binding))]
#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private, plugin))]
#![cfg_attr(not(feature = "with-syntex"), plugin(quasi_macros))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "clippy", allow(used_underscore_binding))]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "192"]
extern crate aster;
extern crate quasi;
extern crate serde_codegen_internals as internals;
#[cfg(feature = "with-syntex")]
extern crate syntex;
#[cfg(feature = "with-syntex")]
#[macro_use]
extern crate syntex_syntax as syntax;
#[cfg(not(feature = "with-syntex"))]
extern crate syn;
#[macro_use]
extern crate syntax;
#[cfg(not(feature = "with-syntex"))]
extern crate rustc_plugin;
extern crate quote;
#[cfg(feature = "with-syntex")]
use std::path::Path;
#[cfg(not(feature = "with-syntex"))]
use syntax::feature_gate::AttributeType;
mod bound;
mod de;
mod ser;
#[cfg(feature = "with-syntex")]
include!(concat!(env!("OUT_DIR"), "/lib.rs"));
#[cfg(not(feature = "with-syntex"))]
include!("lib.rs.in");
#[cfg(feature = "with-syntex")]
pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
where S: AsRef<Path>,
D: AsRef<Path>,
{
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.
@@ -57,11 +37,11 @@ pub fn register(reg: &mut syntex::Registry) {
impl fold::Folder for StripAttributeFolder {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
match attr.node.value.node {
ast::MetaItemKind::List(ref n, _) if n == &"serde" => { return None; }
_ => {}
if attr.value.name == "serde" {
if let ast::MetaItemKind::List(..) = attr.value.node {
return None;
}
}
Some(attr)
}
@@ -73,26 +53,119 @@ 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", shim::expand_derive_serialize);
reg.add_decorator("derive_Deserialize", shim::expand_derive_deserialize);
reg.add_post_expansion_pass(strip_attributes);
reg
}
#[cfg(not(feature = "with-syntex"))]
pub fn register(reg: &mut rustc_plugin::Registry) {
reg.register_syntax_extension(
syntax::parse::token::intern("derive_Serialize"),
syntax::ext::base::MultiDecorator(
Box::new(ser::expand_derive_serialize)));
#[cfg(feature = "with-syntex")]
pub fn expand_str(src: &str) -> Result<String, syntex::Error> {
let src = src.to_owned();
reg.register_syntax_extension(
syntax::parse::token::intern("derive_Deserialize"),
syntax::ext::base::MultiDecorator(
Box::new(de::expand_derive_deserialize)));
let expand_thread = move || {
syntex_registry().expand_str("", "", &src)
};
reg.register_attribute("serde".to_owned(), AttributeType::Normal);
syntex::with_extra_stack(expand_thread)
}
#[cfg(feature = "with-syntex")]
pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
where S: AsRef<Path>,
D: AsRef<Path>,
{
let src = src.as_ref().to_owned();
let dst = dst.as_ref().to_owned();
let expand_thread = move || {
syntex_registry().expand("", src, dst)
};
syntex::with_extra_stack(expand_thread)
}
macro_rules! shim {
($name:ident $pkg:ident :: $func:ident) => {
pub fn $func(
cx: &mut ::syntax::ext::base::ExtCtxt,
span: ::syntax::codemap::Span,
meta_item: &::syntax::ast::MetaItem,
annotatable: &::syntax::ext::base::Annotatable,
push: &mut FnMut(::syntax::ext::base::Annotatable)
) {
let item = match *annotatable {
::syntax::ext::base::Annotatable::Item(ref item) => item,
_ => {
cx.span_err(
meta_item.span,
concat!("`#[derive(",
stringify!($name),
")]` may only be applied to structs and enums"));
return;
}
};
use syntax::{attr, ast, visit};
struct MarkSerdeAttributesUsed;
impl<'a> visit::Visitor<'a> for MarkSerdeAttributesUsed {
fn visit_attribute(&mut self, attr: &ast::Attribute) {
if attr.value.name == "serde" {
if let ast::MetaItemKind::List(..) = attr.value.node {
attr::mark_used(attr);
}
}
}
}
visit::walk_item(&mut MarkSerdeAttributesUsed, item);
use syntax::print::pprust;
let s = pprust::item_to_string(item);
use {syn, $pkg};
let syn_item = syn::parse_macro_input(&s).unwrap();
let expanded = match $pkg::$func(&syn_item) {
Ok(expanded) => expanded.to_string(),
Err(msg) => {
cx.span_err(span, &msg);
return;
}
};
use syntax::parse;
let name = stringify!($name).to_string();
let sess = cx.parse_sess;
let impl_item = parse::parse_item_from_source_str(name, expanded, sess);
push(::syntax::ext::base::Annotatable::Item(impl_item.unwrap().unwrap()));
}
};
}
#[cfg(feature = "with-syntex")]
mod shim {
shim!(Serialize ser::expand_derive_serialize);
shim!(Deserialize de::expand_derive_deserialize);
}
#[cfg(feature = "with-syn")]
#[doc(hidden)]
/// Not public API. Use the serde_derive crate.
pub fn expand_derive_serialize(item: &str) -> Result<quote::Tokens, String> {
let syn_item = syn::parse_macro_input(item).unwrap();
ser::expand_derive_serialize(&syn_item)
}
#[cfg(feature = "with-syn")]
#[doc(hidden)]
/// Not public API. Use the serde_derive crate.
pub fn expand_derive_deserialize(item: &str) -> Result<quote::Tokens, String> {
let syn_item = syn::parse_macro_input(item).unwrap();
de::expand_derive_deserialize(&syn_item)
}
-4
View File
@@ -1,4 +0,0 @@
mod bound;
mod de;
mod ser;
mod span;
+325 -586
View File
File diff suppressed because it is too large Load Diff
-43
View File
@@ -1,43 +0,0 @@
use syntax::ast;
use syntax::codemap::{self, ExpnId, Span};
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::fold::{self, Folder};
use syntax::parse::token::intern;
use syntax::ptr::P;
pub fn record_expansion(
cx: &ExtCtxt,
item: P<ast::Item>,
derive: &str,
) -> Annotatable {
let info = codemap::ExpnInfo {
call_site: codemap::DUMMY_SP,
callee: codemap::NameAndSpan {
format: codemap::MacroAttribute(intern(&format!("derive({})", derive))),
span: None,
allow_internal_unstable: false,
},
};
let expn_id = cx.codemap().record_expansion(info);
let mut respanner = Respanner { expn_id: expn_id };
let item = item.map(|item| respanner.fold_item_simple(item));
Annotatable::Item(item)
}
struct Respanner {
expn_id: ExpnId,
}
impl Folder for Respanner {
fn new_span(&mut self, span: Span) -> Span {
Span {
expn_id: self.expn_id,
.. span
}
}
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
fold::noop_fold_mac(mac, self)
}
}
+8 -7
View File
@@ -1,20 +1,21 @@
[package]
name = "serde_codegen_internals"
version = "0.4.0"
version = "0.11.3"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "AST representation used by Serde codegen. Unstable."
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_codegen_internals/"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[features]
default = ["with-syntex"]
nightly-testing = ["clippy"]
with-syntex = ["syntex_syntax", "syntex_errors"]
unstable-testing = ["clippy"]
[dependencies]
clippy = { version = "^0.*", optional = true }
syntex_syntax = { version = "^0.39.0", optional = true }
syntex_errors = { version = "^0.39.0", optional = true }
syn = "0.10"
[badges]
travis-ci = { repository = "serde-rs/serde" }
+29 -55
View File
@@ -1,17 +1,12 @@
use syntax::ast;
use syntax::codemap;
use syntax::ext::base::ExtCtxt;
use syntax::ptr::P;
use syn;
use attr;
use Error;
use Ctxt;
pub struct Item<'a> {
pub ident: ast::Ident,
pub span: codemap::Span,
pub ident: syn::Ident,
pub attrs: attr::Item,
pub body: Body<'a>,
pub generics: &'a ast::Generics,
pub generics: &'a syn::Generics,
}
pub enum Body<'a> {
@@ -20,18 +15,16 @@ pub enum Body<'a> {
}
pub struct Variant<'a> {
pub ident: ast::Ident,
pub span: codemap::Span,
pub ident: syn::Ident,
pub attrs: attr::Variant,
pub style: Style,
pub fields: Vec<Field<'a>>,
}
pub struct Field<'a> {
pub ident: Option<ast::Ident>,
pub span: codemap::Span,
pub ident: Option<syn::Ident>,
pub attrs: attr::Field,
pub ty: &'a P<ast::Ty>,
pub ty: &'a syn::Ty,
}
pub enum Style {
@@ -42,33 +35,25 @@ pub enum Style {
}
impl<'a> Item<'a> {
pub fn from_ast(
cx: &ExtCtxt,
item: &'a ast::Item,
) -> Result<Item<'a>, Error> {
pub fn from_ast(cx: &Ctxt, item: &'a syn::MacroInput) -> Item<'a> {
let attrs = attr::Item::from_ast(cx, item);
let (body, generics) = match item.node {
ast::ItemKind::Enum(ref enum_def, ref generics) => {
let variants = enum_from_ast(cx, enum_def);
(Body::Enum(variants), generics)
let body = match item.body {
syn::Body::Enum(ref variants) => {
Body::Enum(enum_from_ast(cx, variants))
}
ast::ItemKind::Struct(ref variant_data, ref generics) => {
syn::Body::Struct(ref variant_data) => {
let (style, fields) = struct_from_ast(cx, variant_data);
(Body::Struct(style, fields), generics)
}
_ => {
return Err(Error::UnexpectedItemKind);
Body::Struct(style, fields)
}
};
Ok(Item {
ident: item.ident,
span: item.span,
Item {
ident: item.ident.clone(),
attrs: attrs,
body: body,
generics: generics,
})
generics: &item.generics,
}
}
}
@@ -86,16 +71,12 @@ impl<'a> Body<'a> {
}
}
fn enum_from_ast<'a>(
cx: &ExtCtxt,
enum_def: &'a ast::EnumDef,
) -> Vec<Variant<'a>> {
enum_def.variants.iter()
fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>> {
variants.iter()
.map(|variant| {
let (style, fields) = struct_from_ast(cx, &variant.node.data);
let (style, fields) = struct_from_ast(cx, &variant.data);
Variant {
ident: variant.node.name,
span: variant.span,
ident: variant.ident.clone(),
attrs: attr::Variant::from_ast(cx, variant),
style: style,
fields: fields,
@@ -104,36 +85,29 @@ fn enum_from_ast<'a>(
.collect()
}
fn struct_from_ast<'a>(
cx: &ExtCtxt,
variant_data: &'a ast::VariantData,
) -> (Style, Vec<Field<'a>>) {
match *variant_data {
ast::VariantData::Struct(ref fields, _) => {
fn struct_from_ast<'a>(cx: &Ctxt, data: &'a syn::VariantData) -> (Style, Vec<Field<'a>>) {
match *data {
syn::VariantData::Struct(ref fields) => {
(Style::Struct, fields_from_ast(cx, fields))
}
ast::VariantData::Tuple(ref fields, _) if fields.len() == 1 => {
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
(Style::Newtype, fields_from_ast(cx, fields))
}
ast::VariantData::Tuple(ref fields, _) => {
syn::VariantData::Tuple(ref fields) => {
(Style::Tuple, fields_from_ast(cx, fields))
}
ast::VariantData::Unit(_) => {
syn::VariantData::Unit => {
(Style::Unit, Vec::new())
}
}
}
fn fields_from_ast<'a>(
cx: &ExtCtxt,
fields: &'a [ast::StructField],
) -> Vec<Field<'a>> {
fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field]) -> Vec<Field<'a>> {
fields.iter()
.enumerate()
.map(|(i, field)| {
Field {
ident: field.ident,
span: field.span,
ident: field.ident.clone(),
attrs: attr::Field::from_ast(cx, i, field),
ty: &field.ty,
}
+192 -287
View File
@@ -1,16 +1,7 @@
use std::rc::Rc;
use syntax::ast;
use syntax::attr::{self, HasAttrs};
use syntax::codemap::{Span, Spanned, respan};
use syntax::ext::base::ExtCtxt;
use syntax::fold::Folder;
use syntax::parse::parser::{Parser, PathStyle};
use syntax::parse::token::{self, InternedString};
use syntax::parse;
use syntax::print::pprust::{lit_to_string, meta_item_to_string};
use syntax::ptr::P;
use syntax::tokenstream::{self, TokenTree};
use Ctxt;
use syn;
use syn::MetaItem::{List, NameValue, Word};
use syn::NestedMetaItem::{Literal, MetaItem};
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
// are `attr::Item::from_ast`, `attr::Variant::from_ast`, and
@@ -20,13 +11,14 @@ use syntax::tokenstream::{self, TokenTree};
// user will see errors simultaneously for all bad attributes in the crate
// rather than just the first.
struct Attr<'a, 'b: 'a, T> {
cx: &'a ExtCtxt<'b>,
struct Attr<'c, T> {
cx: &'c Ctxt,
name: &'static str,
value: Option<Spanned<T>>,
value: Option<T>,
}
impl<'a, 'b, T> Attr<'a, 'b, T> {
fn none(cx: &'a ExtCtxt<'b>, name: &'static str) -> Self {
impl<'c, T> Attr<'c, T> {
fn none(cx: &'c Ctxt, name: &'static str) -> Self {
Attr {
cx: cx,
name: name,
@@ -34,47 +26,40 @@ impl<'a, 'b, T> Attr<'a, 'b, T> {
}
}
fn set(&mut self, span: Span, t: T) {
if let Some(Spanned { span: prev_span, .. }) = self.value {
let mut err = self.cx.struct_span_err(
span,
&format!("duplicate serde attribute `{}`", self.name));
err.span_help(prev_span, "previously set here");
err.emit();
fn set(&mut self, value: T) {
if self.value.is_some() {
self.cx.error(format!("duplicate serde attribute `{}`", self.name));
} else {
self.value = Some(respan(span, t));
self.value = Some(value);
}
}
fn set_opt(&mut self, v: Option<Spanned<T>>) {
if let Some(v) = v {
self.set(v.span, v.node);
fn set_opt(&mut self, value: Option<T>) {
if let Some(value) = value {
self.set(value);
}
}
fn set_if_none(&mut self, span: Span, t: T) {
fn set_if_none(&mut self, value: T) {
if self.value.is_none() {
self.value = Some(respan(span, t));
self.value = Some(value);
}
}
fn get(self) -> Option<T> {
self.value.map(|spanned| spanned.node)
}
fn get_spanned(self) -> Option<Spanned<T>> {
self.value
}
}
struct BoolAttr<'a, 'b: 'a>(Attr<'a, 'b, ()>);
impl<'a, 'b> BoolAttr<'a, 'b> {
fn none(cx: &'a ExtCtxt<'b>, name: &'static str) -> Self {
struct BoolAttr<'c>(Attr<'c, ()>);
impl<'c> BoolAttr<'c> {
fn none(cx: &'c Ctxt, name: &'static str) -> Self {
BoolAttr(Attr::none(cx, name))
}
fn set_true(&mut self, span: Span) {
self.0.set(span, ());
fn set_true(&mut self) {
self.0.set(());
}
fn get(&self) -> bool {
@@ -84,18 +69,18 @@ impl<'a, 'b> BoolAttr<'a, 'b> {
#[derive(Debug)]
pub struct Name {
serialize: InternedString,
deserialize: InternedString,
serialize: String,
deserialize: String,
}
impl Name {
/// Return the container name for the container when serializing.
pub fn serialize_name(&self) -> InternedString {
pub fn serialize_name(&self) -> String {
self.serialize.clone()
}
/// Return the container name for the container when deserializing.
pub fn deserialize_name(&self) -> InternedString {
pub fn deserialize_name(&self) -> String {
self.deserialize.clone()
}
}
@@ -105,35 +90,32 @@ impl Name {
pub struct Item {
name: Name,
deny_unknown_fields: bool,
ser_bound: Option<Vec<ast::WherePredicate>>,
de_bound: Option<Vec<ast::WherePredicate>>,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
}
impl Item {
/// Extract out the `#[serde(...)]` attributes from an item.
pub fn from_ast(cx: &ExtCtxt, item: &ast::Item) -> Self {
pub fn from_ast(cx: &Ctxt, item: &syn::MacroInput) -> Self {
let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename");
let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields");
let mut ser_bound = Attr::none(cx, "bound");
let mut de_bound = Attr::none(cx, "bound");
let ident = item.ident.name.as_str();
for meta_items in item.attrs().iter().filter_map(get_serde_meta_items) {
for meta_items in item.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
let span = meta_item.span;
match meta_item.node {
match meta_item {
// Parse `#[serde(rename="foo")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"rename" => {
if let Ok(s) = get_str_from_lit(cx, name, lit) {
ser_name.set(span, s.clone());
de_name.set(span, s);
MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
ser_name.set(s.clone());
de_name.set(s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"rename" => {
MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser);
de_name.set_opt(de);
@@ -141,31 +123,33 @@ impl Item {
}
// Parse `#[serde(deny_unknown_fields)]`
ast::MetaItemKind::Word(ref name) if name == &"deny_unknown_fields" => {
deny_unknown_fields.set_true(span);
MetaItem(Word(ref name)) if name == "deny_unknown_fields" => {
deny_unknown_fields.set_true();
}
// Parse `#[serde(bound="D: Serialize")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"bound" => {
if let Ok(where_predicates) = parse_lit_into_where(cx, name, lit) {
ser_bound.set(span, where_predicates.clone());
de_bound.set(span, where_predicates);
MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
}
}
// Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"bound" => {
MetaItem(List(ref name, ref meta_items)) if name == "bound" => {
if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
ser_bound.set_opt(ser);
de_bound.set_opt(de);
}
}
_ => {
cx.span_err(
meta_item.span,
&format!("unknown serde container attribute `{}`",
meta_item_to_string(meta_item)));
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde container attribute `{}`",
meta_item.name()));
}
Literal(_) => {
cx.error(format!("unexpected literal in serde container attribute"));
}
}
}
@@ -173,8 +157,8 @@ impl Item {
Item {
name: Name {
serialize: ser_name.get().unwrap_or(ident.clone()),
deserialize: de_name.get().unwrap_or(ident),
serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()),
deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()),
},
deny_unknown_fields: deny_unknown_fields.get(),
ser_bound: ser_bound.get(),
@@ -190,11 +174,11 @@ impl Item {
self.deny_unknown_fields
}
pub fn ser_bound(&self) -> Option<&[ast::WherePredicate]> {
pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
self.ser_bound.as_ref().map(|vec| &vec[..])
}
pub fn de_bound(&self) -> Option<&[ast::WherePredicate]> {
pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
}
@@ -203,40 +187,51 @@ impl Item {
#[derive(Debug)]
pub struct Variant {
name: Name,
skip_deserializing: bool,
skip_serializing: bool,
}
impl Variant {
pub fn from_ast(cx: &ExtCtxt, variant: &ast::Variant) -> Self {
pub fn from_ast(cx: &Ctxt, variant: &syn::Variant) -> Self {
let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename");
let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing");
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
let ident = variant.node.name.name.as_str();
for meta_items in variant.node.attrs.iter().filter_map(get_serde_meta_items) {
for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
let span = meta_item.span;
match meta_item.node {
match meta_item {
// Parse `#[serde(rename="foo")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"rename" => {
if let Ok(s) = get_str_from_lit(cx, name, lit) {
ser_name.set(span, s.clone());
de_name.set(span, s);
MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
ser_name.set(s.clone());
de_name.set(s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"rename" => {
MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser);
de_name.set_opt(de);
}
}
// Parse `#[serde(skip_deserializing)]`
MetaItem(Word(ref name)) if name == "skip_deserializing" => {
skip_deserializing.set_true();
}
// Parse `#[serde(skip_serializing)]`
MetaItem(Word(ref name)) if name == "skip_serializing" => {
skip_serializing.set_true();
}
_ => {
cx.span_err(
meta_item.span,
&format!("unknown serde variant attribute `{}`",
meta_item_to_string(meta_item)));
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde variant attribute `{}`",
meta_item.name()));
}
Literal(_) => {
cx.error(format!("unexpected literal in serde variant attribute"));
}
}
}
@@ -244,15 +239,25 @@ impl Variant {
Variant {
name: Name {
serialize: ser_name.get().unwrap_or(ident.clone()),
deserialize: de_name.get().unwrap_or(ident),
serialize: ser_name.get().unwrap_or_else(|| variant.ident.to_string()),
deserialize: de_name.get().unwrap_or_else(|| variant.ident.to_string()),
},
skip_deserializing: skip_deserializing.get(),
skip_serializing: skip_serializing.get(),
}
}
pub fn name(&self) -> &Name {
&self.name
}
pub fn skip_deserializing(&self) -> bool {
self.skip_deserializing
}
pub fn skip_serializing(&self) -> bool {
self.skip_serializing
}
}
/// Represents field attribute information
@@ -261,12 +266,12 @@ pub struct Field {
name: Name,
skip_serializing: bool,
skip_deserializing: bool,
skip_serializing_if: Option<ast::Path>,
skip_serializing_if: Option<syn::Path>,
default: FieldDefault,
serialize_with: Option<ast::Path>,
deserialize_with: Option<ast::Path>,
ser_bound: Option<Vec<ast::WherePredicate>>,
de_bound: Option<Vec<ast::WherePredicate>>,
serialize_with: Option<syn::Path>,
deserialize_with: Option<syn::Path>,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
}
/// Represents the default to use for a field when deserializing.
@@ -277,14 +282,14 @@ pub enum FieldDefault {
/// The default is given by `std::default::Default::default()`.
Default,
/// The default is given by this function.
Path(ast::Path),
Path(syn::Path),
}
impl Field {
/// Extract out the `#[serde(...)]` attributes from a struct field.
pub fn from_ast(cx: &ExtCtxt,
pub fn from_ast(cx: &Ctxt,
index: usize,
field: &ast::StructField) -> Self {
field: &syn::Field) -> Self {
let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename");
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
@@ -297,24 +302,23 @@ impl Field {
let mut de_bound = Attr::none(cx, "bound");
let ident = match field.ident {
Some(ident) => ident.name.as_str(),
None => token::intern_and_get_ident(&index.to_string()),
Some(ref ident) => ident.to_string(),
None => index.to_string(),
};
for meta_items in field.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
let span = meta_item.span;
match meta_item.node {
match meta_item {
// Parse `#[serde(rename="foo")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"rename" => {
if let Ok(s) = get_str_from_lit(cx, name, lit) {
ser_name.set(span, s.clone());
de_name.set(span, s);
MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
ser_name.set(s.clone());
de_name.set(s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"rename" => {
MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser);
de_name.set_opt(de);
@@ -322,69 +326,71 @@ impl Field {
}
// Parse `#[serde(default)]`
ast::MetaItemKind::Word(ref name) if name == &"default" => {
default.set(span, FieldDefault::Default);
MetaItem(Word(ref name)) if name == "default" => {
default.set(FieldDefault::Default);
}
// Parse `#[serde(default="...")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"default" => {
if let Ok(path) = parse_lit_into_path(cx, name, lit) {
default.set(span, FieldDefault::Path(path));
MetaItem(NameValue(ref name, ref lit)) if name == "default" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
default.set(FieldDefault::Path(path));
}
}
// Parse `#[serde(skip_serializing)]`
ast::MetaItemKind::Word(ref name) if name == &"skip_serializing" => {
skip_serializing.set_true(span);
MetaItem(Word(ref name)) if name == "skip_serializing" => {
skip_serializing.set_true();
}
// Parse `#[serde(skip_deserializing)]`
ast::MetaItemKind::Word(ref name) if name == &"skip_deserializing" => {
skip_deserializing.set_true(span);
MetaItem(Word(ref name)) if name == "skip_deserializing" => {
skip_deserializing.set_true();
}
// Parse `#[serde(skip_serializing_if="...")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"skip_serializing_if" => {
if let Ok(path) = parse_lit_into_path(cx, name, lit) {
skip_serializing_if.set(span, path);
MetaItem(NameValue(ref name, ref lit)) if name == "skip_serializing_if" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
skip_serializing_if.set(path);
}
}
// Parse `#[serde(serialize_with="...")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"serialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, name, lit) {
serialize_with.set(span, path);
MetaItem(NameValue(ref name, ref lit)) if name == "serialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
serialize_with.set(path);
}
}
// Parse `#[serde(deserialize_with="...")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"deserialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, name, lit) {
deserialize_with.set(span, path);
MetaItem(NameValue(ref name, ref lit)) if name == "deserialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
deserialize_with.set(path);
}
}
// Parse `#[serde(bound="D: Serialize")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"bound" => {
if let Ok(where_predicates) = parse_lit_into_where(cx, name, lit) {
ser_bound.set(span, where_predicates.clone());
de_bound.set(span, where_predicates);
MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
}
}
// Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"bound" => {
MetaItem(List(ref name, ref meta_items)) if name == "bound" => {
if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
ser_bound.set_opt(ser);
de_bound.set_opt(de);
}
}
_ => {
cx.span_err(
meta_item.span,
&format!("unknown serde field attribute `{}`",
meta_item_to_string(meta_item)));
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde field attribute `{}`",
meta_item.name()));
}
Literal(_) => {
cx.error(format!("unexpected literal in serde field attribute"));
}
}
}
@@ -392,8 +398,8 @@ impl Field {
// Is skip_deserializing, initialize the field to Default::default()
// unless a different default is specified by `#[serde(default="...")]`
if let Some(Spanned { span, .. }) = skip_deserializing.0.value {
default.set_if_none(span, FieldDefault::Default);
if skip_deserializing.0.value.is_some() {
default.set_if_none(FieldDefault::Default);
}
Field {
@@ -424,7 +430,7 @@ impl Field {
self.skip_deserializing
}
pub fn skip_serializing_if(&self) -> Option<&ast::Path> {
pub fn skip_serializing_if(&self) -> Option<&syn::Path> {
self.skip_serializing_if.as_ref()
}
@@ -432,207 +438,106 @@ impl Field {
&self.default
}
pub fn serialize_with(&self) -> Option<&ast::Path> {
pub fn serialize_with(&self) -> Option<&syn::Path> {
self.serialize_with.as_ref()
}
pub fn deserialize_with(&self) -> Option<&ast::Path> {
pub fn deserialize_with(&self) -> Option<&syn::Path> {
self.deserialize_with.as_ref()
}
pub fn ser_bound(&self) -> Option<&[ast::WherePredicate]> {
pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
self.ser_bound.as_ref().map(|vec| &vec[..])
}
pub fn de_bound(&self) -> Option<&[ast::WherePredicate]> {
pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
}
type SerAndDe<T> = (Option<T>, Option<T>);
fn get_ser_and_de<T, F>(
cx: &ExtCtxt,
attribute: &'static str,
items: &[P<ast::MetaItem>],
cx: &Ctxt,
attr_name: &'static str,
items: &[syn::NestedMetaItem],
f: F
) -> Result<(Option<Spanned<T>>, Option<Spanned<T>>), ()>
where F: Fn(&ExtCtxt, &str, &ast::Lit) -> Result<T, ()>,
) -> Result<SerAndDe<T>, ()>
where F: Fn(&Ctxt, &str, &str, &syn::Lit) -> Result<T, ()>,
{
let mut ser_item = Attr::none(cx, attribute);
let mut de_item = Attr::none(cx, attribute);
let mut ser_item = Attr::none(cx, attr_name);
let mut de_item = Attr::none(cx, attr_name);
for item in items {
match item.node {
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"serialize" => {
if let Ok(v) = f(cx, name, lit) {
ser_item.set(item.span, v);
match *item {
MetaItem(NameValue(ref name, ref lit)) if name == "serialize" => {
if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) {
ser_item.set(v);
}
}
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"deserialize" => {
if let Ok(v) = f(cx, name, lit) {
de_item.set(item.span, v);
MetaItem(NameValue(ref name, ref lit)) if name == "deserialize" => {
if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) {
de_item.set(v);
}
}
_ => {
cx.span_err(
item.span,
&format!("unknown {} attribute `{}`",
attribute,
meta_item_to_string(item)));
cx.error(format!("malformed {0} attribute, expected `{0}(serialize = ..., deserialize = ...)`",
attr_name));
return Err(());
}
}
}
Ok((ser_item.get_spanned(), de_item.get_spanned()))
Ok((ser_item.get(), de_item.get()))
}
fn get_renames(
cx: &ExtCtxt,
items: &[P<ast::MetaItem>],
) -> Result<(Option<Spanned<InternedString>>, Option<Spanned<InternedString>>), ()> {
get_ser_and_de(cx, "rename", items, get_str_from_lit)
cx: &Ctxt,
items: &[syn::NestedMetaItem],
) -> Result<SerAndDe<String>, ()> {
get_ser_and_de(cx, "rename", items, get_string_from_lit)
}
fn get_where_predicates(
cx: &ExtCtxt,
items: &[P<ast::MetaItem>],
) -> Result<(Option<Spanned<Vec<ast::WherePredicate>>>, Option<Spanned<Vec<ast::WherePredicate>>>), ()> {
cx: &Ctxt,
items: &[syn::NestedMetaItem],
) -> Result<SerAndDe<Vec<syn::WherePredicate>>, ()> {
get_ser_and_de(cx, "bound", items, parse_lit_into_where)
}
pub fn get_serde_meta_items(attr: &ast::Attribute) -> Option<&[P<ast::MetaItem>]> {
match attr.node.value.node {
ast::MetaItemKind::List(ref name, ref items) if name == &"serde" => {
attr::mark_used(&attr);
Some(items)
pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option<Vec<syn::NestedMetaItem>> {
match attr.value {
List(ref name, ref items) if name == "serde" => {
Some(items.iter().cloned().collect())
}
_ => None
}
}
/// This syntax folder rewrites tokens to say their spans are coming from a macro context.
struct Respanner<'a, 'b: 'a> {
cx: &'a ExtCtxt<'b>,
}
impl<'a, 'b> Folder for Respanner<'a, 'b> {
fn fold_tt(&mut self, tt: &TokenTree) -> TokenTree {
match *tt {
TokenTree::Token(span, ref tok) => {
TokenTree::Token(
self.new_span(span),
self.fold_token(tok.clone())
)
}
TokenTree::Delimited(span, ref delimed) => {
TokenTree::Delimited(
self.new_span(span),
Rc::new(tokenstream::Delimited {
delim: delimed.delim,
open_span: delimed.open_span,
tts: self.fold_tts(&delimed.tts),
close_span: delimed.close_span,
})
)
}
TokenTree::Sequence(span, ref seq) => {
TokenTree::Sequence(
self.new_span(span),
Rc::new(tokenstream::SequenceRepetition {
tts: self.fold_tts(&seq.tts),
separator: seq.separator.clone().map(|tok| self.fold_token(tok)),
..**seq
})
)
}
}
}
fn new_span(&mut self, span: Span) -> Span {
Span {
lo: span.lo,
hi: span.hi,
expn_id: self.cx.backtrace(),
}
fn get_string_from_lit(cx: &Ctxt, attr_name: &str, meta_item_name: &str, lit: &syn::Lit) -> Result<String, ()> {
if let syn::Lit::Str(ref s, _) = *lit {
Ok(s.clone())
} else {
cx.error(format!("expected serde {} attribute to be a string: `{} = \"...\"`",
attr_name, meta_item_name));
Err(())
}
}
fn get_str_from_lit(cx: &ExtCtxt, name: &str, lit: &ast::Lit) -> Result<InternedString, ()> {
match lit.node {
ast::LitKind::Str(ref s, _) => Ok(s.clone()),
_ => {
cx.span_err(
lit.span,
&format!("serde annotation `{}` must be a string, not `{}`",
name,
lit_to_string(lit)));
return Err(());
}
}
fn parse_lit_into_path(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::Path, ()> {
let string = try!(get_string_from_lit(cx, attr_name, attr_name, lit));
syn::parse_path(&string).map_err(|err| cx.error(err))
}
// If we just parse a string literal from an attibute, any syntax errors in the
// source will only have spans that point inside the string and not back to the
// attribute. So to have better error reporting, we'll first parse the string
// into a token tree. Then we'll update those spans to say they're coming from a
// macro context that originally came from the attribnute, and then finally
// parse them into an expression or where-clause.
fn parse_string_via_tts<T, F>(cx: &ExtCtxt, name: &str, string: String, action: F) -> Result<T, ()>
where F: for<'a> Fn(&'a mut Parser) -> parse::PResult<'a, T>,
{
let tts = panictry!(parse::parse_tts_from_source_str(
format!("<serde {} expansion>", name),
string,
cx.cfg(),
cx.parse_sess()));
// Respan the spans to say they are all coming from this macro.
let tts = Respanner { cx: cx }.fold_tts(&tts);
let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts);
let path = match action(&mut parser) {
Ok(path) => path,
Err(mut e) => {
e.emit();
return Err(());
}
};
// Make sure to error out if there are trailing characters in the stream.
match parser.expect(&token::Eof) {
Ok(()) => { }
Err(mut e) => {
e.emit();
return Err(());
}
}
Ok(path)
}
fn parse_lit_into_path(cx: &ExtCtxt, name: &str, lit: &ast::Lit) -> Result<ast::Path, ()> {
let string = try!(get_str_from_lit(cx, name, lit)).to_string();
parse_string_via_tts(cx, name, string, |parser| {
parser.parse_path(PathStyle::Type)
})
}
fn parse_lit_into_where(cx: &ExtCtxt, name: &str, lit: &ast::Lit) -> Result<Vec<ast::WherePredicate>, ()> {
let string = try!(get_str_from_lit(cx, name, lit));
fn parse_lit_into_where(cx: &Ctxt, attr_name: &str, meta_item_name: &str, lit: &syn::Lit) -> Result<Vec<syn::WherePredicate>, ()> {
let string = try!(get_string_from_lit(cx, attr_name, meta_item_name, lit));
if string.is_empty() {
return Ok(Vec::new());
}
let where_string = format!("where {}", string);
parse_string_via_tts(cx, name, where_string, |parser| {
let where_clause = try!(parser.parse_where_clause());
Ok(where_clause.predicates)
})
syn::parse_where_clause(&where_string).map(|wh| wh.predicates).map_err(|err| cx.error(err))
}
+43
View File
@@ -0,0 +1,43 @@
use std::fmt::Display;
use std::cell::RefCell;
#[derive(Default)]
pub struct Ctxt {
errors: RefCell<Option<Vec<String>>>,
}
impl Ctxt {
pub fn new() -> Self {
Ctxt {
errors: RefCell::new(Some(Vec::new())),
}
}
pub fn error<T: Display>(&self, msg: T) {
self.errors.borrow_mut().as_mut().unwrap().push(msg.to_string());
}
pub fn check(self) -> Result<(), String> {
let mut errors = self.errors.borrow_mut().take().unwrap();
match errors.len() {
0 => Ok(()),
1 => Err(errors.pop().unwrap()),
n => {
let mut msg = format!("{} errors:", n);
for err in errors {
msg.push_str("\n\t# ");
msg.push_str(&err);
}
Err(msg)
}
}
}
}
impl Drop for Ctxt {
fn drop(&mut self) {
if self.errors.borrow().is_some() {
panic!("forgot to check for errors");
}
}
}
-19
View File
@@ -1,19 +0,0 @@
use std::error;
use std::fmt;
#[derive(Debug)]
pub enum Error {
UnexpectedItemKind,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "expected a struct or enum")
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"expected a struct or enum"
}
}
+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.9.0-rc4"
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"]
[badges]
travis-ci = { repository = "serde-rs/serde" }
[lib]
name = "serde_derive"
proc-macro = true
[dependencies.serde_codegen]
version = "=0.9.0-rc4"
path = "../serde_codegen"
default-features = false
features = ["with-syn"]
[dev-dependencies]
compiletest_rs = "^0.2.0"
fnv = "1.0"
serde = { version = "0.9.0-rc4", path = "../serde" }
serde_test = { version = "0.9.0-rc4", path = "../serde_test" }
+8
View File
@@ -0,0 +1,8 @@
[package]
name = "serde_derive_tests_no_std"
version = "0.9.0-rc4"
publish = false
[dependencies]
serde = { path = "../../serde", default-features = false }
serde_derive = { path = ".." }
+50
View File
@@ -0,0 +1,50 @@
#![feature(lang_items, start, libc)]
#![no_std]
extern crate libc;
#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
#[lang = "eh_personality"]
#[no_mangle]
pub extern fn rust_eh_personality() {}
#[lang = "eh_unwind_resume"]
#[no_mangle]
pub extern fn rust_eh_unwind_resume() {}
#[lang = "panic_fmt"]
#[no_mangle]
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
_file: &'static str,
_line: u32) -> ! {
loop {}
}
//////////////////////////////////////////////////////////////////////////////
#[macro_use]
extern crate serde_derive;
#[derive(Serialize, Deserialize)]
struct Unit;
#[derive(Serialize, Deserialize)]
struct Newtype(u8);
#[derive(Serialize, Deserialize)]
struct Tuple(u8, u8);
#[derive(Serialize, Deserialize)]
struct Struct { f: u8 }
#[derive(Serialize, Deserialize)]
enum Enum {
Unit,
Newtype(u8),
Tuple(u8, u8),
Struct { f: u8 },
}
+20
View File
@@ -0,0 +1,20 @@
extern crate proc_macro;
extern crate serde_codegen;
use proc_macro::TokenStream;
#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
match serde_codegen::expand_derive_serialize(&input.to_string()) {
Ok(expanded) => expanded.parse().unwrap(),
Err(msg) => panic!(msg),
}
}
#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
match serde_codegen::expand_derive_deserialize(&input.to_string()) {
Ok(expanded) => expanded.parse().unwrap(),
Err(msg) => panic!(msg),
}
}
@@ -0,0 +1,10 @@
#[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,11 @@
#[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,10 @@
#[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,11 @@
#[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,10 @@
#[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,11 @@
#[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,9 @@
#[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,10 @@
#[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,10 @@
#[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,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
enum E {
#[serde(abc="xyz")] //~^^ HELP: unknown serde variant attribute `abc`
V,
}
fn main() { }
@@ -1,8 +1,8 @@
#![feature(custom_derive, plugin)]
#![plugin(serde_macros, clippy)]
#![deny(identity_op)]
#[macro_use]
extern crate serde_derive;
// The derived implementation uses 0+1 to add up the number of fields
// serialized, which Clippy warns about. If the expansion info is registered
// correctly, the Clippy lint is not triggered.
+10
View File
@@ -0,0 +1,10 @@
#![feature(test)]
#[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
-37
View File
@@ -1,37 +0,0 @@
[package]
name = "serde_macros"
version = "0.7.15"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
repository = "https://github.com/serde-rs/serde"
documentation = "https://github.com/serde-rs/serde"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[lib]
name = "serde_macros"
plugin = true
[features]
nightly-testing = ["clippy", "serde/nightly-testing", "serde_codegen/nightly-testing"]
[dependencies]
clippy = { version = "^0.*", optional = true }
serde_codegen = { version = "^0.7.15", default-features = false, features = ["nightly"] }
[dev-dependencies]
clippy = "^0.0.79"
compiletest_rs = "^0.2.0"
fnv = "1.0"
rustc-serialize = "^0.3.16"
serde = "0.7.15"
serde_test = "0.7.15"
[[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;
+7 -3
View File
@@ -1,14 +1,18 @@
[package]
name = "serde_test"
version = "0.7.15"
version = "0.9.0-rc4"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde-rs.github.io/serde/serde/"
documentation = "https://docs.serde.rs/serde_test/"
readme = "../README.md"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[dependencies]
serde = "0.7.15"
serde = { version = "0.9.0-rc4", path = "../serde" }
[badges]
travis-ci = { repository = "serde-rs/serde" }
+255 -202
View File
@@ -3,12 +3,14 @@ use std::iter;
use serde::de::{
self,
Deserialize,
DeserializeSeed,
EnumVisitor,
MapVisitor,
SeqVisitor,
VariantVisitor,
Visitor,
};
use serde::de::value::ValueDeserializer;
use error::Error;
use token::Token;
@@ -32,95 +34,207 @@ impl<I> Deserializer<I>
self.tokens.next()
}
fn visit_seq<V>(&mut self, len: Option<usize>, mut visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
visitor.visit_seq(DeserializerSeqVisitor {
de: self,
len: len,
})
pub fn expect_token(&mut self, expected: Token) -> Result<(), Error> {
match self.tokens.next() {
Some(token) => {
if expected == token {
Ok(())
} else {
Err(Error::UnexpectedToken(token))
}
}
None => Err(Error::EndOfTokens),
}
}
fn visit_array<V>(&mut self, len: usize, mut visitor: V) -> Result<V::Value, Error>
fn visit_seq<V>(&mut self, len: Option<usize>, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
visitor.visit_seq(DeserializerArrayVisitor {
let value = try!(visitor.visit_seq(DeserializerSeqVisitor {
de: self,
len: len,
})
}));
try!(self.expect_token(Token::SeqEnd));
Ok(value)
}
fn visit_tuple<V>(&mut self, len: usize, mut visitor: V) -> Result<V::Value, Error>
fn visit_array<V>(&mut self, len: usize, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
visitor.visit_seq(DeserializerTupleVisitor {
let value = try!(visitor.visit_seq(DeserializerArrayVisitor {
de: self,
len: len,
})
}));
try!(self.expect_token(Token::SeqEnd));
Ok(value)
}
fn visit_tuple_struct<V>(&mut self, len: usize, mut visitor: V) -> Result<V::Value, Error>
fn visit_tuple<V>(&mut self, len: usize, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
visitor.visit_seq(DeserializerTupleStructVisitor {
let value = try!(visitor.visit_seq(DeserializerTupleVisitor {
de: self,
len: len,
})
}));
try!(self.expect_token(Token::TupleEnd));
Ok(value)
}
fn visit_variant_seq<V>(&mut self, len: Option<usize>, mut visitor: V) -> Result<V::Value, Error>
fn visit_tuple_struct<V>(&mut self, len: usize, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
visitor.visit_seq(DeserializerVariantSeqVisitor {
let value = try!(visitor.visit_seq(DeserializerTupleStructVisitor {
de: self,
len: len,
})
}));
try!(self.expect_token(Token::TupleStructEnd));
Ok(value)
}
fn visit_map<V>(&mut self, len: Option<usize>, mut visitor: V) -> Result<V::Value, Error>
fn visit_variant_seq<V>(&mut self, len: Option<usize>, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
visitor.visit_map(DeserializerMapVisitor {
let value = try!(visitor.visit_seq(DeserializerVariantSeqVisitor {
de: self,
len: len,
})
}));
try!(self.expect_token(Token::EnumSeqEnd));
Ok(value)
}
fn visit_struct<V>(&mut self, len: Option<usize>, mut visitor: V) -> Result<V::Value, Error>
fn visit_map<V>(&mut self, len: Option<usize>, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
visitor.visit_map(DeserializerStructVisitor {
let value = try!(visitor.visit_map(DeserializerMapVisitor {
de: self,
len: len,
})
}));
try!(self.expect_token(Token::MapEnd));
Ok(value)
}
fn visit_variant_map<V>(&mut self, len: Option<usize>, mut visitor: V) -> Result<V::Value, Error>
fn visit_struct<V>(&mut self, fields: &'static [&'static str], visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
visitor.visit_map(DeserializerVariantMapVisitor {
let value = try!(visitor.visit_map(DeserializerStructVisitor {
de: self,
len: fields.len(),
}));
try!(self.expect_token(Token::StructEnd));
Ok(value)
}
fn visit_variant_map<V>(&mut self, len: Option<usize>, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
let value = try!(visitor.visit_map(DeserializerVariantMapVisitor {
de: self,
len: len,
})
}));
try!(self.expect_token(Token::EnumMapEnd));
Ok(value)
}
}
impl<I> de::Deserializer for Deserializer<I>
impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize_seq<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_struct_field<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_map<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_unit<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_bytes<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_byte_buf<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_ignored_any<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_string<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_str<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_char<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i64<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i32<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i16<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i8<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u64<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u32<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u16<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u8<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_f32<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_f64<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_bool<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.tokens.next() {
Some(Token::Bool(v)) => visitor.visit_bool(v),
Some(Token::Isize(v)) => visitor.visit_isize(v),
Some(Token::I8(v)) => visitor.visit_i8(v),
Some(Token::I16(v)) => visitor.visit_i16(v),
Some(Token::I32(v)) => visitor.visit_i32(v),
Some(Token::I64(v)) => visitor.visit_i64(v),
Some(Token::Usize(v)) => visitor.visit_usize(v),
Some(Token::U8(v)) => visitor.visit_u8(v),
Some(Token::U16(v)) => visitor.visit_u16(v),
Some(Token::U32(v)) => visitor.visit_u32(v),
@@ -131,27 +245,31 @@ impl<I> de::Deserializer for Deserializer<I>
Some(Token::Str(v)) => visitor.visit_str(v),
Some(Token::String(v)) => visitor.visit_string(v),
Some(Token::Bytes(v)) => visitor.visit_bytes(v),
Some(Token::ByteBuf(v)) => visitor.visit_byte_buf(v),
Some(Token::Option(false)) => visitor.visit_none(),
Some(Token::Option(true)) => visitor.visit_some(self),
Some(Token::Unit) => visitor.visit_unit(),
Some(Token::UnitStruct(name)) => visitor.visit_unit_struct(name),
Some(Token::SeqStart(len)) | Some(Token::TupleStructStart(_, len)) => {
Some(Token::UnitStruct(_name)) => visitor.visit_unit(),
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),
None => Err(Error::EndOfTokens),
}
}
/// Hook into `Option` deserializing so we can treat `Unit` as a
/// `None`, or a regular value as `Some(value)`.
fn deserialize_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.tokens.peek() {
@@ -168,21 +286,21 @@ impl<I> de::Deserializer for Deserializer<I>
visitor.visit_none()
}
Some(_) => visitor.visit_some(self),
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
fn deserialize_enum<V>(&mut self,
fn deserialize_enum<V>(self,
name: &str,
_variants: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Error>
where V: EnumVisitor,
visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.tokens.peek() {
Some(&Token::EnumStart(n)) if name == n => {
self.tokens.next();
visitor.visit(DeserializerVariantVisitor {
visitor.visit_enum(DeserializerEnumVisitor {
de: self,
})
}
@@ -190,7 +308,7 @@ impl<I> de::Deserializer for Deserializer<I>
| Some(&Token::EnumNewType(n, _))
| Some(&Token::EnumSeqStart(n, _, _))
| Some(&Token::EnumMapStart(n, _, _)) if name == n => {
visitor.visit(DeserializerVariantVisitor {
visitor.visit_enum(DeserializerEnumVisitor {
de: self,
})
}
@@ -198,11 +316,11 @@ impl<I> de::Deserializer for Deserializer<I>
let token = self.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => { return Err(Error::EndOfStream); }
None => { return Err(Error::EndOfTokens); }
}
}
fn deserialize_unit_struct<V>(&mut self, name: &str, mut visitor: V) -> Result<V::Value, Error>
fn deserialize_unit_struct<V>(self, name: &str, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.tokens.peek() {
@@ -215,13 +333,13 @@ impl<I> de::Deserializer for Deserializer<I>
}
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
fn deserialize_newtype_struct<V>(&mut self,
fn deserialize_newtype_struct<V>(self,
name: &str,
mut visitor: V) -> Result<V::Value, Error>
visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.tokens.peek() {
@@ -234,11 +352,11 @@ impl<I> de::Deserializer for Deserializer<I>
}
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
fn deserialize_fixed_size_array<V>(&mut self,
fn deserialize_seq_fixed_size<V>(self,
len: usize,
visitor: V) -> Result<V::Value, Error>
where V: Visitor,
@@ -249,13 +367,13 @@ impl<I> de::Deserializer for Deserializer<I>
self.visit_array(len, visitor)
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
fn deserialize_tuple<V>(&mut self,
fn deserialize_tuple<V>(self,
len: usize,
mut visitor: V) -> Result<V::Value, Error>
visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.tokens.peek() {
@@ -284,14 +402,14 @@ impl<I> de::Deserializer for Deserializer<I>
self.visit_tuple_struct(len, visitor)
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
fn deserialize_tuple_struct<V>(&mut self,
fn deserialize_tuple_struct<V>(self,
name: &str,
len: usize,
mut visitor: V) -> Result<V::Value, Error>
visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.tokens.peek() {
@@ -328,11 +446,11 @@ impl<I> de::Deserializer for Deserializer<I>
}
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
fn deserialize_struct<V>(&mut self,
fn deserialize_struct<V>(self,
name: &str,
fields: &'static [&'static str],
visitor: V) -> Result<V::Value, Error>
@@ -342,7 +460,7 @@ impl<I> de::Deserializer for Deserializer<I>
Some(&Token::StructStart(n, _)) => {
self.tokens.next();
if name == n {
self.visit_struct(Some(fields.len()), visitor)
self.visit_struct(fields, visitor)
} else {
Err(Error::InvalidName(n))
}
@@ -352,7 +470,7 @@ impl<I> de::Deserializer for Deserializer<I>
self.visit_map(Some(fields.len()), visitor)
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
}
@@ -369,30 +487,21 @@ impl<'a, I> SeqVisitor for DeserializerSeqVisitor<'a, I>
{
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: Deserialize,
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where T: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::SeqSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| len - 1);
Ok(Some(try!(Deserialize::deserialize(self.de))))
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::SeqEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStream),
}
}
fn end(&mut self) -> Result<(), Error> {
//assert_eq!(self.len.unwrap_or(0), 0);
match self.de.tokens.next() {
Some(Token::SeqEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
@@ -414,30 +523,21 @@ impl<'a, I> SeqVisitor for DeserializerArrayVisitor<'a, I>
{
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: Deserialize,
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where T: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::SeqSep) => {
self.de.tokens.next();
self.len -= 1;
Ok(Some(try!(Deserialize::deserialize(self.de))))
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::SeqEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStream),
}
}
fn end(&mut self) -> Result<(), Error> {
assert_eq!(self.len, 0);
match self.de.tokens.next() {
Some(Token::SeqEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
@@ -458,30 +558,21 @@ impl<'a, I> SeqVisitor for DeserializerTupleVisitor<'a, I>
{
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: Deserialize,
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where T: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::TupleSep) => {
self.de.tokens.next();
self.len -= 1;
Ok(Some(try!(Deserialize::deserialize(self.de))))
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::TupleEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStream),
}
}
fn end(&mut self) -> Result<(), Error> {
assert_eq!(self.len, 0);
match self.de.tokens.next() {
Some(Token::TupleEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
@@ -502,30 +593,21 @@ impl<'a, I> SeqVisitor for DeserializerTupleStructVisitor<'a, I>
{
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: Deserialize,
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where T: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::TupleStructSep) => {
self.de.tokens.next();
self.len -= 1;
Ok(Some(try!(Deserialize::deserialize(self.de))))
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::TupleStructEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStream),
}
}
fn end(&mut self) -> Result<(), Error> {
assert_eq!(self.len, 0);
match self.de.tokens.next() {
Some(Token::TupleStructEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
@@ -546,30 +628,21 @@ impl<'a, I> SeqVisitor for DeserializerVariantSeqVisitor<'a, I>
{
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: Deserialize,
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where T: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::EnumSeqSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| len - 1);
Ok(Some(try!(Deserialize::deserialize(self.de))))
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::EnumSeqEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStream),
}
}
fn end(&mut self) -> Result<(), Error> {
//assert_eq!(self.len.unwrap_or(0), 0);
match self.de.tokens.next() {
Some(Token::EnumSeqEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
@@ -591,37 +664,28 @@ impl<'a, I> MapVisitor for DeserializerMapVisitor<'a, I>
{
type Error = Error;
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
where K: Deserialize,
fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where K: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::MapSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| if len > 0 { len - 1} else { 0 });
Ok(Some(try!(Deserialize::deserialize(self.de))))
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::MapEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
fn visit_value<V>(&mut self) -> Result<V, Error>
where V: Deserialize,
fn visit_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
where V: DeserializeSeed,
{
Ok(try!(Deserialize::deserialize(self.de)))
}
fn end(&mut self) -> Result<(), Error> {
//assert_eq!(self.len.unwrap_or(0), 0);
match self.de.tokens.next() {
Some(Token::MapEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
}
seed.deserialize(&mut *self.de)
}
fn size_hint(&self) -> (usize, Option<usize>) {
@@ -634,7 +698,7 @@ impl<'a, I> MapVisitor for DeserializerMapVisitor<'a, I>
struct DeserializerStructVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: Option<usize>,
len: usize,
}
impl<'a, I> MapVisitor for DeserializerStructVisitor<'a, I>
@@ -642,76 +706,74 @@ impl<'a, I> MapVisitor for DeserializerStructVisitor<'a, I>
{
type Error = Error;
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
where K: Deserialize,
fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where K: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::StructSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| if len > 0 { len - 1} else { 0 });
Ok(Some(try!(Deserialize::deserialize(self.de))))
self.len = self.len.saturating_sub(1);
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::StructEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
fn visit_value<V>(&mut self) -> Result<V, Error>
where V: Deserialize,
fn visit_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
where V: DeserializeSeed,
{
Ok(try!(Deserialize::deserialize(self.de)))
}
fn end(&mut self) -> Result<(), Error> {
//assert_eq!(self.len.unwrap_or(0), 0);
match self.de.tokens.next() {
Some(Token::StructEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
}
seed.deserialize(&mut *self.de)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len.unwrap_or(0);
(len, self.len)
(self.len, Some(self.len))
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerVariantVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
struct DeserializerEnumVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
}
impl<'a, I> VariantVisitor for DeserializerVariantVisitor<'a, I>
impl<'a, I> EnumVisitor for DeserializerEnumVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
type Variant = Self;
fn visit_variant<V>(&mut self) -> Result<V, Error>
where V: Deserialize,
fn visit_variant_seed<V>(self, seed: V) -> Result<(V::Value, Self), Error>
where V: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::EnumUnit(_, v))
| Some(&Token::EnumNewType(_, v))
| Some(&Token::EnumSeqStart(_, v, _))
| Some(&Token::EnumMapStart(_, v, _)) => {
let mut de = de::value::ValueDeserializer::<Error>::into_deserializer(v);
let value = try!(Deserialize::deserialize(&mut de));
Ok(value)
let de = v.into_deserializer();
let value = try!(seed.deserialize(de));
Ok((value, self))
}
Some(_) => {
Deserialize::deserialize(self.de)
let value = try!(seed.deserialize(&mut *self.de));
Ok((value, self))
}
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
}
fn visit_unit(&mut self) -> Result<(), Error> {
impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I>
where I: Iterator<Item=Token<'static>>
{
type Error = Error;
fn visit_unit(self) -> Result<(), Error> {
match self.de.tokens.peek() {
Some(&Token::EnumUnit(_, _)) => {
self.de.tokens.next();
@@ -720,32 +782,32 @@ impl<'a, I> VariantVisitor for DeserializerVariantVisitor<'a, I>
Some(_) => {
Deserialize::deserialize(self.de)
}
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
where T: Deserialize,
fn visit_newtype_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
where T: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::EnumNewType(_, _)) => {
self.de.tokens.next();
Deserialize::deserialize(self.de)
seed.deserialize(self.de)
}
Some(_) => {
Deserialize::deserialize(self.de)
seed.deserialize(self.de)
}
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
fn visit_tuple<V>(&mut self,
fn visit_tuple<V>(self,
len: usize,
visitor: V) -> Result<V::Value, Error>
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 {
@@ -764,19 +826,19 @@ impl<'a, I> VariantVisitor for DeserializerVariantVisitor<'a, I>
}
}
Some(_) => {
Deserialize::deserialize(self.de)
de::Deserializer::deserialize(self.de, visitor)
}
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
fn visit_struct<V>(&mut self,
fn visit_struct<V>(self,
fields: &'static [&'static str],
visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
match self.de.tokens.peek() {
Some(&Token::EnumMapStart(_, _, Some(enum_len))) => {
Some(&Token::EnumMapStart(_, _, enum_len)) => {
let token = self.de.tokens.next().unwrap();
if fields.len() == enum_len {
@@ -795,9 +857,9 @@ impl<'a, I> VariantVisitor for DeserializerVariantVisitor<'a, I>
}
}
Some(_) => {
Deserialize::deserialize(self.de)
de::Deserializer::deserialize(self.de, visitor)
}
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
}
@@ -814,37 +876,28 @@ impl<'a, I> MapVisitor for DeserializerVariantMapVisitor<'a, I>
{
type Error = Error;
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
where K: Deserialize,
fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where K: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::EnumMapSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| if len > 0 { len - 1} else { 0 });
Ok(Some(try!(Deserialize::deserialize(self.de))))
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::EnumMapEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStream),
None => Err(Error::EndOfTokens),
}
}
fn visit_value<V>(&mut self) -> Result<V, Error>
where V: Deserialize,
fn visit_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
where V: DeserializeSeed,
{
Ok(try!(Deserialize::deserialize(self.de)))
}
fn end(&mut self) -> Result<(), Error> {
//assert_eq!(self.len.unwrap_or(0), 0);
match self.de.tokens.next() {
Some(Token::EnumMapEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStream),
}
seed.deserialize(&mut *self.de)
}
fn size_hint(&self) -> (usize, Option<usize>) {
+21 -60
View File
@@ -1,4 +1,5 @@
use std::{error, fmt};
use std::error;
use std::fmt::{self, Display};
use serde::{ser, de};
@@ -6,82 +7,42 @@ use token::Token;
#[derive(Clone, PartialEq, Debug)]
pub enum Error {
// Shared
Custom(String),
InvalidValue(String),
// De
EndOfStream,
InvalidType(de::Type),
InvalidLength(usize),
UnknownVariant(String),
UnknownField(String),
MissingField(&'static str),
DuplicateField(&'static str),
Message(String),
InvalidName(&'static str),
UnexpectedToken(Token<'static>),
EndOfTokens,
}
impl ser::Error for Error {
fn custom<T: Into<String>>(msg: T) -> Error {
Error::Custom(msg.into())
}
fn invalid_value(msg: &str) -> Error {
Error::InvalidValue(msg.to_owned())
fn custom<T: Display>(msg: T) -> Error {
Error::Message(msg.to_string())
}
}
impl de::Error for Error {
fn custom<T: Into<String>>(msg: T) -> Error {
Error::Custom(msg.into())
}
fn end_of_stream() -> Error {
Error::EndOfStream
}
fn invalid_type(ty: de::Type) -> Error {
Error::InvalidType(ty)
}
fn invalid_value(msg: &str) -> Error {
Error::InvalidValue(msg.to_owned())
}
fn invalid_length(len: usize) -> Error {
Error::InvalidLength(len)
}
fn unknown_variant(variant: &str) -> Error {
Error::UnknownVariant(variant.to_owned())
}
fn unknown_field(field: &str) -> Error {
Error::UnknownField(field.to_owned())
}
fn missing_field(field: &'static str) -> Error {
Error::MissingField(field)
}
fn duplicate_field(field: &'static str) -> Error {
Error::DuplicateField(field)
fn custom<T: Display>(msg: T) -> Error {
Error::Message(msg.to_string())
}
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(format!("{:?}", self).as_ref())
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Message(ref msg) => formatter.write_str(msg),
Error::InvalidName(name) => write!(formatter, "invalid name `{}`", name),
Error::UnexpectedToken(_) => formatter.write_str("unexpected token"),
Error::EndOfTokens => formatter.write_str("end of tokens"),
}
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Error"
}
fn cause(&self) -> Option<&error::Error> {
None
match *self {
Error::Message(ref msg) => msg,
Error::InvalidName(_) => "invalid name",
Error::UnexpectedToken(_) => "unexpected token",
Error::EndOfTokens => "end of tokens",
}
}
}
+228 -232
View File
@@ -1,11 +1,6 @@
use std::marker::PhantomData;
use serde::ser::{
self,
MapVisitor,
SeqVisitor,
Serialize,
};
use serde::{ser, Serialize};
use error::Error;
use token::Token;
@@ -30,321 +25,322 @@ 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>
impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
{
type Ok = ();
type Error = Error;
fn serialize_unit(&mut self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Unit));
Ok(())
}
type SerializeSeq = Self;
type SerializeTuple = Self;
type SerializeTupleStruct = Self;
type SerializeTupleVariant = Self;
type SerializeMap = Self;
type SerializeStruct = Self;
type SerializeStructVariant = Self;
fn serialize_newtype_variant<T>(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::EnumNewType(name, variant)));
value.serialize(self)
}
fn serialize_unit_struct(&mut self, name: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::UnitStruct(name)));
Ok(())
}
fn serialize_unit_variant(&mut self,
name: &str,
_variant_index: usize,
variant: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumUnit(name, variant)));
Ok(())
}
fn serialize_bool(&mut self, v: bool) -> Result<(), Error> {
fn serialize_bool(self, v: bool) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Bool(v)));
Ok(())
}
fn serialize_isize(&mut self, v: isize) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Isize(v)));
Ok(())
}
fn serialize_i8(&mut self, v: i8) -> Result<(), Error> {
fn serialize_i8(self, v: i8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I8(v)));
Ok(())
}
fn serialize_i16(&mut self, v: i16) -> Result<(), Error> {
fn serialize_i16(self, v: i16) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I16(v)));
Ok(())
}
fn serialize_i32(&mut self, v: i32) -> Result<(), Error> {
fn serialize_i32(self, v: i32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I32(v)));
Ok(())
}
fn serialize_i64(&mut self, v: i64) -> Result<(), Error> {
fn serialize_i64(self, v: i64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I64(v)));
Ok(())
}
fn serialize_usize(&mut self, v: usize) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Usize(v)));
Ok(())
}
fn serialize_u8(&mut self, v: u8) -> Result<(), Error> {
fn serialize_u8(self, v: u8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U8(v)));
Ok(())
}
fn serialize_u16(&mut self, v: u16) -> Result<(), Error> {
fn serialize_u16(self, v: u16) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U16(v)));
Ok(())
}
fn serialize_u32(&mut self, v: u32) -> Result<(), Error> {
fn serialize_u32(self, v: u32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U32(v)));
Ok(())
}
fn serialize_u64(&mut self, v: u64) -> Result<(), Error> {
fn serialize_u64(self, v: u64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U64(v)));
Ok(())
}
fn serialize_f32(&mut self, v: f32) -> Result<(), Error> {
fn serialize_f32(self, v: f32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::F32(v)));
Ok(())
}
fn serialize_f64(&mut self, v: f64) -> Result<(), Error> {
fn serialize_f64(self, v: f64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::F64(v)));
Ok(())
}
fn serialize_char(&mut self, v: char) -> Result<(), Error> {
fn serialize_char(self, v: char) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Char(v)));
Ok(())
}
fn serialize_str(&mut self, v: &str) -> Result<(), Error> {
fn serialize_str(self, v: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Str(v)));
Ok(())
}
fn serialize_none(&mut self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Option(false)));
fn serialize_bytes(self, value: &[u8]) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::Bytes(value)));
Ok(())
}
fn serialize_some<V>(&mut self, value: V) -> Result<(), Error>
where V: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::Option(true)));
value.serialize(self)
}
fn serialize_seq<V>(&mut self, visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::SeqStart(len)));
self.visit_seq(visitor)
}
fn serialize_fixed_size_array<V>(&mut self, visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
let len = visitor.len().expect("arrays must have a length");
assert_eq!(self.tokens.next(), Some(&Token::SeqArrayStart(len)));
self.visit_seq(visitor)
}
fn serialize_seq_elt<T>(&mut self, value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::SeqSep));
value.serialize(self)
}
fn serialize_tuple<V>(&mut self, mut visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
let len = visitor.len().expect("arrays must have a length");
assert_eq!(self.tokens.next(), Some(&Token::TupleStart(len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::TupleEnd));
fn serialize_unit(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Unit));
Ok(())
}
fn serialize_tuple_elt<T>(&mut self, value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::TupleSep));
value.serialize(self)
fn serialize_unit_struct(self, name: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::UnitStruct(name)));
Ok(())
}
fn serialize_newtype_struct<T>(&mut self,
name: &'static str,
value: T) -> Result<(), Error>
fn serialize_unit_variant(self,
name: &str,
_variant_index: usize,
variant: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumUnit(name, variant)));
Ok(())
}
fn serialize_newtype_struct<T: ?Sized>(self,
name: &'static str,
value: &T) -> Result<(), Error>
where T: Serialize,
{
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_newtype_variant<T: ?Sized>(self,
name: &str,
_variant_index: usize,
variant: &str,
value: &T) -> Result<(), Error>
where T: Serialize,
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::EnumNewType(name, variant)));
value.serialize(self)
}
fn serialize_none(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Option(false)));
Ok(())
}
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::Option(true)));
value.serialize(self)
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::SeqStart(len)));
Ok(self)
}
fn serialize_seq_fixed_size(self, len: usize) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::SeqArrayStart(len)));
Ok(self)
}
fn serialize_tuple(self, len: usize) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleStart(len)));
Ok(self)
}
fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
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(())
Ok(self)
}
fn serialize_tuple_struct_elt<T>(&mut self, value: T) -> Result<(), Error>
where T: Serialize,
fn serialize_tuple_variant(self,
name: &str,
_variant_index: usize,
variant: &str,
len: usize) -> Result<Self, Error>
{
assert_eq!(self.tokens.next(), Some(&Token::TupleStructSep));
value.serialize(self)
}
fn serialize_tuple_variant<V>(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
mut visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqStart(name, variant, len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqEnd));
Ok(())
Ok(self)
}
fn serialize_tuple_variant_elt<T>(&mut self, value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqSep));
value.serialize(self)
}
fn serialize_map<V>(&mut self, visitor: V) -> Result<(), Error>
where V: MapVisitor
{
let len = visitor.len();
fn serialize_map(self, len: Option<usize>) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::MapStart(len)));
self.visit_map(visitor)
Ok(self)
}
fn serialize_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Error>
where K: Serialize,
V: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::MapSep));
try!(key.serialize(self));
value.serialize(self)
}
fn serialize_struct<V>(&mut self, name: &str, mut visitor: V) -> Result<(), Error>
where V: MapVisitor
{
let len = visitor.len();
fn serialize_struct(self, name: &str, len: usize) -> Result<Self, 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(())
Ok(self)
}
fn serialize_struct_elt<T>(&mut self, key: &'static str, value: T) -> Result<(), Error>
where T: Serialize,
fn serialize_struct_variant(self,
name: &str,
_variant_index: usize,
variant: &str,
len: usize) -> Result<Self, Error>
{
assert_eq!(self.tokens.next(), Some(&Token::StructSep));
try!(key.serialize(self));
value.serialize(self)
}
fn serialize_struct_variant<V>(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
mut visitor: V) -> Result<(), Error>
where V: MapVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::EnumMapStart(name, variant, len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::EnumMapEnd));
Ok(())
}
fn serialize_struct_variant_elt<T>(&mut self, key: &'static str, value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::EnumMapSep));
try!(key.serialize(self));
value.serialize(self)
Ok(self)
}
}
impl<'s, 'a, I> ser::SerializeSeq for &'s mut Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
{
type Ok = ();
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::SeqSep));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::SeqEnd));
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeTuple for &'s mut Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
{
type Ok = ();
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::TupleSep));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleEnd));
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeTupleStruct for &'s mut Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
{
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::TupleStructSep));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleStructEnd));
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeTupleVariant for &'s mut Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
{
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqSep));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqEnd));
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeMap for &'s mut Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
{
type Ok = ();
type Error = Error;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error> where T: Serialize {
assert_eq!(self.tokens.next(), Some(&Token::MapSep));
key.serialize(&mut **self)
}
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> where T: Serialize {
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::MapEnd));
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeStruct for &'s mut Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
{
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where T: Serialize {
assert_eq!(self.tokens.next(), Some(&Token::StructSep));
try!(key.serialize(&mut **self));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::StructEnd));
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeStructVariant for &'s mut Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
{
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where T: Serialize {
assert_eq!(self.tokens.next(), Some(&Token::EnumMapSep));
try!(key.serialize(&mut **self));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumMapEnd));
Ok(())
}
}
+5 -6
View File
@@ -1,12 +1,10 @@
#[derive(Clone, PartialEq, Debug)]
pub enum Token<'a> {
Bool(bool),
Isize(isize),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
Usize(usize),
U8(u8),
U16(u16),
U32(u32),
@@ -17,6 +15,7 @@ pub enum Token<'a> {
Str(&'a str),
String(String),
Bytes(&'a [u8]),
ByteBuf(Vec<u8>),
Option(bool),
@@ -38,7 +37,7 @@ pub enum Token<'a> {
TupleSep,
TupleEnd,
TupleStructStart(&'a str, Option<usize>),
TupleStructStart(&'a str, usize),
TupleStructSep,
TupleStructEnd,
@@ -46,15 +45,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,
}
+8 -10
View File
@@ -1,26 +1,28 @@
[package]
name = "serde_testing"
version = "0.7.15"
version = "0.9.0-rc4"
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"
publish = false
[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 = "*", features = ["with-syntex"] }
serde_codegen = { path = "../serde_codegen", features = ["with-syntex"] }
[dev-dependencies]
fnv = "1.0"
rustc-serialize = "^0.3.16"
serde = "*"
serde_test = "*"
serde = { path = "../serde" }
serde_test = { path = "../serde_test" }
[dependencies]
clippy = { version = "^0.*", optional = true }
@@ -28,7 +30,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();
}
+4 -2
View File
@@ -1,4 +1,6 @@
#![cfg_attr(feature = "nightly", feature(plugin))]
#![cfg_attr(feature = "nightly", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "unstable-testing", feature(non_ascii_idents))]
include!(concat!(env!("OUT_DIR"), "/test.rs"));
+3
View File
@@ -1,3 +1,6 @@
extern crate serde;
extern crate serde_test;
#[macro_use]
mod macros;
+48 -48
View File
@@ -20,12 +20,12 @@ trait ShouldSkip: Sized {
}
trait SerializeWith: Sized {
fn serialize_with<S>(&self, ser: &mut S) -> Result<(), S::Error>
fn serialize_with<S>(&self, ser: S) -> Result<S::Ok, S::Error>
where S: Serializer;
}
trait DeserializeWith: Sized {
fn deserialize_with<D>(de: &mut D) -> Result<Self, D::Error>
fn deserialize_with<D>(de: D) -> Result<Self, D::Error>
where D: Deserializer;
}
@@ -38,7 +38,7 @@ impl ShouldSkip for i32 {
}
impl SerializeWith for i32 {
fn serialize_with<S>(&self, ser: &mut S) -> Result<(), S::Error>
fn serialize_with<S>(&self, ser: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
if *self == 123 {
@@ -50,7 +50,7 @@ impl SerializeWith for i32 {
}
impl DeserializeWith for i32 {
fn deserialize_with<D>(de: &mut D) -> Result<Self, D::Error>
fn deserialize_with<D>(de: D) -> Result<Self, D::Error>
where D: Deserializer
{
if try!(Deserialize::deserialize(de)) {
@@ -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", 3),
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", 3),
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"),
@@ -239,7 +239,7 @@ impl Default for NotDeserializeStruct {
}
impl DeserializeWith for NotDeserializeStruct {
fn deserialize_with<D>(_: &mut D) -> Result<Self, D::Error>
fn deserialize_with<D>(_: D) -> Result<Self, D::Error>
where D: Deserializer
{
panic!()
@@ -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"),
@@ -343,7 +343,7 @@ fn test_ignore_unknown() {
Token::StructSep,
Token::Str("whoops"),
],
Error::UnknownField("whoops".to_owned())
Error::Message("unknown field `whoops`, expected `a1`".to_owned())
);
}
@@ -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"),
@@ -642,7 +642,7 @@ struct NotSerializeStruct(i8);
enum NotSerializeEnum { Trouble }
impl SerializeWith for NotSerializeEnum {
fn serialize_with<S>(&self, ser: &mut S) -> Result<(), S::Error>
fn serialize_with<S>(&self, ser: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
"trouble".serialize(ser)
@@ -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"),
@@ -905,12 +905,12 @@ fn test_missing_renamed_field_struct() {
Token::StructEnd,
],
Error::MissingField("a3"),
Error::Message("missing field `a3`".to_owned()),
);
assert_de_tokens_error::<RenameStructSerializeDeserialize>(
&[
Token::StructStart("SuperheroDe", Some(2)),
Token::StructStart("SuperheroDe", 2),
Token::StructSep,
Token::Str("a1"),
@@ -918,7 +918,7 @@ fn test_missing_renamed_field_struct() {
Token::StructEnd,
],
Error::MissingField("a5"),
Error::Message("missing field `a5`".to_owned()),
);
}
@@ -926,16 +926,16 @@ 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,
],
Error::MissingField("b"),
Error::Message("missing field `b`".to_owned()),
);
assert_de_tokens_error::<RenameEnumSerializeDeserialize<i8>>(
&[
Token::EnumMapStart("SuperheroDe", "jason_todd", Some(2)),
Token::EnumMapStart("SuperheroDe", "jason_todd", 2),
Token::EnumMapSep,
Token::Str("a"),
@@ -943,7 +943,7 @@ fn test_missing_renamed_field_enum() {
Token::EnumMapEnd,
],
Error::MissingField("d"),
Error::Message("missing field `d`".to_owned()),
);
}
@@ -957,20 +957,20 @@ enum InvalidLengthEnum {
fn test_invalid_length_enum() {
assert_de_tokens_error::<InvalidLengthEnum>(
&[
Token::EnumSeqStart("InvalidLengthEnum", "A", Some(3)),
Token::EnumSeqStart("InvalidLengthEnum", "A", 3),
Token::EnumSeqSep,
Token::I32(1),
Token::EnumSeqEnd,
],
Error::InvalidLength(1),
Error::Message("invalid length 1, expected tuple of 3 elements".to_owned()),
);
assert_de_tokens_error::<InvalidLengthEnum>(
&[
Token::EnumSeqStart("InvalidLengthEnum", "B", Some(3)),
Token::EnumSeqStart("InvalidLengthEnum", "B", 3),
Token::EnumSeqSep,
Token::I32(1),
Token::EnumSeqEnd,
],
Error::InvalidLength(1),
Error::Message("invalid length 1, expected tuple of 2 elements".to_owned()),
);
}
+47 -177
View File
@@ -1,185 +1,55 @@
use std::fmt;
use std::error;
extern crate serde;
use self::serde::Serialize;
use self::serde::bytes::{ByteBuf, Bytes};
///////////////////////////////////////////////////////////////////////////////
#[derive(Debug, PartialEq)]
struct Error;
impl serde::ser::Error for Error {
fn custom<T: Into<String>>(_: T) -> Error { Error }
}
impl serde::de::Error for Error {
fn custom<T: Into<String>>(_: T) -> Error { Error }
fn end_of_stream() -> Error { Error }
}
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
}
}
///////////////////////////////////////////////////////////////////////////////
struct BytesSerializer {
bytes: Vec<u8>,
}
impl BytesSerializer {
fn new(bytes: Vec<u8>) -> Self {
BytesSerializer {
bytes: bytes,
}
}
}
impl serde::Serializer for BytesSerializer {
type Error = Error;
fn serialize_unit(&mut self) -> Result<(), Error> {
Err(Error)
}
fn serialize_bool(&mut self, _v: bool) -> Result<(), Error> {
Err(Error)
}
fn serialize_i64(&mut self, _v: i64) -> Result<(), Error> {
Err(Error)
}
fn serialize_u64(&mut self, _v: u64) -> Result<(), Error> {
Err(Error)
}
fn serialize_f32(&mut self, _v: f32) -> Result<(), Error> {
Err(Error)
}
fn serialize_f64(&mut self, _v: f64) -> Result<(), Error> {
Err(Error)
}
fn serialize_char(&mut self, _v: char) -> Result<(), Error> {
Err(Error)
}
fn serialize_str(&mut self, _v: &str) -> Result<(), Error> {
Err(Error)
}
fn serialize_none(&mut self) -> Result<(), Error> {
Err(Error)
}
fn serialize_some<V>(&mut self, _value: V) -> Result<(), Error>
where V: serde::Serialize,
{
Err(Error)
}
fn serialize_seq<V>(&mut self, _visitor: V) -> Result<(), Error>
where V: serde::ser::SeqVisitor,
{
Err(Error)
}
fn serialize_seq_elt<T>(&mut self, _value: T) -> Result<(), Error>
where T: serde::Serialize
{
Err(Error)
}
fn serialize_map<V>(&mut self, _visitor: V) -> Result<(), Error>
where V: serde::ser::MapVisitor,
{
Err(Error)
}
fn serialize_map_elt<K, V>(&mut self, _key: K, _value: V) -> Result<(), Error>
where K: serde::Serialize,
V: serde::Serialize,
{
Err(Error)
}
fn serialize_bytes(&mut self, bytes: &[u8]) -> Result<(), Error> {
assert_eq!(self.bytes, bytes);
Ok(())
}
}
///////////////////////////////////////////////////////////////////////////////
struct BytesDeserializer {
bytes: Option<Vec<u8>>,
}
impl BytesDeserializer {
fn new(bytes: Vec<u8>) -> Self {
BytesDeserializer {
bytes: Some(bytes),
}
}
}
impl serde::Deserializer for BytesDeserializer {
type Error = Error;
fn deserialize<V>(&mut self, _visitor: V) -> Result<V::Value, Error>
where V: serde::de::Visitor,
{
Err(Error)
}
fn deserialize_bytes<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: serde::de::Visitor,
{
visitor.visit_byte_buf(self.bytes.take().unwrap())
}
}
///////////////////////////////////////////////////////////////////////////////
use serde::bytes::{ByteBuf, Bytes};
use serde_test::{assert_tokens, assert_ser_tokens, assert_de_tokens, Token};
#[test]
fn test_bytes_ser_bytes() {
let buf = vec![];
let bytes = Bytes::from(&buf);
let mut ser = BytesSerializer::new(vec![]);
bytes.serialize(&mut ser).unwrap();
fn test_bytes() {
let empty = Bytes::new(&[]);
assert_ser_tokens(&empty, &[Token::Bytes(b"")]);
let buf = vec![1, 2, 3];
let bytes = Bytes::from(&buf);
let mut ser = BytesSerializer::new(vec![1, 2, 3]);
bytes.serialize(&mut ser).unwrap();
let buf = vec![65, 66, 67];
let bytes = Bytes::new(&buf);
assert_ser_tokens(&bytes, &[Token::Bytes(b"ABC")]);
}
///////////////////////////////////////////////////////////////////////////////
#[test]
fn test_byte_buf_de_bytes() {
let mut de = BytesDeserializer::new(vec![]);
let bytes = serde::Deserialize::deserialize(&mut de);
assert_eq!(bytes, Ok(ByteBuf::new()));
fn test_byte_buf() {
let empty = ByteBuf::new();
assert_tokens(&empty, &[Token::Bytes(b"")]);
assert_de_tokens(&empty, &[Token::ByteBuf(Vec::new())]);
assert_de_tokens(&empty, &[Token::Str("")]);
assert_de_tokens(&empty, &[Token::String(String::new())]);
assert_de_tokens(&empty, &[
Token::SeqStart(None),
Token::SeqEnd,
]);
assert_de_tokens(&empty, &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
]);
let mut de = BytesDeserializer::new(vec![1, 2, 3]);
let bytes = serde::Deserialize::deserialize(&mut de);
assert_eq!(bytes, Ok(ByteBuf::from(vec![1, 2, 3])));
let buf = ByteBuf::from(vec![65, 66, 67]);
assert_tokens(&buf, &[Token::Bytes(b"ABC")]);
assert_de_tokens(&buf, &[Token::ByteBuf(vec![65, 66, 67])]);
assert_de_tokens(&buf, &[Token::Str("ABC")]);
assert_de_tokens(&buf, &[Token::String("ABC".to_owned())]);
assert_de_tokens(&buf, &[
Token::SeqStart(None),
Token::SeqSep,
Token::U8(65),
Token::SeqSep,
Token::U8(66),
Token::SeqSep,
Token::U8(67),
Token::SeqEnd,
]);
assert_de_tokens(&buf, &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::U8(65),
Token::SeqSep,
Token::U8(66),
Token::SeqSep,
Token::U8(67),
Token::SeqEnd,
]);
}
+155 -32
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;
@@ -32,12 +32,43 @@ struct Struct {
c: i32,
}
#[derive(PartialEq, Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct StructDenyUnknown {
a: i32,
#[serde(skip_deserializing)]
b: i32,
}
#[derive(PartialEq, Debug, Deserialize)]
struct StructSkipAll {
#[serde(skip_deserializing)]
a: i32,
}
#[derive(PartialEq, Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct StructSkipAllDenyUnknown {
#[serde(skip_deserializing)]
a: i32,
}
#[derive(PartialEq, Debug, Deserialize)]
enum Enum {
#[allow(dead_code)]
#[serde(skip_deserializing)]
Skipped,
Unit,
Simple(i32),
Seq(i32, i32, i32),
Map { a: i32, b: i32, c: i32 }
Map { a: i32, b: i32, c: i32 },
}
#[derive(PartialEq, Debug, Deserialize)]
enum EnumSkipAll {
#[allow(dead_code)]
#[serde(skip_deserializing)]
Skipped,
}
//////////////////////////////////////////////////////////////////////////
@@ -81,9 +112,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 +122,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 +132,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);
}
@@ -124,12 +155,10 @@ declare_tests! {
false => &[Token::Bool(false)],
}
test_isize {
0isize => &[Token::Isize(0)],
0isize => &[Token::I8(0)],
0isize => &[Token::I16(0)],
0isize => &[Token::I32(0)],
0isize => &[Token::I64(0)],
0isize => &[Token::Usize(0)],
0isize => &[Token::U8(0)],
0isize => &[Token::U16(0)],
0isize => &[Token::U32(0)],
@@ -138,14 +167,12 @@ declare_tests! {
0isize => &[Token::F64(0.)],
}
test_ints {
0isize => &[Token::Isize(0)],
0i8 => &[Token::I8(0)],
0i16 => &[Token::I16(0)],
0i32 => &[Token::I32(0)],
0i64 => &[Token::I64(0)],
}
test_uints {
0usize => &[Token::Usize(0)],
0u8 => &[Token::U8(0)],
0u16 => &[Token::U16(0)],
0u32 => &[Token::U32(0)],
@@ -197,7 +224,7 @@ declare_tests! {
Token::SeqEnd,
],
() => &[
Token::TupleStructStart("Anything", Some(0)),
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
],
}
@@ -215,6 +242,9 @@ declare_tests! {
Token::SeqEnd,
],
}
test_unit_string {
String::new() => &[Token::Unit],
}
test_tuple_struct {
TupleStruct(1, 2, 3) => &[
Token::SeqStart(Some(3)),
@@ -241,7 +271,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 +283,7 @@ declare_tests! {
Token::TupleStructEnd,
],
TupleStruct(1, 2, 3) => &[
Token::TupleStructStart("TupleStruct", None),
Token::TupleStructStart("TupleStruct", 3),
Token::TupleStructSep,
Token::I32(1),
@@ -299,7 +329,7 @@ declare_tests! {
Token::UnitStruct("Anything"),
],
BTreeSet::<isize>::new() => &[
Token::TupleStructStart("Anything", Some(0)),
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
],
}
@@ -327,7 +357,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 +407,7 @@ declare_tests! {
Token::UnitStruct("Anything"),
],
Vec::<isize>::new() => &[
Token::TupleStructStart("Anything", Some(0)),
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
],
}
@@ -441,7 +471,7 @@ declare_tests! {
Token::UnitStruct("Anything"),
],
[0; 0] => &[
Token::TupleStructStart("Anything", Some(0)),
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
],
}
@@ -533,7 +563,7 @@ declare_tests! {
Token::UnitStruct("Anything"),
],
BTreeMap::<isize, isize>::new() => &[
Token::StructStart("Anything", Some(0)),
Token::StructStart("Anything", 0),
Token::MapEnd,
],
}
@@ -587,7 +617,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 +645,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 +686,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),
@@ -675,6 +705,29 @@ declare_tests! {
Token::StructEnd,
],
}
test_struct_skip_all {
StructSkipAll { a: 0 } => &[
Token::StructStart("StructSkipAll", 0),
Token::StructEnd,
],
StructSkipAll { a: 0 } => &[
Token::StructStart("StructSkipAll", 1),
Token::StructSep,
Token::Str("a"),
Token::I32(1),
Token::StructSep,
Token::Str("b"),
Token::I32(2),
Token::StructEnd,
],
}
test_struct_skip_all_deny_unknown {
StructSkipAllDenyUnknown { a: 0 } => &[
Token::StructStart("StructSkipAllDenyUnknown", 0),
Token::StructEnd,
],
}
test_enum_unit {
Enum::Unit => &[
Token::EnumUnit("Enum", "Unit"),
@@ -688,7 +741,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 +755,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),
@@ -720,7 +773,7 @@ declare_tests! {
test_enum_unit_usize {
Enum::Unit => &[
Token::EnumStart("Enum"),
Token::Usize(0),
Token::U32(0),
Token::Unit,
],
}
@@ -746,6 +799,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 +839,7 @@ declare_tests! {
}
}
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
#[test]
fn test_net_ipaddr() {
assert_de_tokens(
@@ -774,11 +849,51 @@ fn test_net_ipaddr() {
}
declare_error_tests! {
test_unknown_field<StructDenyUnknown> {
&[
Token::StructStart("StructDenyUnknown", 2),
Token::StructSep,
Token::Str("a"),
Token::I32(0),
Token::StructSep,
Token::Str("d"),
],
Error::Message("unknown field `d`, expected `a`".to_owned()),
}
test_skipped_field_is_unknown<StructDenyUnknown> {
&[
Token::StructStart("StructDenyUnknown", 2),
Token::StructSep,
Token::Str("b"),
],
Error::Message("unknown field `b`, expected `a`".to_owned()),
}
test_skip_all_deny_unknown<StructSkipAllDenyUnknown> {
&[
Token::StructStart("StructSkipAllDenyUnknown", 1),
Token::StructSep,
Token::Str("a"),
],
Error::Message("unknown field `a`, there are no fields".to_owned()),
}
test_unknown_variant<Enum> {
&[
Token::EnumUnit("Enum", "Foo"),
],
Error::UnknownVariant("Foo".to_owned()),
Error::Message("unknown variant `Foo`, expected one of `Unit`, `Simple`, `Seq`, `Map`".to_owned()),
}
test_enum_skipped_variant<Enum> {
&[
Token::EnumUnit("Enum", "Skipped"),
],
Error::Message("unknown variant `Skipped`, expected one of `Unit`, `Simple`, `Seq`, `Map`".to_owned()),
}
test_enum_skip_all<EnumSkipAll> {
&[
Token::EnumUnit("EnumSkipAll", "Skipped"),
],
Error::Message("unknown variant `Skipped`, there are no variants".to_owned()),
}
test_struct_seq_too_long<Struct> {
&[
@@ -799,11 +914,11 @@ declare_error_tests! {
Token::MapSep,
Token::Str("a"),
],
Error::DuplicateField("a"),
Error::Message("duplicate field `a`".to_owned()),
}
test_duplicate_field_enum<Enum> {
&[
Token::EnumMapStart("Enum", "Map", Some(3)),
Token::EnumMapStart("Enum", "Map", 3),
Token::EnumMapSep,
Token::Str("a"),
Token::I32(1),
@@ -811,6 +926,14 @@ declare_error_tests! {
Token::EnumMapSep,
Token::Str("a"),
],
Error::DuplicateField("a"),
Error::Message("duplicate field `a`".to_owned()),
}
test_enum_out_of_range<Enum> {
&[
Token::EnumStart("Enum"),
Token::U32(4),
Token::Unit,
],
Error::Message("invalid value: integer `4`, expected variant index 0 <= i < 4".into()),
}
}
+293 -101
View File
@@ -6,129 +6,321 @@ 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>();
#[cfg(feature = "unstable-testing")]
#[cfg_attr(feature = "unstable-testing", derive(Serialize, Deserialize))]
struct NonAsciiIdents {
σ: f64
}
#[derive(Serialize, Deserialize)]
struct EmptyBraced {}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct EmptyBracedDenyUnknown {}
#[derive(Serialize, Deserialize)]
struct BracedSkipAll {
#[serde(skip_deserializing)]
f: u8,
}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct BracedSkipAllDenyUnknown {
#[serde(skip_deserializing)]
f: u8,
}
#[cfg(feature = "unstable-testing")]
#[cfg_attr(feature = "unstable-testing", derive(Serialize, Deserialize))]
struct EmptyTuple();
#[cfg(feature = "unstable-testing")]
#[cfg_attr(feature = "unstable-testing", derive(Serialize, Deserialize))]
#[serde(deny_unknown_fields)]
struct EmptyTupleDenyUnknown();
#[derive(Serialize, Deserialize)]
struct TupleSkipAll(#[serde(skip_deserializing)] u8);
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct TupleSkipAllDenyUnknown(#[serde(skip_deserializing)] u8);
#[derive(Serialize, Deserialize)]
enum EmptyEnum {}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
enum EmptyEnumDenyUnknown {}
#[derive(Serialize, Deserialize)]
enum EnumSkipAll {
#[serde(skip_deserializing)]
#[allow(dead_code)]
Variant,
}
#[cfg(feature = "unstable-testing")]
#[cfg_attr(feature = "unstable-testing", derive(Serialize, Deserialize))]
enum EmptyVariants {
Braced {},
Tuple(),
BracedSkip {
#[serde(skip_deserializing)]
f: u8,
},
TupleSkip(#[serde(skip_deserializing)] u8),
}
#[cfg(feature = "unstable-testing")]
#[cfg_attr(feature = "unstable-testing", derive(Serialize, Deserialize))]
#[serde(deny_unknown_fields)]
enum EmptyVariantsDenyUnknown {
Braced {},
Tuple(),
BracedSkip {
#[serde(skip_deserializing)]
f: u8,
},
TupleSkip(#[serde(skip_deserializing)] u8),
}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct UnitDenyUnknown;
}
//////////////////////////////////////////////////////////////////////////
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, _: S) -> StdResult<S::Ok, S::Error>;
}
trait DeserializeWith: Sized {
fn deserialize_with<D: Deserializer>(_: &mut D) -> Result<Self, D::Error>;
fn deserialize_with<D: Deserializer>(_: 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, _: S) -> StdResult<S::Ok, S::Error> {
unimplemented!()
}
fn de_x<D: Deserializer>(_: D) -> StdResult<X, D::Error> {
unimplemented!()
}
impl SerializeWith for X {
fn serialize_with<S: Serializer>(_: &Self, _: S) -> StdResult<S::Ok, S::Error> {
unimplemented!()
}
}
impl DeserializeWith for X {
fn deserialize_with<D: Deserializer>(_: 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,
]
);
}
+96 -10
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::{
@@ -14,6 +15,9 @@ use self::serde_test::{
extern crate fnv;
use self::fnv::FnvHasher;
#[cfg(feature = "unstable")]
use serde::ser::iterator;
//////////////////////////////////////////////////////////////////////////
#[derive(Serialize)]
@@ -29,12 +33,20 @@ struct Struct {
c: i32,
}
#[derive(Serialize)]
#[derive(Serialize, PartialEq, Debug)]
enum Enum {
Unit,
One(i32),
Seq(i32, i32),
Map { a: i32, b: i32 },
#[serde(skip_serializing)]
SkippedUnit,
#[serde(skip_serializing)]
SkippedOne(i32),
#[serde(skip_serializing)]
SkippedSeq(i32, i32),
#[serde(skip_serializing)]
SkippedMap { _a: i32, _b: i32 },
}
//////////////////////////////////////////////////////////////////////////
@@ -48,14 +60,12 @@ declare_ser_tests! {
false => &[Token::Bool(false)],
}
test_isizes {
0isize => &[Token::Isize(0)],
0i8 => &[Token::I8(0)],
0i16 => &[Token::I16(0)],
0i32 => &[Token::I32(0)],
0i64 => &[Token::I64(0)],
}
test_usizes {
0usize => &[Token::Usize(0)],
0u8 => &[Token::U8(0)],
0u16 => &[Token::U16(0)],
0u32 => &[Token::U32(0)],
@@ -256,7 +266,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 +280,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 +299,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 +308,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 +334,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 +370,50 @@ declare_ser_tests! {
}
}
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
#[test]
fn test_iterator() {
assert_ser_tokens(iterator([0; 0].iter()), &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
]);
assert_ser_tokens(iterator([1, 2, 3].iter()), &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(1),
Token::SeqSep,
Token::I32(2),
Token::SeqSep,
Token::I32(3),
Token::SeqEnd,
]);
assert_ser_tokens(iterator([1, 2, 3].iter().map(|x| x * 2)), &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(2),
Token::SeqSep,
Token::I32(4),
Token::SeqSep,
Token::I32(6),
Token::SeqEnd,
]);
assert_ser_tokens(iterator([1, 2, 3].iter().filter(|&x| x % 2 != 0)), &[
Token::SeqStart(None),
Token::SeqSep,
Token::I32(1),
Token::SeqSep,
Token::I32(3),
Token::SeqEnd,
]);
}
#[cfg(feature = "unstable")]
#[test]
fn test_net_ipaddr() {
assert_ser_tokens(
@@ -364,7 +430,7 @@ fn test_cannot_serialize_paths() {
assert_ser_tokens_error(
&Path::new(path),
&[],
Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned()));
Error::Message("path contains invalid UTF-8 characters".to_owned()));
let mut path_buf = PathBuf::new();
path_buf.push(path);
@@ -372,5 +438,25 @@ fn test_cannot_serialize_paths() {
assert_ser_tokens_error(
&path_buf,
&[],
Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned()));
Error::Message("path contains invalid UTF-8 characters".to_owned()));
}
#[test]
fn test_enum_skipped() {
assert_ser_tokens_error(
&Enum::SkippedUnit,
&[],
Error::Message("the enum variant Enum::SkippedUnit cannot be serialized".to_owned()));
assert_ser_tokens_error(
&Enum::SkippedOne(42),
&[],
Error::Message("the enum variant Enum::SkippedOne cannot be serialized".to_owned()));
assert_ser_tokens_error(
&Enum::SkippedSeq(1, 2),
&[],
Error::Message("the enum variant Enum::SkippedSeq cannot be serialized".to_owned()));
assert_ser_tokens_error(
&Enum::SkippedMap { _a: 1, _b: 2 },
&[],
Error::Message("the enum variant Enum::SkippedMap cannot be serialized".to_owned()));
}