Compare commits

...

1434 Commits

Author SHA1 Message Date
David Tolnay c47b4c8e0b Release 1.0.7 2017-05-19 17:00:31 -07:00
David Tolnay 2d793b82f6 Merge pull request #940 from BurntSushi/ag-deser-borrowed
add borrowed value deserializers
2017-05-19 16:59:55 -07:00
Andrew Gallant 237be46e29 add borrowed value deserializers
This adds two new types to the `de::value` module,
`BorrowedStrDeserializer` and `BorrowedBytesDeserializer`. A
`BorrowedStrDeserializer` is just like `StrDeserializer`, except the
lifetime of the string is tied to the lifetime of the deserializer. This
can be useful when, for example, deserializing into a
`HashMap<&str, &str>` when the keys/values are tied to the deserializer
itself.

The `BorrowedBytesDeserializer` has no analog, but it's the same as
`BorrowedStrDeserialize` except for `&[u8]` instead of `&str`.
2017-05-19 19:55:34 -04:00
David Tolnay 3d7aad1e7b Release 1.0.6 2017-05-17 08:20:54 -07:00
David Tolnay e792874369 Merge pull request #935 from spikefoo/combined-skip
Add a combined skip attribute
2017-05-16 09:13:49 -07:00
spikefoo 1669c69714 Add a combined #serde[(skip)] field attribute 2017-05-16 12:33:26 +03:00
David Tolnay 4d5e450054 Release 1.0.5 2017-05-14 12:53:48 -07:00
David Tolnay 26b22e647d Merge pull request #933 from serde-rs/contentstr
Fix internally tagged struct variant containing unit variant containing borrowed string
2017-05-14 12:53:07 -07:00
David Tolnay cda1fc46b0 Fix internally tagged struct variant containing unit variant containing borrowed string 2017-05-14 12:39:42 -07:00
David Tolnay c68b959696 Release 1.0.4 2017-05-10 20:05:22 -07:00
David Tolnay eab80172e4 Merge pull request #926 from serde-rs/borrow
Support borrowing within internally tagged enum
2017-05-10 20:04:36 -07:00
David Tolnay c1259fbc87 Support borrowing within internally tagged enum 2017-05-10 19:56:05 -07:00
David Tolnay 58e30eaee4 Release 1.0.3 2017-05-10 10:15:39 -07:00
David Tolnay bafa941004 Merge pull request #924 from pshc/deserialize-borrowed-path
impl Deserialize for &'a Path
2017-05-10 10:14:25 -07:00
Paul Collier f347b2d363 impl Deserialize for &'a Path 2017-05-10 13:03:03 -04:00
David Tolnay 3f9fc49cca Merge pull request #922 from serde-rs/nonzero
Removed Deref impl for NonZero
2017-05-09 19:58:17 -07:00
David Tolnay c913527944 Removed Deref impl for NonZero 2017-05-09 19:48:54 -07:00
David Tolnay 8fafc7420c Release 1.0.2 2017-04-27 12:32:30 -07:00
David Tolnay bea1c5b0f5 Remove trailing whitespace 2017-04-27 12:31:13 -07:00
David Tolnay aa37caf216 Merge pull request #905 from TedDriggs/adjacent_tag_enums
Fix #816 - adjacently-tagged enums honor deny_unknown_fields
2017-04-27 12:27:31 -07:00
Ted Driggs 2440b59aae Address feedback on PR #905
* Added error test when deny_unknown_fields enabled
* Fixed next_relevant_key to use absolute paths
2017-04-27 12:21:32 -07:00
Ted Driggs 873cfbe9ab Fix #816 - adjacently-tagged enums honor deny_unknown_fields 2017-04-27 11:24:09 -07:00
David Tolnay c96efcb87a Merge pull request #900 from SuperFluffy/macro_to_derive_input
Replace deprecated MacroInput; completes c52e131
2017-04-25 08:10:26 -07:00
Richard Janis Goldschmidt b53026a21b Replace deprecated MacroInput; completes c52e13 2017-04-25 11:08:56 +02:00
David Tolnay c7901e532e Release 1.0.1 2017-04-23 16:40:56 -07:00
David Tolnay 2af0701be6 Merge tag 'v0.9.15' into 'origin/master' 2017-04-23 16:39:32 -07:00
David Tolnay ae79451b7a Release 0.9.15 2017-04-23 16:37:43 -07:00
David Tolnay b220f264a5 Merge pull request #898 from SimonSapin/z-is-dead
Remove usage of unstable core::num::Zero, which was removed upstream.
2017-04-23 16:35:57 -07:00
David Tolnay 1a2b3815ef Merge pull request #899 from SimonSapin/z-is-dead-in-0.9-too
Remove usage of unstable core::num::Zero, which was removed upstream.
2017-04-23 16:34:06 -07:00
Simon Sapin 6fbf40b83c Remove usage of unstable core::num::Zero, which was removed upstream.
https://github.com/rust-lang/rust/pull/41437
2017-04-24 08:29:38 +09:00
Simon Sapin 1d6ecf3c2c Remove usage of unstable core::num::Zero, which was removed upstream.
https://github.com/rust-lang/rust/pull/41437

Backport of https://github.com/serde-rs/serde/pull/898 to 0.9.x
2017-04-24 08:25:08 +09:00
David Tolnay d7ccef0cac Release 1.0.0 2017-04-20 08:19:31 -07:00
David Tolnay 2d465415c5 Take credit 2017-04-20 08:13:46 -07:00
David Tolnay bc2d637112 Cut an internals release 2017-04-20 08:11:31 -07:00
David Tolnay cf1cdadc77 Fix some rustfmt screwups 2017-04-19 15:56:22 -07:00
David Tolnay 4a9cb3395d Fix the serialize_bytes doc test 2017-04-19 15:03:02 -07:00
David Tolnay dfa6623a24 Encourage serialize_entry 2017-04-19 14:56:52 -07:00
David Tolnay a8adac6b93 Document misuse of SerializeMap 2017-04-19 14:55:28 -07:00
David Tolnay b9b7922ef1 Naming for &str and &[u8] is more like primitives 2017-04-19 14:53:15 -07:00
David Tolnay a369ee156f Run serde_test doc tests in Travis 2017-04-19 14:45:06 -07:00
David Tolnay d1253cb193 Minimal serde_derive documentation
Fixes #886.
2017-04-19 14:43:53 -07:00
David Tolnay bc982f9757 Examples for serde_test methods 2017-04-19 14:39:52 -07:00
David Tolnay 0240814677 Update post-merge html_root_urls 2017-04-19 14:32:04 -07:00
David Tolnay 670be2ce2f Crate-level documentation for serde_test 2017-04-19 14:31:07 -07:00
David Tolnay c893e3e872 Support old rustc 2017-04-19 14:17:18 -07:00
David Tolnay fe8141fd70 Reorder Tokens to match the Serializer trait 2017-04-19 14:15:24 -07:00
David Tolnay aa750d2bf3 Examples of every token 2017-04-19 14:12:56 -07:00
David Tolnay 4cea214da2 Update the assert_ser_tokens_error example 2017-04-19 13:11:14 -07:00
David Tolnay 15341780a2 Use struct variants in test suite 2017-04-19 13:06:31 -07:00
David Tolnay 4767ca3f5d Use struct variants in token 2017-04-19 12:20:17 -07:00
David Tolnay 26a6ba177c Remove error from serde_test public API 2017-04-19 11:54:48 -07:00
David Tolnay 974c8434e9 Add example of Error::Message 2017-04-19 10:42:15 -07:00
David Tolnay 0734b44a3a Remove unneeded trait bounds 2017-04-19 10:41:58 -07:00
David Tolnay d0f846182b Keep serde_test serializer and deserializer private 2017-04-19 09:46:30 -07:00
David Tolnay 7a7d4c6364 Format in rfc style 2017-04-18 14:23:21 -07:00
David Tolnay c567e749ef Merge branch 'origin/1.0' into 'origin/master' 2017-04-18 14:03:00 -07:00
David Tolnay b8a6e68322 Revert "Allow borrowing from str's IntoDeserializer"
This reverts commit 30e8c84d01.
2017-04-17 16:18:48 -07:00
David Tolnay 6279b0d930 Resolve merge conflicts 2017-04-17 14:25:29 -07:00
David Tolnay a778425d0f Merge branch 'origin/master' into 'origin/1.0'
Conflicts:
    serde/Cargo.toml
    serde/src/de/impls.rs
    serde/src/ser/impls.rs
    serde_derive/Cargo.toml
    serde_test/Cargo.toml
2017-04-17 14:18:33 -07:00
David Tolnay faaf5ee115 Merge pull request #884 from serde-rs/sfs
Remove seq_fixed_size in favor of tuple
2017-04-17 12:29:36 -07:00
David Tolnay 86deb8db79 Remove seq_fixed_size in favor of tuple 2017-04-17 12:07:49 -07:00
David Tolnay d4d2061a2e Release 0.9.14 2017-04-17 07:33:45 -07:00
David Tolnay c202ce13dc Merge pull request #882 from jethrogb/feature/interior_mut_types
Add Serialize/Deserialize for std types that provide interior mutability
2017-04-17 07:32:13 -07:00
Jethro Beekman 1c9478bfa6 Add Serialize/Deserialize for std types that provide interior mutability
Fixes #179
2017-04-16 22:59:17 -07:00
David Tolnay 739ad64c7c Organize top links 2017-04-16 20:44:27 -07:00
David Tolnay 3eef7c87c9 Fix xml link spacing 2017-04-16 20:33:15 -07:00
David Tolnay e0c040a3a2 Document MapAccess misuse 2017-04-15 12:36:43 -07:00
David Tolnay c13a37d4db Rename VariantAccess methods to not conflict with Deserializer 2017-04-15 12:35:04 -07:00
David Tolnay 4354aab93a Document the default behavior of Visitor methods 2017-04-14 22:29:46 -07:00
David Tolnay 691e304fff Mention the shorthand for identifiers 2017-04-14 22:13:55 -07:00
David Tolnay 13463e25c2 Add a lowercase case convention 2017-04-14 22:09:46 -07:00
David Tolnay 54bbf81dfc Put deserialize_struct and deserialize_enum adjacent 2017-04-14 22:00:27 -07:00
David Tolnay cdfd445528 Generate deserialize impls for identifiers 2017-04-14 21:53:48 -07:00
David Tolnay 30e8c84d01 Allow borrowing from str's IntoDeserializer 2017-04-14 20:54:58 -07:00
David Tolnay a35bde49c6 Factor out logic to decide the tag style 2017-04-14 16:14:10 -07:00
David Tolnay f9535a4d67 Remove "item" terminology in favor of "container"
The docs have been using "container" for a long time.
2017-04-14 15:52:58 -07:00
David Tolnay 6d55501dab Replace "codegen" with "derive" 2017-04-14 15:42:27 -07:00
David Tolnay 5b118fdef4 Reorder methods to match the serializer trait 2017-04-14 15:24:21 -07:00
David Tolnay 337c6e91d8 Access terminology in serde_test 2017-04-14 15:07:19 -07:00
David Tolnay b0dc7ea6da Nicer type parameter for the access forwarding impls 2017-04-14 15:03:43 -07:00
David Tolnay 67d56ae427 Remove unneeded impl bounds 2017-04-14 15:00:16 -07:00
David Tolnay 6829c10a10 Helper deserializer means nothing 2017-04-14 14:49:45 -07:00
David Tolnay 6a37472023 Implement ser::Error for the value error 2017-04-14 14:40:37 -07:00
David Tolnay d10fa2bd86 Keep underscored names out of the documentation 2017-04-14 14:38:58 -07:00
David Tolnay e722cf8791 Fix some function signatures that rustfmt missed 2017-04-14 14:33:00 -07:00
David Tolnay bc4205a1d0 Use V as the Visitor parameter 2017-04-14 14:31:29 -07:00
David Tolnay ea5af417fb Use access terminology for value deserializers 2017-04-14 14:30:28 -07:00
David Tolnay c70c364754 Example of IntoDeserializer 2017-04-14 14:24:47 -07:00
David Tolnay 9cda4563c0 Clean up extraneous vertical space 2017-04-14 14:10:55 -07:00
David Tolnay fc927e0e25 Review deserialize impls 2017-04-14 14:08:11 -07:00
David Tolnay 7915835a93 Merge pull request #879 from serde-rs/size_hint
Simplify size_hint to Option<usize>
2017-04-14 14:07:36 -07:00
David Tolnay 0c5db90de8 Simplify size_hint to Option<usize> 2017-04-14 13:31:46 -07:00
David Tolnay 637332de2d Merge pull request #878 from serde-rs/deserialize_any
Rename Deserializer::deserialize to deserialize_any
2017-04-14 13:04:20 -07:00
David Tolnay e77e7c4bba Rename Deserializer::deserialize to deserialize_any 2017-04-14 12:52:57 -07:00
David Tolnay 1798d1af6e Merge pull request #876 from serde-rs/access
Access traits
2017-04-14 12:45:54 -07:00
David Tolnay 31cec05712 Access traits 2017-04-14 12:24:35 -07:00
David Tolnay f2de0509f5 Whitelist the zero prefixed literals used in array_impls 2017-04-14 12:24:22 -07:00
David Tolnay 26d357e846 Map ser impls should serialize a map 2017-04-14 12:08:26 -07:00
David Tolnay 4e2f08cc7a Format some where clauses that rustfmt refused to touch 2017-04-13 23:04:53 -07:00
David Tolnay 91a0f248a1 More readable MapDeserializer bounds 2017-04-13 22:59:36 -07:00
David Tolnay 03462b6e39 Update the list of deserializable types 2017-04-13 17:48:39 -07:00
David Tolnay 37f8ea234f Hyperlink the de module documentation 2017-04-13 17:43:10 -07:00
David Tolnay 3f920f645c License boilerplate 2017-04-13 17:34:42 -07:00
David Tolnay a937a06d3e Add an IgnoredAny example 2017-04-13 17:22:51 -07:00
David Tolnay dd092dce95 Allow using IgnoredAny as a visitor 2017-04-13 16:53:27 -07:00
David Tolnay dfea7ec939 This is not a bottleneck 2017-04-13 16:46:38 -07:00
David Tolnay 0e7c027ff1 NonZero is just another deref 2017-04-13 16:44:05 -07:00
David Tolnay 8b6f77095a Remove redundant cfg 2017-04-13 16:43:03 -07:00
David Tolnay dbe7d04282 Import Path and PathBuf directly 2017-04-13 16:38:04 -07:00
David Tolnay fb7964fde7 Clean up serialize_display_bounded_length 2017-04-13 16:36:24 -07:00
David Tolnay f45b83f0c1 Condense the deref impls 2017-04-13 16:26:30 -07:00
David Tolnay f28abe8fde Map impls more like the seq impls 2017-04-13 16:09:53 -07:00
David Tolnay 15faaf8bc3 Condense the tuple impls 2017-04-13 16:01:50 -07:00
David Tolnay a15636f808 More like the Deserialize impls for sequences 2017-04-13 15:55:34 -07:00
David Tolnay 5d396c4e3b Condense the array impls 2017-04-13 15:41:26 -07:00
David Tolnay bdccde5c9b Simplify serialize impl for String 2017-04-13 15:36:46 -07:00
David Tolnay 7dd01dd54a This macro serializes a primitive 2017-04-13 15:36:42 -07:00
David Tolnay e4b21e6caa Example for serialize_unit 2017-04-13 15:20:09 -07:00
David Tolnay 2afbffa924 Example for serialize_unit_struct 2017-04-13 15:20:01 -07:00
David Tolnay 385f83a7de Examples and links for Option 2017-04-13 15:16:43 -07:00
David Tolnay 50f5ef2fb6 Condense some serializer imports 2017-04-13 14:54:59 -07:00
David Tolnay 13f273ad74 Examples for the primitive serializer methods 2017-04-13 14:51:39 -07:00
David Tolnay 09bd8287e7 Hyperlink the serialize_entry documentation 2017-04-13 14:27:13 -07:00
David Tolnay 35313257c5 Do not hyperlink first sentence because it shows up in index 2017-04-13 14:23:06 -07:00
David Tolnay 07bce54ad3 Add a collect_map example 2017-04-13 14:21:28 -07:00
David Tolnay 41488252ff Add a collect_seq example 2017-04-13 14:19:17 -07:00
David Tolnay 8d1f882512 Hyperlink the collect methods 2017-04-13 14:16:28 -07:00
David Tolnay dec6b67236 Hyperlink the Serializer associated types 2017-04-13 14:02:13 -07:00
David Tolnay 0cf8eadef8 Dynamically sized means something else 2017-04-13 13:56:12 -07:00
David Tolnay 7d16710fb4 Add an example to Serialize 2017-04-13 13:55:51 -07:00
David Tolnay 9253fccf04 Hyperlink the Serialize documentation 2017-04-13 13:55:34 -07:00
David Tolnay eab771cd1a Standardize on 80 characters per line
Per Mozilla coding style:
https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Coding_Style
2017-04-13 13:24:47 -07:00
David Tolnay 4f6518dad7 Hyperlink the ser::Error documentation 2017-04-13 13:20:12 -07:00
David Tolnay f8e53e837d Hyperlink the ser module documentation 2017-04-13 13:15:23 -07:00
David Tolnay c5854f19f7 Prefer where clauses 2017-04-13 13:02:10 -07:00
David Tolnay 5bb6de80b2 Use better names for the sake of the documentation 2017-04-13 12:45:42 -07:00
David Tolnay c4e31bd968 Match the associated types from the Serializer trait 2017-04-13 12:43:24 -07:00
David Tolnay 2887c379de Hyperlink the Impossible documentation 2017-04-13 12:42:36 -07:00
David Tolnay ea8fb97beb Format in rfc style 2017-04-13 12:32:29 -07:00
David Tolnay c5bd760133 Sort macros in a more readable order 2017-04-13 12:15:12 -07:00
David Tolnay 942642c0f4 Hyperlink the forward_to_deserialize documentation 2017-04-13 12:09:42 -07:00
David Tolnay 78407e19a9 Export Formatter directly for generated code 2017-04-13 12:02:16 -07:00
David Tolnay 47a4e61b8b Document the parts of lib.rs 2017-04-13 11:59:42 -07:00
David Tolnay 5141270346 Touch up the top-level documentation 2017-04-13 11:52:33 -07:00
David Tolnay dc7ab2696a Point html_root_url to docs.rs 2017-04-13 11:31:29 -07:00
David Tolnay 14034968df Implement Copy for de::Unexpected 2017-04-13 11:11:37 -07:00
David Tolnay aef136934b Implement Clone for the value deserializers 2017-04-13 11:11:09 -07:00
David Tolnay 7d0a38270d Eagerly implement common traits for IgnoredAny 2017-04-13 11:06:48 -07:00
David Tolnay 07154303ed Implement Debug for public types 2017-04-13 11:04:16 -07:00
David Tolnay 4f39766211 Fix paths to readme files 2017-04-13 10:37:24 -07:00
David Tolnay 304b598a05 Add appveyor badge to crates.io 2017-04-13 10:26:47 -07:00
David Tolnay afd080d005 Merge branch 'origin/master' into 'origin/1.0' 2017-04-13 10:19:35 -07:00
David Tolnay 1232cfd194 Add playground link to readme 2017-04-13 10:19:22 -07:00
David Tolnay 7e72d8bf66 Merge pull request #869 from serde-rs/into
Rename ValueDeserializer trait to IntoDeserializer
2017-04-12 08:06:18 -07:00
David Tolnay 0d82bbf74f Rename ValueDeserializer trait to IntoDeserializer 2017-04-11 23:20:35 -07:00
David Tolnay aed5a77540 Fix assert_next_token on old rustc 2017-04-10 19:41:32 -07:00
David Tolnay f54d597b2e Merge pull request #865 from serde-rs/use
Centralize all import wrangling
2017-04-10 19:15:45 -07:00
David Tolnay 2efb95015b Appease Rust 1.13.0 2017-04-10 19:06:42 -07:00
David Tolnay f88db0f547 Centralize all import wrangling 2017-04-10 18:50:22 -07:00
David Tolnay 0b7accf86c Remove unused unstable flag from serde_derive 2017-04-10 17:29:59 -07:00
David Tolnay ab82f09e5d Merge pull request #864 from serde-rs/rc
Put rc impls behind a cfg
2017-04-10 17:20:38 -07:00
David Tolnay 0f72d1a388 Put rc impls behind a cfg 2017-04-10 17:01:11 -07:00
David Tolnay ef3489a23e Merge pull request #863 from serde-rs/cfgs
Document the cargo cfgs
2017-04-10 16:47:14 -07:00
David Tolnay 8bbab627a0 Document the cargo cfgs 2017-04-10 16:38:11 -07:00
David Tolnay 76ff216a5f Merge pull request #853 from serde-rs/fwd
Configurable forward_to_deserialize
2017-04-10 15:43:34 -07:00
David Tolnay b40ecf04ce Merge branch 'origin/1.0' into 'origin/fwd'
Conflicts:
    serde/src/macros.rs
2017-04-10 15:23:37 -07:00
David Tolnay eeaa095cd3 Merge pull request #860 from serde-rs/identifier
Standardize on u32 for struct field index and enum variant index
2017-04-10 15:16:16 -07:00
David Tolnay 1985cfc955 Merge branch 'origin/1.0' into 'origin/identifier'
Conflicts:
    serde_derive/src/ser.rs
2017-04-10 12:37:41 -07:00
David Tolnay 517270a943 Merge pull request #858 from serde-rs/remote
Derive for remote types
2017-04-10 12:33:38 -07:00
David Tolnay 6a6606cd64 Test unknown field in remote struct 2017-04-10 12:23:02 -07:00
David Tolnay 174867295b Test missing field in remote struct 2017-04-10 12:22:51 -07:00
David Tolnay ad5bf04c4e Test for incorrect remote type deserializing 2017-04-10 12:15:40 -07:00
David Tolnay 2deacf8eaa Detect incorrect remote type without getter 2017-04-10 12:12:00 -07:00
David Tolnay e133b8b708 Fix unused import on windows 2017-04-09 14:11:27 -07:00
David Tolnay 52e93150e6 Standardize on u32 as the type of a variant index 2017-04-09 14:03:18 -07:00
David Tolnay a38b24136b Rename deserialize_struct_field to deserialize_identifier
Because it applies to both struct fields and discriminants of an enum.
2017-04-09 13:35:22 -07:00
David Tolnay 78f682590a Merge branch 'origin/1.0' into 'origin/remote'
Conflicts:
    serde_derive/src/de.rs
2017-04-09 13:19:04 -07:00
David Tolnay 528ec3cdd8 Merge pull request #859 from serde-rs/unitseq
Remove conversion from empty seq to unit struct
2017-04-09 13:17:41 -07:00
David Tolnay 1986c17052 Remove conversion from empty seq to unit struct 2017-04-09 13:08:05 -07:00
David Tolnay 5ec317a899 More compile-fail tests for remote derive 2017-04-09 11:11:27 -07:00
David Tolnay 9d8987bde8 Require getters to return the correct type 2017-04-09 10:59:54 -07:00
David Tolnay a6d172111b Derive for remote types 2017-04-09 10:15:46 -07:00
David Tolnay 9271f7c48c Use a deserializer in which V would conflict 2017-04-08 22:46:53 -07:00
David Tolnay 74e15ea9f5 Configurable forward_to_deserialize 2017-04-08 22:43:07 -07:00
David Tolnay 2c49f9aad3 Recommend 'extern crate serde' 2017-04-08 13:53:13 -07:00
David Tolnay cc933b9cdb Just use an existing macro 2017-04-07 17:26:03 -07:00
David Tolnay fdaa8202b9 Clean up some existing examples 2017-04-07 11:06:19 -07:00
David Tolnay 85d4dc3e20 Copy the Serializer examples to the helper traits 2017-04-07 10:45:13 -07:00
David Tolnay 11a6e42256 Unignore SerializeSeq example 2017-04-07 10:42:54 -07:00
David Tolnay b1cfa5aef5 Unignore Serializer::serialize_struct_variant example 2017-04-07 10:35:42 -07:00
David Tolnay f2b230a0b8 Unignore Serializer::serialize_struct example 2017-04-07 10:34:03 -07:00
David Tolnay 8aa630ea48 Unignore Serializer::serialize_map example 2017-04-07 10:32:01 -07:00
David Tolnay ad249c7fac Unignore Serializer::serialize_tuple_variant example 2017-04-07 10:28:53 -07:00
David Tolnay fccb395168 Unignore Serializer::serialize_tuple_struct example 2017-04-07 10:26:00 -07:00
David Tolnay 8d130123d9 Unignore Serializer::serialize_tuple example 2017-04-07 10:23:52 -07:00
David Tolnay d97c4f403c Unignore Serializer::serialize_seq_fixed_size example 2017-04-07 10:17:40 -07:00
David Tolnay e86e716f7a Show imports in Serializer examples 2017-04-07 10:12:15 -07:00
David Tolnay 870305aa93 Unignore Serializer::serialize_seq example 2017-04-07 10:11:08 -07:00
David Tolnay b9be543596 Unignore Serializer::serialize_newtype_variant example 2017-04-07 10:04:37 -07:00
David Tolnay 43d49f54be Unignore Serializer::serialize_newtype_struct example 2017-04-07 10:02:11 -07:00
David Tolnay 753c711cd7 Unignore Serializer::serialize_unit_variant example 2017-04-07 10:01:39 -07:00
David Tolnay 2e9cc6e98a Move utf8 encode to where it is used 2017-04-07 09:50:38 -07:00
David Tolnay 726eea9a97 Separate out the private functionality
This makes it easier when clicking through [src] links from rustdoc, not having
to sift through public and internal code combined together.
2017-04-07 09:46:48 -07:00
David Tolnay 467b5fc595 Macro to ignore tokens in doc test 2017-04-07 09:28:33 -07:00
David Tolnay 995f2b3f76 Ignore clippy false positive 2017-04-07 09:21:30 -07:00
David Tolnay e57ce37ac1 Unignore Serializer::serialize_bytes example 2017-04-07 09:07:08 -07:00
David Tolnay a581c0d147 Keep Debug and Display as supertraits even in no_std 2017-04-07 09:00:00 -07:00
David Tolnay 21c2119349 Unignore the Impossible example 2017-04-06 17:09:01 -07:00
David Tolnay f12a951f22 Unignore VariantVisitor::visit_struct example 2017-04-06 16:28:24 -07:00
David Tolnay d2d4892873 Unignore VariantVisitor::visit_tuple example 2017-04-06 16:26:51 -07:00
David Tolnay 2b449683f3 Unignore VariantVisitor::visit_newtype_seed example 2017-04-06 16:24:48 -07:00
David Tolnay 9d73271db2 Unignore VariantVisitor::visit_unit example 2017-04-06 16:19:47 -07:00
David Tolnay 7ef80a845d Unignore DeserializeOwned example 2017-04-06 16:11:30 -07:00
David Tolnay 33760e122c Remove LineColIterator
This belongs in a helper crate.
2017-04-06 14:27:21 -07:00
David Tolnay dd62801b22 Use spaces around =-sign like Rust does 2017-04-06 14:22:03 -07:00
David Tolnay 5415abf80b Merge pull request #848 from serde-rs/emptyarray
Relax impls for [T; 0]
2017-04-05 17:43:11 -07:00
David Tolnay 6388019ad4 Relax impls for [T; 0] 2017-04-05 17:34:13 -07:00
David Tolnay 2fe67d3d72 Merge pull request #847 from serde-rs/error
Remove serde::error::Error
2017-04-05 16:37:18 -07:00
David Tolnay 1e32329e61 Fix unused feature gate warning 2017-04-05 16:30:46 -07:00
David Tolnay e2a1f08e43 Remove unused import of std::ops 2017-04-05 16:26:58 -07:00
David Tolnay 11c89695a1 Rust 1.13.0 macro parsing workaround 2017-04-05 16:22:47 -07:00
David Tolnay 5f49eb8b24 Remove unused import of MapVisitor 2017-04-05 16:18:11 -07:00
David Tolnay 3cc14c2a6d Remove serde::error::Error 2017-04-05 16:12:41 -07:00
David Tolnay aa30ef827c Move Bytes and ByteBuf to their own crate
Moved to https://github.com/serde-rs/bytes.
2017-04-05 15:21:27 -07:00
David Tolnay ebe214e8ac Remove CString dependency on ByteBuf 2017-04-05 15:19:29 -07:00
David Tolnay 8fd41d3b28 Disable publishing 2017-04-05 15:11:47 -07:00
David Tolnay a7f6ad137a Merge branch 'master' into '1.0'
Conflicts:
    serde/src/macros.rs
2017-04-05 15:10:18 -07:00
David Tolnay 1b763da529 Release 0.9.13 2017-04-05 15:03:37 -07:00
David Tolnay b7d6c5d9f7 Remove no_std special case in forward_to_deserialize 2017-04-05 15:01:55 -07:00
David Tolnay e7d3d515df Simplify integer conversion logic 2017-04-05 13:06:05 -07:00
David Tolnay 145733ce77 Remove redundant Bounded trait 2017-04-05 12:36:51 -07:00
David Tolnay 1a63cbccb2 Remove unused ToPrimitive trait 2017-04-05 12:29:05 -07:00
David Tolnay 07ac9eb538 Remove unused number conversion logic 2017-04-05 12:11:50 -07:00
David Tolnay 14aa89aac8 Merge pull request #846 from serde-rs/float
Remove implicit conversion from float to integer
2017-04-05 11:51:49 -07:00
David Tolnay e66033e53e Remove implicit conversion from float to integer 2017-04-05 11:25:12 -07:00
David Tolnay dcb837b531 Merge pull request #845 from serde-rs/token
Modernize serde_test Token names
2017-04-05 10:52:33 -07:00
David Tolnay 51d3fb1ebc Update token names in test suite 2017-04-05 10:40:14 -07:00
David Tolnay 826b53f691 Update token names in serde_test 2017-04-05 10:30:46 -07:00
David Tolnay b6605b57e0 Modernize serde_test Token names 2017-04-05 10:26:34 -07:00
David Tolnay f03e8e6056 Exhaustive match in serde_test deserializer 2017-04-05 09:54:12 -07:00
David Tolnay a33a9a5b26 Merge pull request #844 from serde-rs/sep
Eliminate Sep tokens in serde_test
2017-04-05 09:54:02 -07:00
David Tolnay 67ed7a0edd Eliminate Sep tokens in serde_test 2017-04-05 09:42:27 -07:00
David Tolnay 9b51be4ba6 Merge pull request #843 from serde-rs/ignore
Stop ignoring error in assert_de_tokens_ignore
2017-04-05 09:36:22 -07:00
David Tolnay c3d9b42cdf Fix handling of option and newtype in IgnoredAny 2017-04-05 09:19:22 -07:00
David Tolnay b2377d4c0b Allow enums in ignored map value in serde_test 2017-04-05 08:54:30 -07:00
David Tolnay dee58ead7f Merge pull request #841 from serde-rs/nostr
Remove the no_std implementation of collect_str
2017-04-05 08:12:31 -07:00
David Tolnay 887985523e Merge pull request #840 from serde-rs/privimpl
Make the built-in visitors private
2017-04-05 08:12:00 -07:00
David Tolnay cabc299447 Merge pull request #839 from serde-rs/conv
Remove questionable type conversions
2017-04-05 08:11:50 -07:00
David Tolnay 21adee8f40 Partial support for EnumStart in assert_ser_tokens 2017-04-05 01:15:42 -07:00
David Tolnay afaab12b66 Improve assert_ser_tokens error messages 2017-04-05 01:06:42 -07:00
David Tolnay 93860d0643 Require slice of tokens in serde_test::Serializer 2017-04-05 00:27:30 -07:00
David Tolnay b43554fbb1 Require slice of tokens in serde_test::Deserializer 2017-04-05 00:22:00 -07:00
David Tolnay 5871fb9ce0 Remove lifetime from serde_test::Token 2017-04-05 00:17:50 -07:00
David Tolnay f05368ed24 Remove the no_std implementation of collect_str 2017-04-04 19:10:35 -07:00
David Tolnay 732b91e53d Make the built-in visitors private 2017-04-04 18:59:57 -07:00
David Tolnay d03ecda333 Test that conversions do not happen 2017-04-04 18:50:40 -07:00
David Tolnay 7a722d5060 Remove questionable conversion tests 2017-04-04 18:38:58 -07:00
David Tolnay 2795f0ed9d Remove questionable type conversions 2017-04-04 18:18:47 -07:00
David Tolnay 92bc23e484 Deserializing OsString on windows requires a 'de lifetime 2017-04-04 18:08:36 -07:00
David Tolnay 5a98bd9ee3 Merge branch 'master' into '1.0' 2017-04-04 18:04:40 -07:00
David Tolnay bfabaf3789 Merge pull request #838 from serde-rs/winstr
Deserialize OsString on Windows
2017-04-04 11:33:42 -07:00
David Tolnay cf6c4ab7ec Deserialize OsString on Windows 2017-04-04 11:19:24 -07:00
David Tolnay 7c27e10226 Merge pull request #837 from serde-rs/borrow
Derive for borrowed fields
2017-04-04 10:51:56 -07:00
David Tolnay 20ff9ba89b Add tests of deserializing borrows 2017-04-04 10:47:21 -07:00
David Tolnay 211e2bb8d9 Support borrowed tokens in serde_test 2017-04-04 09:56:01 -07:00
David Tolnay cee3efbda8 Relax lifetime requirement of the borrow_cow functions 2017-04-03 00:54:50 -07:00
David Tolnay fb48111e46 Derive for borrowed fields 2017-04-03 00:40:45 -07:00
David Tolnay 8c3e72f2c8 Merge pull request #834 from serde-rs/easy
Deserialize impls for &str and &[u8]
2017-03-31 00:44:44 -07:00
David Tolnay aa46318425 Deserialize impls for &str and &[u8] 2017-03-30 23:36:20 -07:00
David Tolnay 3d3118f8b0 Merge pull request #826 from serde-rs/lifetime
Add a 'de lifetime to the deserialize traits
2017-03-30 23:11:49 -07:00
David Tolnay b6f1a2eb55 Add a note about assuming the deserializer lifetime name 2017-03-30 23:06:00 -07:00
David Tolnay 8eb50186e0 Merge pull request #831 from serde-rs/derivepath
Use the live serde_derive for serde doc tests
2017-03-30 22:55:33 -07:00
David Tolnay 4dec5f4de8 Update example code for zero copy 2017-03-30 22:54:42 -07:00
David Tolnay 8e0c036158 Merge branch 'derivepath' into 'lifetime' 2017-03-30 22:48:48 -07:00
David Tolnay 7d985ff3fd Use the live serde_derive for serde doc tests
This is required as both are updated to Deserialize<'de> together.
2017-03-30 22:45:15 -07:00
David Tolnay d3a2f5e268 Add a 'de lifetime to the deserialize traits 2017-03-29 00:10:34 -07:00
David Tolnay 59b3961ad4 Release 0.9.12 2017-03-27 15:45:14 -07:00
David Tolnay dbc9a60c5f Merge pull request #824 from alexcrichton/osstr-osstring
Implement Serialize/Deserialize for OsStr/OsString
2017-03-27 15:39:07 -07:00
Alex Crichton ce687431f3 Implement Serialize/Deserialize for OsStr/OsString
This commit implements the two serde traits for the libstd `OsStr` and
`OsString` types. This came up as a use case during implementing sccache where
we're basically just doing IPC to communicate paths around. Additionally the
`Path` and `PathBuf` implementations have been updated to delegate to the os
string ones.

These types are platform-specific, however, so the serialization/deserialization
isn't trivial. Currently this "fakes" a newtype variant for Unix/Windows to
prevent cross-platform serialization/deserialization. This means if you're doing
IPC within the same OS (e.g. Windows to Windows) then serialization should be
infallible. If you're doing IPC across platforms (e.g.  Unix to Windows) then
using `OsString` is guaranteed to fail as bytes from one OS won't deserialize on
the other (even if they're unicode).
2017-03-27 11:44:50 -07:00
David Tolnay 71ccc5753b Merge pull request #820 from serde-rs/reexport
Re-export derives from serde
2017-03-26 20:37:12 -07:00
David Tolnay 13886435a6 Re-export derives from serde 2017-03-21 16:54:31 -07:00
David Tolnay 08e2182042 UFCS for Option::map and Result::map 2017-03-18 13:31:03 -07:00
David Tolnay d60595cc27 Use format_args! to simplify de::Error 2017-03-18 10:48:47 -07:00
David Tolnay 8c7396c35a Be consistent with UFCS and double underscores 2017-03-18 10:33:22 -07:00
David Tolnay 42b2fd8eec Improve error message parsing from and into 2017-03-18 09:22:44 -07:00
John Baublitz bc946e4fd7 Macro attributes to specify From and Into trait types for structs and enums (#817)
* serde macro support for type conversions through From and Into trait

* Revisions requested by dtolnay

* Additional changes requested by dtolnay
2017-03-18 09:22:27 -07:00
David Tolnay c488cec641 Remove RangeInclusive impl for now
The old impl is inconsistent with the new ops::Range impl.
2017-03-13 11:09:56 -07:00
David Tolnay fcc3c69a49 Range impl is defined when building with std 2017-03-09 12:04:02 -08:00
David Tolnay 350c2e835b Remove duplicate ops::Range serialize impl 2017-03-09 11:57:36 -08:00
David Tolnay a0a031677e Merge pull request #813 from rocallahan/support-range
Implement `Serialize`/`Deserialize` for `Range`
2017-03-09 11:55:21 -08:00
Robert O'Callahan cc0d045f5c Add Deserialize impl for std::ops::Range
Resolves #796
2017-03-10 08:39:34 +13:00
Robert O'Callahan aebe1fddab Add Serialize impl for std::ops::Range 2017-03-10 00:35:04 +13:00
David Tolnay 77ee306b57 Format serde with rustfmt 0.8.0 2017-03-08 21:11:17 -08:00
David Tolnay 6750fdaae1 Merge pull request #811 from jonhoo/deserialize-cstr
Add Deserialize impl for CStr
2017-03-08 21:06:09 -08:00
David Tolnay dd6989d551 Actually run unstable tests 2017-03-08 21:02:15 -08:00
Jon Gjengset 0c2fed49e2 Add Deserialize impl for CStr
Fixes #810
2017-03-08 23:57:26 -05:00
Oliver Schneider a4ee9bd045 Merge pull request #808 from serde-rs/u32
Implement deserialize_enum for U32Deserializer
2017-03-07 18:58:29 +01:00
David Tolnay 6d9397d573 Implement deserialize_enum for U32Deserializer 2017-03-07 09:05:33 -08:00
David Tolnay dc9445f873 Release 0.9.11 2017-03-05 16:51:44 -08:00
David Tolnay 17bc40ec1c Merge pull request #789 from nox/display
Introduce Serializer::collect_str (fixes #786)
2017-03-05 16:47:22 -08:00
David Tolnay 2184fef82f Add format_args example to collect_str 2017-03-05 16:43:31 -08:00
David Tolnay 7e1b5c6ce4 Neater collect_str variable name for rustdoc 2017-03-05 16:26:05 -08:00
David Tolnay 36da8a5cee Error message geared toward serializer users
The previous message was targeted toward Serializer implementors, which is not
the group that will be seeing this message most often.
2017-03-05 16:24:48 -08:00
David Tolnay fbe85f399d Force no_std formats to implement collect_str in the future 2017-03-05 16:22:02 -08:00
David Tolnay 880b27b19e Identical signature for std and no_std collect_str 2017-03-05 16:17:03 -08:00
David Tolnay cc06f070d1 Use the existing CString error message 2017-03-05 13:59:18 -08:00
David Tolnay 2f988aa5e6 Merge pull request #801 from jonhoo/ffi-strings
impls for null-terminated FFI string types
2017-03-05 13:51:09 -08:00
Jon Gjengset d294a10e83 Only include ByteBuf when ser/de is on for std 2017-03-03 23:48:00 -05:00
Jon Gjengset defcbef7ab Use a non-stupid path for bytes::ByteBuf 2017-03-03 23:28:35 -05:00
Jon Gjengset d90eecd4a2 Add tests for CStr(ing) ser/de 2017-03-03 18:06:04 -05:00
Jon Gjengset 0d6d077e6a Serialize and deserialize CString through [u8] 2017-03-03 18:05:08 -05:00
Jon Gjengset be09fc9bbb Remove unsafe Deserialize impl for CStr
See also https://github.com/rust-lang/rust/issues/40248
2017-03-03 17:34:01 -05:00
Jon Gjengset fc9d78e26b Use serialize_bytes for speed 2017-03-03 17:14:39 -05:00
Jon Gjengset 9f83164c40 Don't serialize trailing NULL 2017-03-03 17:14:28 -05:00
Jon Gjengset 857974ab8a impls for null-terminated FFI string types
Fixes #800.
2017-03-03 16:09:41 -05:00
David Tolnay d70636f4d4 Merge pull request #794 from clarcharr/master
Documentation for serde_test.
2017-03-02 11:53:05 -08:00
Clar Charr 09e467cc4c Documentation for serde_test. 2017-02-28 18:20:27 -05:00
David Tolnay 51ed9c2a40 Release 0.9.10 2017-02-28 12:45:39 -08:00
Anthony Ramine a9a05350a9 Introduce Serializer::collect_str (fixes #786)
The default implementation collects the Display value into a String
and then passes that to Serializer::serialize_str when the std or collections
features are enabled, otherwise it unconditionally returns an error.
2017-02-28 12:11:47 +01:00
David Tolnay fe9ea3b4b4 Fix needless_pass_by_value lint 2017-02-27 19:43:42 -08:00
David Tolnay f944b453c4 Merge pull request #792 from elliottslaughter/fix_serialize_tuple_docs
Fix documentation of serialize_tuple and SerializeTuple
2017-02-27 14:05:15 -08:00
Elliott Slaughter a993630cf9 Fix documentation of serialize_tuple and SerializeTuple. 2017-02-27 14:00:21 -08:00
David Tolnay abc081ce9c Test rename_all attribute 2017-02-25 11:58:34 -08:00
David Tolnay 207940046b Merge pull request #788 from 46bit/issue-140
`rename_all` container attribute to have all children fit a naming convention
2017-02-25 11:38:33 -08:00
David Tolnay 47efbc6d75 Don't need to pass back the input here 2017-02-25 11:32:27 -08:00
David Tolnay 17279e8a4f Simplify case conversion implementation 2017-02-25 11:32:22 -08:00
David Tolnay 06c631db05 Bring in the tests 2017-02-25 11:02:51 -08:00
David Tolnay 7952bad41f Move case conversion to its own file 2017-02-25 11:02:25 -08:00
Michael Mokrysz 3308f81c3a Saving progress on naming convention conversion code to try new Inflector changes. #788 2017-02-25 13:24:49 +00:00
David Tolnay 75e6da02d3 Split up test suite so it compiles in parallel 2017-02-24 15:39:18 -08:00
David Tolnay 59ec931d8f Release 0.9.9 2017-02-24 13:57:52 -08:00
David Tolnay 4b3c5ea99e Fix clippy lint in content serializer 2017-02-24 13:56:44 -08:00
David Tolnay d4ea4a7eef Add test for enums containing enums
Fixes #775.
2017-02-24 13:50:47 -08:00
David Tolnay 5fbdadefb2 Deserializing enums in serde_test 2017-02-24 13:47:04 -08:00
David Tolnay 4da77e4200 Serialize to Content 2017-02-24 12:59:35 -08:00
David Tolnay d797504407 Deserialize enums from &Content 2017-02-24 09:32:14 -08:00
Michael Mokrysz 84915268ee Minor fixes for pull request. Cheers @dtolnay. 2017-02-24 01:55:31 +00:00
Michael Mokrysz 3b59d47e07 Heavily refactored rename_all and switched to SCREAMING_SNAKE_CASE. 2017-02-23 23:22:54 +00:00
Michael Mokrysz fc94c5399a Implementing rename_all container attribute using Inflector trait. #140 2017-02-23 18:58:41 +00:00
David Tolnay 8e5f472e27 Merge pull request #787 from 46bit/issue-775
Fix internally tagged enums by implementing ContentDeserializer::deserialize_enum
2017-02-22 18:23:18 -08:00
David Tolnay 5e7883945b Fix clippy lint in Content::unexpected 2017-02-22 18:16:51 -08:00
David Tolnay a4bd6b9a96 Fix content's SeqDeserializer on no_std 2017-02-22 18:14:56 -08:00
Michael Mokrysz 4c253748c2 Compiles and fixes internally tagged testcases. 2017-02-23 01:05:44 +00:00
Michael Mokrysz 8f6e1fb5b3 Resolved error typing. Needs to adapt to Content::Map with non-String keys.
`EnumDeserializer` is being adapted from:
  `serde_json::Value::Map<Vec<(String, Value)>>`
serde has a Map variant that allows non-String keys:
  `serde::de::Content::Map<Vec<(Content, Content)>>`

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

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

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

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

fixes #729

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

* don't build serde in the clippy travis job

* only run clippy tests if installing clippy succeeds

* why is travis so picky?

* no more serde_codegen

* serde_test_suite_deps has no features

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

* abort the clippy job when clippy lints are triggered

* use caches on travis to speed up builds

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

* need to reinstall clippy frequently due to nightly updates

* command line tools are hard
2017-01-31 09:09:37 -08:00
Oliver Schneider 74cf80989d Merge pull request #731 from serde-rs/pubtuple
No tuple structs with private fields in public API
2017-01-31 08:56:46 +01:00
David Tolnay f0b4735781 No tuple structs with private fields in public API 2017-01-30 18:10:50 -08:00
David Tolnay 297f373548 Release 0.9.4 2017-01-30 17:42:11 -08:00
David Tolnay 81f28da8e1 Clarify the role of Impossible serializer 2017-01-30 17:41:33 -08:00
David Tolnay d4bb687032 Merge pull request #728 from nox/impossibru
Introduce ser::Impossible (fixes #694)
2017-01-30 17:26:21 -08:00
Anthony Ramine f9bc5037f5 Introduce ser::Impossible (fixes #694) 2017-01-31 02:20:04 +01:00
David Tolnay 8624ca6f1d Release 0.9.3 2017-01-28 15:01:58 -08:00
David Tolnay a9b5cc4830 Fix invalid_length message for tuples and arrays 2017-01-28 15:00:54 -08:00
David Tolnay c31f76321c Release 0.9.2 2017-01-28 09:10:39 -08:00
David Tolnay f2402dcf52 Merge pull request #724 from serde-rs/entry
SerializeMap::serialize_entry
2017-01-28 09:08:51 -08:00
David Tolnay 361402ac4d SerializeMap::serialize_entry 2017-01-28 09:03:32 -08:00
David Tolnay c52e131a03 Replace deprecated MacroInput 2017-01-27 15:42:43 -08:00
David Tolnay c0a06bdc96 Update to syn 0.11 2017-01-27 15:25:42 -08:00
David Tolnay dd13fd3a34 Isolate the compiletest dependencies 2017-01-27 14:53:30 -08:00
David Tolnay 91f628727b Clean up the compile_tests script 2017-01-27 14:37:28 -08:00
David Tolnay 571a2e4e2d Indent the travis config to look like serde_json's 2017-01-27 14:17:07 -08:00
David Tolnay 7edcf6ec3b Simplify Error::custom example 2017-01-27 14:03:40 -08:00
David Tolnay e4f7d8513c Clean up clippy lints in codegen_internals 2017-01-25 21:22:15 -08:00
David Tolnay 09c69da909 Move test macro to where it is used 2017-01-25 20:55:55 -08:00
David Tolnay 7ee175f448 Remove duplicate btreemap macro 2017-01-25 20:54:31 -08:00
David Tolnay 70ab3cdd61 Docs are built in a different repo 2017-01-25 20:51:10 -08:00
David Tolnay 8fb554e593 Rename no_std tests to underscores 2017-01-25 20:50:23 -08:00
David Tolnay 7a2bfdc1dd Consistent underscores in root directory 2017-01-25 20:45:33 -08:00
David Tolnay 9046e9d7a1 Test suite requires beta for now 2017-01-25 20:45:08 -08:00
David Tolnay 87040b4bc4 Fix clippy lints in serde_test 2017-01-25 20:42:44 -08:00
David Tolnay 68aab2424f Rename test suite crate 2017-01-25 20:40:13 -08:00
David Tolnay 9b9b697eb1 Make compiletest an optional dependency of the test suite 2017-01-25 20:39:27 -08:00
David Tolnay db449c4bf2 Set up clippy for serde_test 2017-01-25 20:38:21 -08:00
David Tolnay 948aa47687 Clean up clippy lints 2017-01-25 20:34:01 -08:00
David Tolnay 3e1e42ef9b Combine the test suites 2017-01-25 20:29:09 -08:00
David Tolnay dbdfe4f306 Remove serde_codegen from the test suite 2017-01-25 20:19:16 -08:00
David Tolnay e0d6b9d010 Merge serde_codegen into serde_derive crate 2017-01-25 20:07:55 -08:00
David Tolnay a5b8e806f8 Remove with-syntex feature of serde_codegen 2017-01-25 20:02:24 -08:00
David Tolnay d7dadd83b6 Remove the syntex example 2017-01-25 19:54:24 -08:00
David Tolnay 7612fd8e82 Release 0.9.1 2017-01-25 14:58:22 -08:00
David Tolnay 4c77af53e5 Clean up dependency declarations 2017-01-25 14:54:32 -08:00
David Tolnay 5d9c1aeb06 Release 0.9.0 2017-01-25 12:57:45 -08:00
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
David Tolnay 78e74886be Update syntex to 0.39 2016-07-26 09:22:33 -07:00
Oliver Schneider 061a1d8a8c Merge pull request #465 from serde-rs/underscore
Remove underscore from parameter names in deserializer traits
2016-07-26 08:25:15 +02:00
David Tolnay de9fd3b04e Remove underscore from parameter names in deserializer traits
This makes the generated rustdoc easier to read.
2016-07-25 20:18:45 -07:00
David Tolnay e36f33589c Release 0.8.0-rc3 2016-07-23 15:13:19 -07:00
Homu a892a13473 Auto merge of #462 - jimmycuadra:ser-error-docstring, r=oli-obk
Fix typos in docstring of ser::Error.

Just a minor documentation fix for grammar and and a copy/paste error.
2016-07-23 17:07:46 +09:00
Jimmy Cuadra 556d5bdc27 Fix typos in docstring of ser::Error. 2016-07-23 00:56:55 -07:00
Homu c6acec29e5 Auto merge of #459 - serde-rs:phantom, r=oli-obk
PhantomData<T> does not require bounds on T
2016-07-23 01:43:45 +09:00
David Tolnay dce02c624b Merge pull request #460 from serde-rs/revert
Revert "Mention Empty Bounds for Recursion in Readme"
2016-07-22 09:13:53 -07:00
David Tolnay 77e56613a5 Revert "Mention Empty Bounds for Recursion in Readme"
This reverts commit 93968455f3.
2016-07-22 09:09:23 -07:00
David Tolnay 3b7fa47b2e PhantomData<T> does not require bounds on T 2016-07-22 09:05:43 -07:00
David Tolnay f5fd7f5950 Merge pull request #458 from serde-rs/testgen
Add tests for concrete instantiations in test_gen
2016-07-22 09:04:33 -07:00
David Tolnay fb6fc4e19f Add tests for concrete instantiations in test_gen 2016-07-22 08:49:51 -07:00
David Tolnay 85772726ee Merge pull request #456 from serde-rs/generic
Generate bounds on type parameters only
2016-07-22 07:58:56 -07:00
Oliver Schneider f05ba9fdf2 unhygienize the generic parameter comparison
include! completely messes up the identifiers' expansion info
2016-07-22 14:09:14 +02:00
Homu 2e829ae4e6 Auto merge of #457 - serde-rs:phantom, r=oli-obk
Impl Deserialize for PhantomData<T> for all T
2016-07-22 16:31:51 +09:00
David Tolnay 25a5dd1579 Impl Deserialize for PhantomData<T> for all T 2016-07-21 23:22:38 -07:00
David Tolnay 1831b471f9 Generate bounds on type parameters only 2016-07-21 23:06:18 -07:00
Oliver Schneider 49ff56aa15 Merge pull request #452 from oli-obk/pure_interface
Pure interface for Deserializer
2016-07-21 11:25:16 +02:00
Oliver Schneider 89549e2567 fix nightly 2016-07-21 10:49:02 +02:00
Oliver Schneider 124bacd871 fix for 1.8, 1.9 and stable 2016-07-21 10:11:04 +02:00
Oliver Schneider 4280dd466d rename deserialize_fixed_size_array to deserialize_seq_fixed_size 2016-07-20 19:20:31 +02:00
Oliver Schneider 65eb116a85 address comments 2016-07-20 19:18:45 +02:00
Homu e15940f355 Auto merge of #454 - nox:boxed, r=oli-obk
Implement Deserialize for Box<str>
2016-07-20 19:49:11 +09:00
Anthony Ramine 68440952ab Implement Deserialize for Box<str> 2016-07-20 12:47:08 +02:00
Oliver Schneider d751b4c39a Merge pull request #451 from killercup/doc/recursive-bounds
Mention Empty Bounds for Recursion in Readme
2016-07-20 10:43:54 +02:00
Oliver Schneider d10a69b243 document some hints for defaults 2016-07-20 10:42:14 +02:00
Pascal Hertleif 1a1b6fbf85 Fix Typo in Readme 2016-07-20 10:39:57 +02:00
Pascal Hertleif 93968455f3 Mention Empty Bounds for Recursion in Readme
Fixes #427
2016-07-20 10:39:57 +02:00
Oliver Schneider 4722571a4d make VariantVisitor pure 2016-07-20 10:33:28 +02:00
Oliver Schneider 36a7bf6244 make Deserializer pure 2016-07-20 10:26:31 +02:00
David Tolnay 89f0ad99a6 Merge pull request #449 from oli-obk/docs
add more extensive docs
2016-07-18 07:09:20 -07:00
Oliver Schneider 05ad8662e2 add more extensive docs 2016-07-18 16:08:07 +02:00
Oliver Schneider 15c09a8d2c Merge pull request #448 from laktak/hjson
add Hjson
2016-07-18 13:04:02 +02:00
Christian Zangl 80a27cbb4a add Hjson 2016-07-18 12:06:21 +02:00
David Tolnay 13e1a129dd Ignore unused struct in test_gen.rs 2016-07-17 21:10:05 -07:00
David Tolnay 334a6e788a Remove commented code in test_macros.rs 2016-07-17 21:09:44 -07:00
David Tolnay fa51083a12 Merge pull request #446 from serde-rs/unstable
Rename feature nightly-testing to unstable-testing
2016-07-17 18:26:20 -07:00
David Tolnay aaca4f06c6 Release 0.8.0-rc2 2016-07-17 18:07:40 -07:00
David Tolnay cc8a5a79ab See whether relative paths help cargo find the unstable-testing feature 2016-07-17 13:40:39 -07:00
David Tolnay 4f79829849 Rename feature nightly-testing to unstable-testing 2016-07-17 13:34:23 -07:00
David Tolnay 6c18896cf5 Unpin the clippy dependency 2016-07-17 13:32:40 -07:00
David Tolnay ac738632ef Merge pull request #445 from serde-rs/pubdep
Remove public dependency on Syntex
2016-07-17 13:15:42 -07:00
David Tolnay 8d06f36d71 Remove public dependency on Syntex 2016-07-17 13:00:39 -07:00
David Tolnay e404de85b2 Remove serde-syntex-example from travis until serde_json 0.8.0 2016-07-17 12:59:04 -07:00
David Tolnay 6fe01bc8e3 Release 0.8.0-rc1
This prerelease contains the Serializer API changes intended for 0.8.0. It
allows us to start merging PRs that use the new API.
2016-07-17 11:46:03 -07:00
David Tolnay 855f3d99bb Do not release any more 0.7 releases from master 2016-07-15 17:00:09 -07:00
David Tolnay 9d015a2942 Merge pull request #437 from oli-obk/map_seq_ser
Revamp Map/Seq serialization
2016-07-15 16:59:45 -07:00
Oliver Schneider 42c41922ce adjust tests for new interface 2016-07-15 12:59:30 +02:00
Oliver Schneider 984181c558 Merge remote-tracking branch 'serde/master' into map_seq_ser 2016-07-15 10:59:46 +02:00
David Tolnay ed603d4580 Merge pull request #442 from serde-rs/override
Use cargo override instead of relative paths
2016-07-15 01:56:14 -07:00
Oliver Schneider 70c83768b7 Merge pull request #1 from serde-rs/dtolnay/serializer
David's take on Serializer
2016-07-15 10:38:22 +02:00
David Tolnay 7220029055 Use cargo override instead of relative paths
This makes it possible to use `cargo clone` + `cargo build`.
2016-07-15 01:17:23 -07:00
David Tolnay 35676305da Merge pull request #401 from erickt/contributing
Add a contribution guide
2016-07-15 01:06:54 -07:00
David Tolnay fbad194042 Restore 'static requirement for names 2016-07-15 00:59:56 -07:00
David Tolnay 2e4cc0b443 Restore serialize_seq_fixed_size 2016-07-15 00:58:48 -07:00
David Tolnay 9217517532 Update impls 2016-07-15 00:55:38 -07:00
David Tolnay 0feeb7a341 David's take on Serializer 2016-07-15 00:01:31 -07:00
Oliver Schneider 2901344722 this time really fix ranges 2016-07-14 16:16:20 +02:00
Oliver Schneider 54c80ad677 fix range serialization 2016-07-14 15:37:05 +02:00
Oliver Schneider 16ba32dbe1 stateful map/seq serialization 2016-07-14 15:36:47 +02:00
Oliver Schneider 60938913b2 face -> palm 2016-07-13 19:18:01 +02:00
Oliver Schneider 26528fbbb4 silence lint about a: ref a patterns 2016-07-12 16:53:38 +02:00
Oliver Schneider 6adcaa55e5 json needs more info 2016-07-12 16:53:20 +02:00
Oliver Schneider fb575225bc simplify! 2016-07-12 16:16:48 +02:00
Oliver Schneider ee4e7413b0 whoops 2016-07-12 15:50:41 +02:00
Oliver Schneider a6f8bd5aac nightly 2016-07-12 15:49:41 +02:00
Oliver Schneider 3766633f4a adjust codegen to work with the revamped map/seq serializer 2016-07-12 15:44:19 +02:00
Dawid Ciężarkiewicz 99038b044e Eliminate Visitor pattern
Visitor is "pull", while `MapSerializer` and `SeqSerializer`
are "push" like the rest of the API.
2016-07-12 11:46:44 +02:00
David Tolnay 4ec0a7e672 Merge pull request #433 from softprops/add_envy
add envy
2016-07-10 20:59:50 -07:00
softprops a41dae45a5 add envy 2016-07-10 23:55:32 -04:00
David Tolnay cb9e1cfb54 Merge pull request #431 from serde-rs/version
Drop support for 1.7.0
2016-07-10 14:40:15 -07:00
David Tolnay 54ce7f2e90 Drop support for 1.7.0 2016-07-10 14:25:17 -07:00
David Tolnay ddbd139793 Merge pull request #430 from serde-rs/bump
Update syntex to 0.38
2016-07-09 11:51:38 -07:00
David Tolnay a070de28e2 Update syntex to 0.38 2016-07-09 11:37:01 -07:00
David Tolnay 57aeb26728 Merge pull request #428 from erickt/readme
Rewrite readme to front-load stable rust usage
2016-07-07 20:26:00 -07:00
Erick Tryzelaar a592828808 Rewrite readme to front-load stable rust usage 2016-07-07 14:31:24 -07:00
David Tolnay 67d86dcc4f Merge pull request #426 from serde-rs/display
impl Display for de::Type
2016-07-07 00:59:17 -07:00
David Tolnay 15764cb955 impl Display for de::Type 2016-07-06 23:33:59 -07:00
David Tolnay 97bc1e08e7 Release 0.7.13 2016-07-05 20:06:10 -07:00
Oliver Schneider 7ffb74f5bb Merge pull request #423 from dtolnay/seq
Close the seq before failing on invalid length
2016-07-05 22:44:52 +02:00
David Tolnay f25e6d3ea9 Close the seq before failing on invalid length
Equivalent to what 0f9a930 does for maps.
2016-07-05 10:08:36 -07:00
David Tolnay 431cbe48b7 Merge pull request #422 from serde-rs/missing
Close the map before checking for missing fields
2016-07-05 07:11:03 -07:00
Homu 5405ab319d Auto merge of #421 - serde-rs:length, r=oli-obk
Invalid-length when enum seq is too short

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

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

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

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

Fixes #360. The error looks like this:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

I should probably yank 0.7.6, too

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

This filters out junk files from the crates.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Used to be:

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

Now it is:

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

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

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

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

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

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

breaking-change

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

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

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

Example:
```json
fn visit_map<V>(&mut self, visitor: V) -> Result<Self::Value, V::Error>
    where V: de::MapVisitor
{
    let mut deserializer = de::value::MapVisitorDeserializer::new(visitor);
    try!(Deserialize::deserialize(&mut deserializer))
}
```
2015-10-08 15:22:02 +02:00
Erick Tryzelaar 534e6d1f4c Merge pull request #167 from pwoolcoc/patch-1
Fix code block end marker
2015-10-06 11:50:54 -07:00
Paul Woolcock 7ad31a01dd Fix code block end marker
Looks like someone accidentally removed the `\`\`\`` from the end of a code block, causing the `Serialization without Macros` section to be formatted like code
2015-10-06 14:04:54 -04:00
Thomas Bahn e0429cdd96 style: remove the redundant Error suffix 2015-10-06 01:37:39 +02:00
Thomas Bahn 7413bbb7bf feat: ValueDeserializers are generic over the error type
This makes it possible to remove the `From<de::value::Error>` trait
bound from the `de::Error` trait.

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

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

Please note that there is an regression in serde-rs/json which needs to
be fixed.
2015-10-06 01:37:39 +02:00
Erick Tryzelaar 00cd2900e7 Merge pull request #155 from erickt/skip
Add skip serializing fields if empty or none
2015-10-05 14:51:46 -07:00
Erick Tryzelaar 05a238fac4 Merge pull request #164 from serde-rs/oli-obk-patch-1
add link to the README from the docs
2015-10-05 14:49:46 -07:00
Thomas Bahn 0a65153634 fix: forward more errors in de::value::Error
When using a `ValueDeserializer` errors produced with the methods
`type_mismatch`, `length_mismatch` and `syntax` were not forwarded
correctly. These methods now store all information in the enum
`de::value::Error`.
2015-10-05 23:40:36 +02:00
Oliver Schneider 310db21d64 add link to the README from the docs
The small starting page in the docs was noted at https://users.rust-lang.org/t/lets-talk-about-ecosystem-documentation/2791/25
2015-10-05 15:57:01 +02:00
Florian Gilcher fc19895237 Have serde::de::Error require std::error::Error 2015-09-24 07:03:36 -07:00
Erick Tryzelaar 72af0896e8 docs(codegen): Document annotations 2015-09-07 16:59:11 -07:00
Erick Tryzelaar c4392ff256 feat(codegen): Add more attributes to skip serializing
These attributes are `#[serde(skip_serializing_if_none)]` and
`#[serde(skip_serializing_if_empty)]`.
2015-09-07 16:58:52 -07:00
Erick Tryzelaar c68ab508c0 refactor(codegen): Simplify parsing attributes 2015-09-07 16:58:52 -07:00
Erick Tryzelaar 76cca814f0 docs(readme): Improve the readme 2015-09-07 16:58:46 -07:00
Erick Tryzelaar 22b69fc5c9 docs(serde): Fix typo 2015-09-07 13:02:53 -07:00
Homu a1bd0c1667 Auto merge of #153 - erickt:doc, r=erickt
Start documenting everything
2015-09-03 00:54:55 +09:00
Erick Tryzelaar 48ea75fddc Bump version
This is because I removed some public, but unused things
2015-09-02 08:54:01 -07:00
Erick Tryzelaar 4b49f716b9 Document serde::de::impls. 2015-09-02 08:36:14 -07:00
Erick Tryzelaar 55f5f397d7 Document serde::de::value 2015-09-02 08:36:14 -07:00
Erick Tryzelaar 4be4f60f21 Document serde::de::mod. 2015-09-02 08:36:14 -07:00
Erick Tryzelaar 9a8037bbf2 Remove unused Enum{Seq,Map}Visitor 2015-09-02 08:36:14 -07:00
Erick Tryzelaar c7f1af90b2 Document serde::iter 2015-09-02 08:36:14 -07:00
Erick Tryzelaar 902d3a0aa5 Document serde::bytes. 2015-09-02 08:36:14 -07:00
Erick Tryzelaar c14eb28223 Remove unused buf module. 2015-09-02 08:36:14 -07:00
Erick Tryzelaar 2722a04e52 Document serde::ser::impls 2015-09-02 08:36:14 -07:00
Erick Tryzelaar 5dbcd7957a Start documenting everything, starting with serde::ser. 2015-09-01 08:02:17 -07:00
Erick Tryzelaar 7511eeae7b Version bump
Closes #149
2015-08-31 10:04:34 -07:00
Erick Tryzelaar 5f4a7e54bc Fix README deserialization-without-macros example
Closes #150.
2015-08-31 09:23:33 -07:00
Erick Tryzelaar b7e3058078 Add coverage badge 2015-08-29 21:09:20 -07:00
Erick Tryzelaar f3358cc377 Merge pull request #144 from erickt/master
Factor serde_json out into it's own module
2015-08-29 21:06:21 -07:00
Erick Tryzelaar fa3460e0a7 Migrate serde_json into it's own repo
New location is https://github.com/serde-rs/json.
2015-08-29 18:09:51 -07:00
Erick Tryzelaar 42069ca669 Refactor tests to not use serde_json 2015-08-29 17:29:42 -07:00
Homu acc7141b64 Auto merge of #145 - erickt:travis, r=erickt
Travis work
2015-08-30 08:31:25 +09:00
Erick Tryzelaar 3e1b950b14 Merge pull request #147 from jmesmon/fix-readme
readme: fix example code so it builds
2015-08-28 08:31:17 -07:00
Cody P Schafer b50b702d1c readme: fix example code so it builds
Might be worthwhile to look at trying to automate testing the code in
the README (perhaps by generating the README from some special tests).
2015-08-28 11:27:03 -04:00
Erick Tryzelaar caddd11c15 Travis work 2015-08-27 22:51:11 -07:00
Erick Tryzelaar 5711e3d860 Merge pull request #143 from 3Hren/master
Add a Sized requirement to the Deserialize trait.
2015-08-24 21:41:58 -07:00
Evgeny Safronov 8b1058b8ec Add a Sized requirement to the Deserialize trait. 2015-08-24 18:44:19 +03:00
Erick Tryzelaar 092ba6dae2 Merge pull request #139 from erickt/str-keys
Reject serializing maps to JSON with non-string keys
2015-08-19 09:01:27 -07:00
Erick Tryzelaar cab653e7c7 Version bump 2015-08-18 12:50:39 -07:00
Erick Tryzelaar 8d999a8edd VecMap was removed from libcollections 2015-08-18 12:49:50 -07:00
Erick Tryzelaar 7b773ac088 Merge pull request #138 from erickt/master
Expose serde_json::from_{iter,reader,slice}
2015-08-13 22:32:34 -07:00
Erick Tryzelaar 4f6b27eec1 Black box json benchmark numbers
This prevents the optimizer from optimizing away the thing
we're benchmarking.
2015-08-13 22:30:02 -07:00
Erick Tryzelaar fe20852b2c Reject serializing maps to JSON with non-string keys
Closes #122. This is a breaking change since it modifies the
return type of serde_json::to_vec{,pretty}, so it'll require a major
version bump of serde_json.
2015-08-13 22:29:13 -07:00
Erick Tryzelaar fc58ea7487 Expose serde_json::from_{iter,reader,slice} 2015-08-13 21:19:27 -07:00
Erick Tryzelaar c61cea0eb1 Merge pull request #136 from erickt/visit
Have deserializer numeric visits chain
2015-08-13 21:19:19 -07:00
Erick Tryzelaar 764b25bd07 Have Deserializer::visit_{usize,u8,...,isize,i8,...,f32} call visit_{u64,i64,f64}
This cuts down the amount of overloading needed by a format like
toml which wants to prevent casting a float to an integer and
vice versa.
2015-08-13 08:40:19 -07:00
Erick Tryzelaar a66cd25787 Merge pull request #135 from erickt/doc
Add a table pointing to the serializers that support serde
2015-08-11 07:02:22 -07:00
Erick Tryzelaar 0e8d94750b Add a table pointing to the serializers that support serde 2015-08-11 07:00:59 -07:00
Erick Tryzelaar 3c915189f4 version bump 2015-08-10 10:09:37 -07:00
Erick Tryzelaar c5541cddeb Merge pull request #134 from erickt/err
Add Error::length_mismatch, Error::type_mismatch, and de::Type
2015-08-10 10:07:51 -07:00
Erick Tryzelaar 63561609a6 Add Error::length_mismatch, Error::type_mismatch, and de::Type
This improves error handling to match the needs of msgpack
2015-08-09 21:42:42 -07:00
Erick Tryzelaar 5dc356ddb0 Merge pull request #133 from erickt/fixup
Fix doc links, recover some json deserialization speed
2015-08-09 18:17:02 -07:00
Erick Tryzelaar dc36fd38d6 Gain back 10MB/s on the json deserialization benchmark 2015-08-09 16:45:55 -07:00
Erick Tryzelaar 26873bf3d5 Don't use sudo in the travis 2015-08-09 16:40:35 -07:00
Erick Tryzelaar ff53323790 Correct the documentation links in the crates 2015-08-09 16:38:10 -07:00
Erick Tryzelaar fd3869d380 Update the README 2015-08-09 16:37:21 -07:00
Erick Tryzelaar 1d538bc59d Merge pull request #132 from Byron/fix-codegen
Use fully qualified `Result` type
2015-08-08 15:48:49 -07:00
Sebastian Thiel 784cfcd49e Use fully qualified Result type
If that is not the case, the generated code might attempt to use a
custom `Result` type with incompatible type parameters.
2015-08-08 12:33:29 +02:00
Erick Tryzelaar a142d319e7 Point the serde_json readme at the root readme 2015-08-07 12:05:01 -07:00
Erick Tryzelaar da3bf3c20a Merge pull request #130 from oli-obk/fix
json deser from Value adjusted to be equal to deser from strings
2015-08-07 09:45:37 -07:00
Erick Tryzelaar 1672306fa1 Merge pull request #129 from erickt/remove-error
Remove "_error" from de::Error methods, add string argument to Error::syntax()
2015-08-07 09:45:11 -07:00
Oliver Schneider 7fc780ba1b json deser from Value adjusted to be equal to deser from strings 2015-08-07 18:31:42 +02:00
Erick Tryzelaar 7fb2bd50bf Add a string argument to Error::syntax() 2015-08-07 08:08:56 -07:00
Erick Tryzelaar 2aeb51ad51 Remove "_error" from de::Error::*_error 2015-08-07 07:53:22 -07:00
Erick Tryzelaar 0482b756e8 Merge pull request #127 from erickt/json3
Rewrite json parser to not require consuming the full stream
2015-08-07 07:52:52 -07:00
Erick Tryzelaar 1d9c707a76 Rewrite json parser to not require consuming the full stream
Closes #89
2015-08-06 11:12:37 -07:00
Erick Tryzelaar 199ed417bd Merge pull request #126 from erickt/json-f64
Update json number parsing to switch to floats if the number gets too big
2015-08-06 10:08:31 -07:00
Erick Tryzelaar 199a02cb68 i64::wrapping_neg is not stable yet 2015-08-06 09:31:37 -07:00
Erick Tryzelaar b6371f045f Simplify parsing a number 2015-08-06 07:12:00 -07:00
Erick Tryzelaar fd84aec485 Fix parsing min, max, and epsilon f64 values 2015-08-05 08:15:47 -07:00
Erick Tryzelaar ed6777e59f Fix json parsing i64::MIN, add tests for min and max i64 and u64 values 2015-08-03 09:09:44 -07:00
Erick Tryzelaar 22024a2b71 Simplify parsing floating point decimals and exponents 2015-08-01 14:26:53 -07:00
Erick Tryzelaar 8eff38b6f6 Eliminate some code duplication parsing an exponent as an integer 2015-08-01 13:50:42 -07:00
Erick Tryzelaar fa562d449d Minor optimization to not check if JSON number starts with '-' twice 2015-08-01 13:50:24 -07:00
Erick Tryzelaar c9d55362d6 Add a serde_json::Result helper type 2015-08-01 13:49:57 -07:00
Erick Tryzelaar 23031d057f Add test for parsing json "0" and "0.0" 2015-07-31 07:33:23 -07:00
Erick Tryzelaar 882d394352 Remove a debug comment 2015-07-31 07:28:07 -07:00
Erick Tryzelaar fbdede68a4 Build the serde_json docs 2015-07-31 07:24:05 -07:00
Erick Tryzelaar e88ef4715c Explicitly make the visit_struct_{,variant}_elt key a &'static str 2015-07-31 07:22:14 -07:00
Erick Tryzelaar 94f3dd25d8 Allow VariantVisitor::visit_newtype to default to calling visit_tuple 2015-07-31 07:22:13 -07:00
Erick Tryzelaar 2c58a9c11d Expose TupleVisitor*::new 2015-07-31 07:22:13 -07:00
Erick Tryzelaar 97528b59cf Add support for serializing newtype structs
This enables formats like JSON to serialize newtype wrapper
structs without the normal object wrapper. Consider types like:

```rust
struct Point {
    x: u32,
    y: u32,
}

stuct MyPoint(Point);
```

Before this patch, `MyPoint(1,2)` would get serialized as
`[{"x":1,"y":2}]`, but now it gets serialized as `{"x":1,"y"2}`.
2015-07-31 07:22:13 -07:00
Erick Tryzelaar 6715fb6652 Rename visit_simple to visit_newtype 2015-07-31 07:22:13 -07:00
Erick Tryzelaar fefc010deb Rename visit_enum_simple to visit_newtype_variant 2015-07-31 07:22:13 -07:00
Erick Tryzelaar 6cbb72decf Inlne the visit_seq method 2015-07-31 07:22:13 -07:00
Erick Tryzelaar 7e25ed863c Merge pull request #120 from erickt/enum-fields
Add enum fields and tuple length to deserialization visitor methods, renamed some more methods
2015-07-30 09:51:01 -07:00
Erick Tryzelaar 5a56394814 Add test to deserialize variants from usize and &[u8] 2015-07-30 08:06:04 -07:00
Erick Tryzelaar de1059f648 Allow Result<T, E> to use usize variant names 2015-07-30 08:06:04 -07:00
Erick Tryzelaar 97f08086dd Have visit_enum_simple default to calling visit_tuple_variant 2015-07-30 08:06:04 -07:00
Erick Tryzelaar 0348a3914d Pass variant index to visit_enum_simple 2015-07-30 08:06:04 -07:00
Erick Tryzelaar 5dc245d2ce Switch serializing Result to using simple enums 2015-07-30 08:06:04 -07:00
Erick Tryzelaar 71cc95248c Allow Option<T> to be used directly as a ser::SeqVisitor 2015-07-30 08:06:04 -07:00
Erick Tryzelaar 2cb7d66767 Add test for deserializing a simple enum 2015-07-30 08:06:04 -07:00
Erick Tryzelaar 49fa208242 Minor cleanup 2015-07-30 08:06:04 -07:00
Erick Tryzelaar d2fef27721 Rename ser::Serializer::visit_enum_{unit,seq,map} to visit_{unit,tuple,struct}_variant 2015-07-30 06:45:21 -07:00
Erick Tryzelaar 351b7039a8 Rename de::VariantVisitor::visit_{map,seq} to visit_{struct,tuple} 2015-07-30 06:45:21 -07:00
Erick Tryzelaar 7585ce9ed4 Re-indent 2015-07-30 06:45:21 -07:00
Erick Tryzelaar 578a0178b5 Make sure the visit_{enum,struct,tuple_struct} name is a &'static str 2015-07-30 06:45:21 -07:00
Erick Tryzelaar 6c9cebdcc3 Pass the variant fields and tuple lengths into visit_{enum,tuple,tuple_struct} 2015-07-30 06:45:21 -07:00
Erick Tryzelaar 35e2022e9a Point at github.com/serde-rs/serde 2015-07-30 06:43:20 -07:00
Erick Tryzelaar 0058e3a8d4 Merge pull request #111 from oli-obk/master
tuple enums with single element should not be a json-array
2015-07-29 13:35:43 -07:00
Erick Tryzelaar abf28ee167 Merge pull request #118 from erickt/ignore-fields
Add `#[serde(skip_serializing)] to skip serializing some fields
2015-07-29 10:08:19 -07:00
Oliver Schneider 5f1cb9b96c rebased again 2015-07-24 09:31:35 +02:00
Oliver 'ker' Schneider 8f8fc6f3ff nits and rebase fallout 2015-07-24 09:10:58 +02:00
Oliver Schneider 24787195a1 serialize tuple enums with single element directly as the value instead of a sequence 2015-07-24 09:10:58 +02:00
Oliver Schneider 5885111863 deserialize tuple enums with single element directly as the value instead of a sequence 2015-07-24 09:10:58 +02:00
Erick Tryzelaar b1cb5379de Add `#[serde(skip_serializing)] to skip serializing some fields
Closes #99
2015-07-23 08:07:49 -07:00
Erick Tryzelaar 447d08bd91 Merge pull request #117 from erickt/fix-json
Fix deriving traits for fully generic types.
2015-07-23 08:04:46 -07:00
Erick Tryzelaar b0512a4479 Fix deriving traits for fully generic types.
Closes #100
2015-07-23 07:25:27 -07:00
Erick Tryzelaar 8663435a05 Merge remote-tracking branch 'remotes/origin/master' into v5-5
# Conflicts:
#	serde_tests/tests/test_json.rs
2015-07-23 07:04:10 -07:00
Erick Tryzelaar 327990bc5f Merge pull request #115 from erickt/fix-json
Fix serializing maps/sequences with no size hint
2015-07-23 06:58:18 -07:00
Erick Tryzelaar 57753c9044 Fix references to serde::json 2015-07-22 10:44:43 -07:00
Erick Tryzelaar e35603eb85 Fix serializing maps/sequences with no size hint
Closes #101
2015-07-22 10:44:43 -07:00
Erick Tryzelaar 8fa40fe7e1 Move json into it's own crate
Not everyone needs json, so no reason to force people to build
it.
2015-07-22 10:44:43 -07:00
Erick Tryzelaar d4c20829f6 Inline enum visit_map 2015-07-22 10:44:43 -07:00
Erick Tryzelaar dbe2beacb0 Allow structs to be deserialized from sequences
This relies on the sequence to have the same ordering as the
struct field order.
2015-07-22 10:44:43 -07:00
Erick Tryzelaar b9a938a01c Some default de::Visitor::visit* should proxy to other methods 2015-07-22 10:44:43 -07:00
Erick Tryzelaar 4dd7345568 Simplify result serialization and deserialization 2015-07-22 10:44:43 -07:00
Erick Tryzelaar b3cf9375d4 Add Tuple Deserializer Visitor constructor 2015-07-22 10:44:43 -07:00
Erick Tryzelaar 1751155a3a Minor cleanup 2015-07-22 10:44:43 -07:00
Erick Tryzelaar 5dae700aec Pass struct field names to deserializer 2015-07-22 10:44:42 -07:00
Erick Tryzelaar affa9382be Expose variant index to Serializer 2015-07-22 10:44:42 -07:00
Erick Tryzelaar 10f23dddfe Rename named_* to use {enum,struct,unit}_*
This better reflects how they're used.
2015-07-22 10:44:42 -07:00
Erick Tryzelaar d30cf07254 Serializer::visit_enum_seq{,_elt} should call visit_named_seq{,_elt} 2015-07-22 10:44:42 -07:00
Erick Tryzelaar 31491b822f Version bump 2015-07-22 10:44:42 -07:00
Erick Tryzelaar 4c19cfead5 Fix serializing maps/sequences with no size hint
Closes #101
2015-07-22 10:41:51 -07:00
Erick Tryzelaar b2754c2c3b Merge pull request #116 from erickt/travis
Use new travis containers
2015-07-22 10:41:38 -07:00
Erick Tryzelaar f56976db1d Fix running serde_tests with nightly cargo 2015-07-22 10:40:06 -07:00
Erick Tryzelaar 77b8a8baa0 Use new travis containers 2015-07-22 09:51:19 -07:00
Erick Tryzelaar 0b9190cce3 Merge pull request #108 from dswd/patch-1
Make the TupleVisitors public
2015-07-18 21:21:09 -04:00
dswd 2a40c5dd24 Make the TupleVisitors public
This change is needed to use the TupleVisitor to implement a VariantVisitor
2015-07-17 09:58:55 +02:00
Erick Tryzelaar 60ab494226 Fix cd serde_macros && cargo build 2015-07-16 13:48:15 -04:00
Erick Tryzelaar ac758ed3c8 Version bump 2015-07-16 11:28:18 -04:00
Erick Tryzelaar 236d40d73e Add Serializer hooks for sequence elements 2015-07-16 10:51:01 -04:00
Erick Tryzelaar 92029a05c6 Add Deserializer type hints
This allows file formats like bincode, which do not encode it's values
with a type tag, to deserialize values.
2015-07-16 10:50:54 -04:00
Erick Tryzelaar c7b9997dd1 Add all of the stdlib collection deserialization implementations 2015-07-16 10:42:34 -04:00
Erick Tryzelaar 48309bfdd0 Add all of the stdlib collection serialization implementations 2015-07-16 10:00:22 -04:00
Erick Tryzelaar f76d1ab10d Compile serde_macros tests with the nightly features 2015-07-16 10:00:22 -04:00
Erick Tryzelaar 45f552f006 Fix feature flag use for NonZero 2015-07-16 10:00:21 -04:00
Erick Tryzelaar 4d42cfea53 Fix warnings 2015-07-16 09:36:14 -04:00
Erick Tryzelaar 7109e2d379 Fix the tests 2015-07-16 09:35:09 -04:00
Erick Tryzelaar ff214643ce Merge remote-tracking branch 'remotes/origin/master' into nonzero
# Conflicts:
#	serde/src/de/impls.rs
2015-07-16 09:34:45 -04:00
Erick Tryzelaar 04918a52eb Merge pull request #105 from jnicholls/boolvisitor
Make BoolVisitor public so it is documented as being in existence
2015-07-16 07:41:49 -04:00
Erick Tryzelaar 5dd71600f7 Merge pull request #102 from pcwalton/result
Implement serialization for `Result`.
2015-07-16 07:29:28 -04:00
Patrick Walton ea9ed22e3e Implement serialization for NonZero values in nightly. 2015-07-14 12:00:46 -07:00
Jarred Nicholls 1611daf802 Make BoolVisitor public so it is documented as being in existence 2015-07-13 12:13:00 -04:00
Patrick Walton e24f52d3ae Implement serialization for Result.
Servo wants this.
2015-07-10 15:08:59 -07:00
Erick Tryzelaar bcc9e15b05 Merge pull request #94 from cmbrandenburg/master
Fix spelling in README.md
2015-07-01 10:38:13 -07:00
Craig M. Brandenburg af835a2699 Fix spelling in README.md 2015-06-29 07:18:48 -07:00
Erick Tryzelaar 5f2d306f9b Merge pull request #92 from SkylerLipthay/cow-impls
Add impls for Cow
2015-06-21 10:07:00 -07:00
Skyler Lipthay 36fb49b522 Add impls for Cow 2015-06-19 22:50:16 -07:00
Erick Tryzelaar ed5b4d7319 Fix serializing generic enums
This fixes generic enums with variants that don't use all lifetime
and typarams. Closes #88.
2015-06-18 08:45:03 -07:00
Erick Tryzelaar b09c0fc653 Fix an indent typo 2015-06-18 07:49:13 -07:00
Erick Tryzelaar ab3e40ca45 Version bump 2015-06-08 07:12:27 -07:00
Erick Tryzelaar 8f67e9c048 Switch exponent bounds checking back to using powi 2015-06-08 07:07:09 -07:00
Erick Tryzelaar 7dc1a64f03 Merge pull request #80 from ProtectedMode/master
Fix #77, integer overflow when parsing JSON scientific notation number.
2015-06-08 06:57:33 -07:00
Erick Tryzelaar ac3a3e922f Fix compilation with rust nightly (613e57b44) and syntex 0.7.0 2015-06-08 06:55:36 -07:00
Erick Tryzelaar 4e50c56542 Merge pull request #87 from Manishearth/patch-1
Use correct attribute syntax
2015-06-07 20:46:44 -07:00
Manish Goregaokar 26b1ed79c0 !!!!!! 2015-06-06 18:08:33 +05:30
ProtectedMode 2e8ef0f768 Add test for #77, integer overflow when parsing JSON scientific notation number. 2015-05-21 09:59:14 +02:00
Erick Tryzelaar c993414b92 serde_tests tests doesn't need the test crate 2015-05-20 22:57:19 -07:00
Erick Tryzelaar ed6ef4e149 Travis work 2015-05-20 22:44:50 -07:00
Erick Tryzelaar 859cdcc815 Remove unnecessary lifetime 2015-05-20 09:02:38 -07:00
ProtectedMode 745a95b607 Fix #77, integer overflow when parsing JSON scientific notation number. 2015-05-20 16:32:10 +02:00
Erick Tryzelaar 81d617bd93 The README is in a different location 2015-05-18 23:36:46 -07:00
Erick Tryzelaar 3396388222 Remove redundant import 2015-05-18 23:34:17 -07:00
Erick Tryzelaar ff8c3b3d51 Initial support for syntex 2015-05-18 23:34:17 -07:00
Erick Tryzelaar 3d0efd123f Minor cleanup 2015-05-18 22:49:50 -07:00
Erick Tryzelaar 8ca1b9ac3c default_value doesn't need to be public 2015-05-18 22:49:49 -07:00
Erick Tryzelaar 2c24be90d2 Switch to using MultiDecorator 2015-05-18 22:49:49 -07:00
Erick Tryzelaar 482f92af61 Add a single driver for tests and benchmarks 2015-05-18 22:47:36 -07:00
Erick Tryzelaar 24ac61f9f2 Pull codegen into it's own crate 2015-05-18 22:47:35 -07:00
Erick Tryzelaar 426394cd7b Version bump 2015-05-18 22:47:35 -07:00
Erick Tryzelaar 7c3e95a7c7 Ignore all target and Cargo.lock files 2015-05-18 22:47:35 -07:00
Erick Tryzelaar 9dd5f9dc7a Restructure directories to prep for syntex 2015-05-18 22:47:35 -07:00
Erick Tryzelaar e6776ffc37 Protect against json integer overflow
Closes #75
2015-05-18 22:40:29 -07:00
Erick Tryzelaar adae2bd3c5 Merge pull request #72 from borman/bytestrings
Improved support for byte strings
2015-05-18 22:28:37 -07:00
Erick Tryzelaar 14ca260c26 Merge pull request #70 from oli-obk/xml_requirements
changes needed for xml parsing
2015-05-18 22:25:15 -07:00
Erick Tryzelaar 64588f0cb6 Merge pull request #74 from tomprogrammer/array
Add serialization/deserialization for fixed size arrays
2015-05-18 22:21:59 -07:00
Erick Tryzelaar 50cac7f985 Rewrite Value::lookup to not require an allocation 2015-05-18 22:19:30 -07:00
Erick Tryzelaar 5fe85128c2 Merge pull request #76 from blaenk/json-lookup
implement lookup method for json::Value
2015-05-18 21:50:55 -07:00
Jorge Israel Peña bc236bde34 implement lookup method for json::Value 2015-05-17 21:24:00 -07:00
Thomas Bahn 15794a5ed6 Improve build time 2015-05-16 14:36:28 +02:00
Thomas Bahn 62058962de Add deserialiation implementations for fixed size arrays 2015-05-16 14:19:22 +02:00
Thomas Bahn 7d52366403 Add serialization implementations for fixed size arrays 2015-05-16 14:18:32 +02:00
Erick Tryzelaar ee45eb8340 Merge pull request #69 from hugoduncan/feature/format-specific-field-names
Adds serializer format specific field names
2015-05-14 21:59:05 -07:00
Hugo Duncan 801f37b305 Fix visitors for generic structs 2015-05-14 17:35:21 -04:00
Hugo Duncan bdec0b3e63 Update commas and blocks in match arms 2015-05-14 17:35:16 -04:00
Mikhail Borisov 5c631f3e58 WIP 2015-05-12 15:16:06 +03:00
Mikhail Borisov 5fd9daa865 WIP 2015-05-12 15:03:26 +03:00
Oliver Schneider 0485702a68 update benchmarks 2015-05-11 10:34:58 +02:00
Mikhail Borisov 875610044f Improved support for byte strings 2015-05-09 03:18:13 +03:00
Hugo Duncan ec483fc07d Add doc string for format method 2015-05-08 12:43:12 -04:00
Hugo Duncan 53e6e29571 Fix whitespace 2015-05-08 12:43:12 -04:00
Hugo Duncan c5eed99c6a Make forwarded trait name global 2015-05-08 12:43:12 -04:00
Hugo Duncan fe5176113b Add missing attr.rs file 2015-05-08 12:43:12 -04:00
Hugo Duncan 0f7c67efa7 Factor default attribute lookup into FieldAttrs 2015-05-08 12:43:12 -04:00
Hugo Duncan cd0ee64892 Add constructor functions for FieldAttrs 2015-05-08 12:43:12 -04:00
Hugo Duncan ec3af2cb6a Factor out attr module
Factors out field attribute code into the attr module.
2015-05-08 12:43:12 -04:00
Hugo Duncan 960b68937d Remove commented code and extra newline 2015-05-08 12:43:12 -04:00
Hugo Duncan a1e101b513 Make Value use the 'json' format string 2015-05-08 12:43:11 -04:00
Hugo Duncan c30311153c Rename fmt to format 2015-05-08 12:43:11 -04:00
Hugo Duncan a935ebe8b9 Adds serializer format specific field names
Allows different field names to be used for different external formats.

Field names are specified using the `rename` field attribute, e.g:

    #[serde(rename(xml= "a4", json="a5"))]

Reverts #62

Addresses #61
2015-05-08 12:43:11 -04:00
Oliver Schneider 83ee86122b address comments by erickt 2015-05-08 16:32:46 +02:00
Erick Tryzelaar af752ddcb5 Merge pull request #71 from lifthrasiir/json-split-branch
Replace a redundant `escape` variable with nested matches.
2015-05-07 10:51:57 -07:00
Kang Seonghoon 9550063275 Replace a redundant escape variable with nested matches.
This has a non-trivial performance effect due to the branch prediction,
but is expected to be no slower than the older code and, at least in
some cases, is slightly faster for a string-heavy JSON.
2015-05-08 01:53:24 +09:00
Oliver Schneider c117a680cf changes needed for xml parsing 2015-05-04 16:07:19 +02:00
150 changed files with 24435 additions and 13958 deletions
+4 -2
View File
@@ -1,2 +1,4 @@
/target/
/Cargo.lock
target/
**/*.rs.bk
*.sw[po]
Cargo.lock
+16 -15
View File
@@ -1,16 +1,17 @@
sudo: false
language: rust
script:
- cargo test
- cargo bench
- cargo doc
after_success: |
[ $TRAVIS_BRANCH = "master" ] &&
[ $TRAVIS_PULL_REQUEST = false ] &&
cargo doc &&
echo "<meta http-equiv=refresh content=0;url=`echo $TRAVIS_REPO_SLUG | cut -d '/' -f 2`/index.html>" > target/doc/index.html &&
sudo pip install ghp-import &&
ghp-import -n target/doc &&
git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
env:
global:
secure: HO41LMpMXkF2In9+1sxWVu7fgolL+y9+4Q5PI6wZX2L5pDwpPJCjxaQarQXCEnoIxED1PlP03JuF7ULNz0zw1ylYhAOfOSdkxFZRnE2wMZqq6qvXBHwyMiDrAociIzoPKSGv7JVrKPsjsnd+96K6xxueIodQZrmAdyq7N/M82Mc=
cache: cargo
# run builds for all the trains (and more)
rust:
- 1.13.0
- stable
- beta
- nightly
matrix:
include:
- rust: nightly
env: CLIPPY=true
script: ./travis.sh
+45
View File
@@ -0,0 +1,45 @@
# Contributing to Serde
Serde welcomes contribution from everyone. Here are the guidelines if you are
thinking of helping us:
## Contributions
Contributions to Serde or its dependencies should be made in the form of GitHub
pull requests. Each pull request will be reviewed by a core contributor
(someone with permission to land patches) and either landed in the main tree or
given feedback for changes that would be required. All contributions should
follow this format, even those from core contributors.
Should you wish to work on an issue, please claim it first by commenting on
the GitHub issue that you want to work on it. This is to prevent duplicated
efforts from contributors on the same issue.
## Pull Request Checklist
- Branch from the master branch and, if needed, rebase to the current master
branch before submitting your pull request. If it doesn't merge cleanly with
master you may be asked to rebase your changes.
- Commits should be as small as possible, while ensuring that each commit is
correct independently (i.e., each commit should compile and pass tests).
- If your patch is not getting reviewed or you need a specific person to review
it, you can @-reply a reviewer asking for a review in the pull request or a
comment, or you can ask for a review in `#serde` on `irc.mozilla.org`.
- Add tests relevant to the fixed bug or new feature.
## Conduct
In all Serde-related forums, we follow the [Rust Code of
Conduct](https://www.rust-lang.org/conduct.html). For escalation or moderation
issues, please contact Erick (erick.tryzelaar@gmail.com) instead of the Rust
moderation team.
## Communication
Beyond opening tickets on the
[serde-rs/serde](https://github.com/serde-rs/serde) project, Serde contributors
frequent the `#serde` channel on
[`irc.mozilla.org`](https://wiki.mozilla.org/IRC).
+9 -17
View File
@@ -1,17 +1,9 @@
[package]
name = "serde"
version = "0.3.3"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
repository = "https://github.com/serde-rs/serde"
documentation = "http://serde-rs.github.io/serde/serde"
readme = "README.md"
keywords = ["serialization"]
[dependencies]
num = "*"
[dev-dependencies]
rustc-serialize = "*"
serde_macros = { version = "*", path = "serde_macros" }
[workspace]
members = [
"serde",
"serde_derive",
"serde_derive_internals",
"serde_test",
"test_suite",
"test_suite/no_std",
]
-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.
+54 -397
View File
@@ -1,424 +1,81 @@
Serde Rust Serialization Framework
==================================
# Serde &emsp; [![Build Status]][travis] [![Latest Version]][crates.io]
[![Build Status](https://api.travis-ci.org/serde-rs/serde.png?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
[travis]: https://travis-ci.org/serde-rs/serde
[Latest Version]: https://img.shields.io/crates/v/serde.svg
[crates.io]: https://crates.io/crates/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.
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
Documentation is available at http://serde-rs.github.io/serde/serde
---
Making a Type Serializable
==========================
You may be looking for:
The simplest way to make a type serializable is to use the `serde_macros`
syntax extension, which comes with a `#[derive(Serialize, Deserialize)]`
annotation, which automatically generates implementations of
[Serialize](http://serde-rs.github.io/serde/serde/ser/trait.Serialize.html)
and
[Deserialize](http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html)
for the annotated type:
- [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)
## Serde in action
<a href="http://play.integer32.com/?gist=9003c5b88c1f4989941925d7190c6eec" target="_blank">
<img align="right" width="50" src="https://raw.githubusercontent.com/serde-rs/serde-rs.github.io/master/img/run.png">
</a>
```rust
#[feature(custom_derive, plugin)]
#[plugin(serde_macros)]
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
...
#[derive(Serialize, Deserialize)]
struct Point {
x: i32,
y: i32,
}
```
Serde bundles a high performance JSON serializer and deserializer,
[serde::json](http://serde-rs.github.io/serde/serde/json/index.html),
which comes with the helper functions
[to_string](http://serde-rs.github.io/serde/serde/json/ser/fn.to_string.html)
and
[from_str](http://serde-rs.github.io/serde/serde/json/de/fn.from_str.html)
that make it easy to go to and from JSON:
```rust
use serde::json;
...
let point = Point { x: 1, y: 2 };
let serialized_point = json::to_string(&point).unwrap();
println!("{}", serialized_point); // prints: {"x":1,"y":2}
let deserialize_point: Point = json::from_str(&serialized_point).unwrap();
```
[serde::json](http://serde-rs.github.io/serde/serde/json/index.html) also
supports a generic
[Value](http://serde-rs.github.io/serde/serde/json/value/enum.Value.html)
type, which can represent any JSON value. Also, any
[Serialize](http://serde-rs.github.io/serde/serde/ser/trait.Serialize.html)
and
[Deserialize](http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html)
can be converted into a
[Value](http://serde-rs.github.io/serde/serde/json/value/enum.Value.html)
with the methods
[to_value](http://serde-rs.github.io/serde/serde/json/value/fn.to_value.html)
and
[from_value](http://serde-rs.github.io/serde/serde/json/value/fn.from_value.html):
```rust
let point = Point { x: 1, y: 2 };
let point_value = json::to_value(&point).unwrap();
println!("{}", point_value.find("x")); // prints: Some(1)
let deserialize_point: Point = json::from_value(point_value).unwrap();
```
Serialization without Macros
============================
Under the covers, Serde extensively uses the Visitor pattern to thread state
between the
[Serializer](http://serde-rs.github.io/serde/serde/ser/trait.Serializer.html)
and
[Serialize](http://serde-rs.github.io/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/ser/trait.Serializer.html)
is threaded through the type:
```rust
impl serde::Serialize for i32 {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: serde::Serializer,
{
serializer.visit_i32(*self)
}
}
```
As you can see it's pretty simple. More complex types like `BTreeMap` need to
pass a
[MapVisitor](http://serde-rs.github.io/serde/serde/ser/trait.MapVisitor.html)
to the
[Serializer](http://serde-rs.github.io/serde/serde/ser/trait.Serializer.html)
in order to walk through the type:
```rust
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.visit_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.visit_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. It's visitor uses a simple state machine to iterate through all
the fields:
```rust
#[derive(Serialize, Deserialize, Debug)]
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.visit_named_map("Point", PointMapVisitor {
value: self,
state: 0,
})
}
}
fn main() {
let point = Point { x: 1, y: 2 };
struct PointMapVisitor<'a> {
value: &'a Point,
state: u8,
}
// Convert the Point to a JSON string.
let serialized = serde_json::to_string(&point).unwrap();
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.visit_map_elt("x", &self.value.x))))
}
1 => {
self.state += 1;
Ok(Some(try!(serializer.visit_map_elt("y", &self.value.y))))
}
_ => {
Ok(None)
}
}
}
// 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();
// Prints deserialized = Point { x: 1, y: 2 }
println!("deserialized = {:?}", deserialized);
}
```
Deserialization without Macros
==============================
## Getting help
Deserialization is a little more complicated since there's a bit more error
handling that needs to occur. Let's start with the simple `i32`
[Deserialize](http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html)
implementation. It passes a
[Visitor](http://serde-rs.github.io/serde/serde/de/trait.Visitor.html) to the
[Deserializer](http://serde-rs.github.io/serde/serde/de/trait.Deserializer.html).
The [Visitor](http://serde-rs.github.io/serde/serde/de/trait.Visitor.html)
can create the `i32` from a variety of different 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.
```rust
impl Deserialize for i32 {
fn deserialize<D>(deserializer: &mut D) -> Result<i32, D::Error>
where D: serde::Deserializer,
{
deserializer.visit(I32Visitor)
}
}
## License
struct I32Visitor;
Serde is licensed under either of
impl serde::de::Visitor for I32Visitor {
type Value = i32;
* 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_i16<E>(&mut self, value: i16) -> Result<i16, E>
where E: Error,
{
self.visit_i32(value as i32)
}
at your option.
fn visit_i32<E>(&mut self, value: i32) -> Result<i32, E>
where E: Error,
{
Ok(value)
}
### Contribution
...
```
Since it's possible for this type to get passed an unexpected type, we need a
way to error out. This is done by way of the
[Error](http://serde-rs.github.io/serde/serde/de/trait.Error.html) trait,
which allows a
[Deserialize](http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html)
to generate an error for a few common error conditions. Here's how it could be used:
```rust
...
fn visit_string<E>(&mut self, _: String) -> Result<i32, E>
where E: Error,
{
Err(serde::de::Error::syntax_error())
}
...
```
Maps follow a similar pattern as before, and use a
[MapVisitor](http://serde-rs.github.io/serde/serde/de/trait.MapVisitor.html)
to walk through the values generated by the
[Deserializer](http://serde-rs.github.io/serde/serde/de/trait.Deserializer.html).
```rust
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.visit(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
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 FieldVisitor;
impl serde::de::Visitor for FieldVisitor {
type Value = Field;
fn visit_str<E>(&mut self, value: &str) -> Result<PointField, E>
where E: serde::de::Error
{
match value {
"x" => Ok(Field::X),
"y" => Ok(Field::Y),
_ => Err(serde::de::Error::syntax_error()),
}
}
}
deserializer.visit(FieldVisitor)
}
}
```
This is then used in our actual deserializer:
```rust
impl serde::Deserialize for Point {
fn deserialize<D>(deserializer: &mut D) -> Result<Point, D::Error>
where D: serde::de::Deserializer
{
deserializer.visit_named_map("Point", 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(Field::X) => { x = Some(try!(visitor.visit_value())); }
Some(Field::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 })
}
}
```
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.
+17
View File
@@ -0,0 +1,17 @@
environment:
matrix:
- APPVEYOR_RUST_CHANNEL: stable
- APPVEYOR_RUST_CHANNEL: nightly
install:
# Install rust, x86_64-pc-windows-msvc host
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
- rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain %APPVEYOR_RUST_CHANNEL%
- set PATH=C:\msys64\usr\bin;%PATH%;C:\Users\appveyor\.cargo\bin
- rustc -vV
- cargo -vV
build: false
test_script:
- sh -c 'PATH=`rustc --print sysroot`/bin:$PATH ./travis.sh'
-454
View File
@@ -1,454 +0,0 @@
#![feature(custom_derive, plugin, test)]
#![plugin(serde_macros)]
extern crate serde;
extern crate rustc_serialize;
extern crate test;
use test::Bencher;
use rustc_serialize::{Decoder, Decodable};
use serde::de::{Deserializer, Deserialize};
use Animal::{Dog, Frog};
//////////////////////////////////////////////////////////////////////////////
#[derive(Clone, PartialEq, Debug, RustcDecodable, Deserialize)]
pub enum Animal {
Dog,
Frog(String, isize)
}
//////////////////////////////////////////////////////////////////////////////
#[derive(Debug)]
pub enum Error {
EndOfStreamError,
SyntaxError,
}
impl serde::de::Error for Error {
fn syntax_error() -> Error { Error::SyntaxError }
fn end_of_stream_error() -> Error { Error::EndOfStreamError }
fn unknown_field_error(_: &str) -> Error { Error::SyntaxError }
fn missing_field_error(_: &'static str) -> Error { Error::SyntaxError }
}
//////////////////////////////////////////////////////////////////////////////
mod decoder {
use rustc_serialize::Decoder;
use super::{Animal, Error};
use super::Animal::{Dog, Frog};
use self::State::{AnimalState, IsizeState, StringState};
enum State {
AnimalState(Animal),
IsizeState(isize),
StringState(String),
}
pub struct AnimalDecoder {
stack: Vec<State>,
}
impl AnimalDecoder {
#[inline]
pub fn new(animal: Animal) -> AnimalDecoder {
AnimalDecoder {
stack: vec!(AnimalState(animal)),
}
}
}
impl Decoder for AnimalDecoder {
type Error = Error;
fn error(&mut self, _: &str) -> Error { Error::SyntaxError }
// Primitive types:
fn read_nil(&mut self) -> Result<(), Error> { Err(Error::SyntaxError) }
fn read_usize(&mut self) -> Result<usize, Error> { Err(Error::SyntaxError) }
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::SyntaxError) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::SyntaxError) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::SyntaxError) }
fn read_u8(&mut self) -> Result<u8, Error> { Err(Error::SyntaxError) }
#[inline]
fn read_isize(&mut self) -> Result<isize, Error> {
match self.stack.pop() {
Some(IsizeState(x)) => Ok(x),
_ => Err(Error::SyntaxError),
}
}
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::SyntaxError) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::SyntaxError) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::SyntaxError) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::SyntaxError) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::SyntaxError) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::SyntaxError) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::SyntaxError) }
fn read_char(&mut self) -> Result<char, Error> { Err(Error::SyntaxError) }
#[inline]
fn read_str(&mut self) -> Result<String, Error> {
match self.stack.pop() {
Some(StringState(x)) => Ok(x),
_ => Err(Error::SyntaxError),
}
}
// 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(AnimalState(animal)) => {
self.stack.push(AnimalState(animal));
if name == "Animal" {
f(self)
} else {
Err(Error::SyntaxError)
}
}
_ => Err(Error::SyntaxError)
}
}
#[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(AnimalState(Dog)) => "Dog",
Some(AnimalState(Frog(x0, x1))) => {
self.stack.push(IsizeState(x1));
self.stack.push(StringState(x0));
"Frog"
}
_ => { return Err(Error::SyntaxError); }
};
let idx = match names.iter().position(|n| *n == name) {
Some(idx) => idx,
None => { return Err(Error::SyntaxError); }
};
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::SyntaxError)
}
fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_struct_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple<T, F>(&mut self, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
// Specialized types:
fn read_option<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder, bool) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
#[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::SyntaxError)
}
fn read_map_elt_key<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_map_elt_val<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
}
}
//////////////////////////////////////////////////////////////////////////////
mod deserializer {
use super::{Animal, Error};
use serde::de;
#[derive(Debug)]
enum State {
AnimalState(Animal),
IsizeState(isize),
StrState(&'static str),
StringState(String),
UnitState,
}
pub struct AnimalDeserializer {
stack: Vec<State>,
}
impl AnimalDeserializer {
#[inline]
pub fn new(animal: Animal) -> AnimalDeserializer {
AnimalDeserializer {
stack: vec!(State::AnimalState(animal)),
}
}
}
impl de::Deserializer for AnimalDeserializer {
type Error = Error;
#[inline]
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.stack.pop() {
Some(State::IsizeState(value)) => {
visitor.visit_isize(value)
}
Some(State::StringState(value)) => {
visitor.visit_string(value)
}
Some(State::StrState(value)) => {
visitor.visit_str(value)
}
Some(State::UnitState) => {
visitor.visit_unit()
}
Some(_) => {
Err(Error::SyntaxError)
}
None => {
Err(Error::EndOfStreamError)
}
}
}
#[inline]
fn visit_enum<V>(&mut self, _name: &str, mut visitor: V) -> Result<V::Value, Error>
where V: de::EnumVisitor,
{
match self.stack.pop() {
Some(State::AnimalState(Animal::Dog)) => {
self.stack.push(State::UnitState);
self.stack.push(State::StrState("Dog"));
visitor.visit(DogVisitor {
de: self,
})
}
Some(State::AnimalState(Animal::Frog(x0, x1))) => {
self.stack.push(State::IsizeState(x1));
self.stack.push(State::StringState(x0));
self.stack.push(State::StrState("Frog"));
visitor.visit(FrogVisitor {
de: self,
state: 0,
})
}
Some(_) => {
Err(Error::SyntaxError)
}
None => {
Err(Error::EndOfStreamError)
}
}
}
}
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_seq<V>(&mut self, 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::SyntaxError)
}
}
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 = 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 = Frog("Henry".to_string(), 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 = 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 = Frog("Henry".to_string(), 349);
let mut d = deserializer::AnimalDeserializer::new(animal.clone());
let value: Animal = Deserialize::deserialize(&mut d).unwrap();
assert_eq!(value, animal);
})
}
-1561
View File
File diff suppressed because it is too large Load Diff
-464
View File
@@ -1,464 +0,0 @@
#![feature(custom_derive, plugin, test)]
#![plugin(serde_macros)]
extern crate serde;
extern crate rustc_serialize;
extern crate test;
use std::fmt::Debug;
use std::collections::HashMap;
use test::Bencher;
use rustc_serialize::{Decoder, Decodable};
use serde::de::{Deserializer, Deserialize};
//////////////////////////////////////////////////////////////////////////////
#[derive(PartialEq, Debug)]
pub enum Error {
EndOfStream,
SyntaxError,
MissingField,
}
impl serde::de::Error for Error {
fn syntax_error() -> Error { Error::SyntaxError }
fn end_of_stream_error() -> Error { Error::EndOfStream }
fn unknown_field_error(_: &str) -> Error { Error::SyntaxError }
fn missing_field_error(_: &'static str) -> Error {
Error::MissingField
}
}
//////////////////////////////////////////////////////////////////////////////
mod decoder {
use std::collections::HashMap;
use std::collections::hash_map::IntoIter;
use rustc_serialize;
use super::Error;
use self::Value::{StringValue, IsizeValue};
enum Value {
StringValue(String),
IsizeValue(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::SyntaxError
}
// Primitive types:
fn read_nil(&mut self) -> Result<(), Error> { Err(Error::SyntaxError) }
fn read_usize(&mut self) -> Result<usize, Error> { Err(Error::SyntaxError) }
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::SyntaxError) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::SyntaxError) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::SyntaxError) }
fn read_u8(&mut self) -> Result<u8, Error> { Err(Error::SyntaxError) }
#[inline]
fn read_isize(&mut self) -> Result<isize, Error> {
match self.stack.pop() {
Some(IsizeValue(x)) => Ok(x),
Some(_) => Err(Error::SyntaxError),
None => Err(Error::EndOfStream),
}
}
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::SyntaxError) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::SyntaxError) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::SyntaxError) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::SyntaxError) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::SyntaxError) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::SyntaxError) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::SyntaxError) }
fn read_char(&mut self) -> Result<char, Error> { Err(Error::SyntaxError) }
#[inline]
fn read_str(&mut self) -> Result<String, Error> {
match self.stack.pop() {
Some(StringValue(x)) => Ok(x),
Some(_) => Err(Error::SyntaxError),
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::SyntaxError)
}
fn read_enum_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_enum_struct_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_struct_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple<T, F>(&mut self, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
// Specialized types:
fn read_option<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder, bool) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_seq<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_seq_elt<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
#[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(IsizeValue(value));
self.stack.push(StringValue(key));
f(self)
}
None => {
Err(Error::SyntaxError)
}
}
}
#[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,
KeyState(String),
ValueState(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 visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.stack.pop() {
Some(State::StartState) => {
visitor.visit_map(self)
}
Some(State::KeyState(key)) => {
visitor.visit_string(key)
}
Some(State::ValueState(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::ValueState(value));
self.stack.push(State::KeyState(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::SyntaxError),
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(StartState) => {
self.stack.push(KeyOrEndState);
Some(Ok(de::Token::MapStart(self.len)))
}
Some(KeyOrEndState) => {
match self.iter.next() {
Some((key, value)) => {
self.stack.push(ValueState(value));
Some(Ok(de::Token::String(key)))
}
None => {
self.stack.push(EndState);
Some(Ok(de::Token::End))
}
}
}
Some(ValueState(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_error(&mut self) -> Error {
EndOfStream
}
#[inline]
fn syntax_error(&mut self, _token: de::Token, _expected: &[de::TokenKind]) -> Error {
SyntaxError
}
#[inline]
fn unexpected_name_error(&mut self, _token: de::Token) -> Error {
SyntaxError
}
#[inline]
fn conversion_error(&mut self, _token: de::Token) -> Error {
SyntaxError
}
#[inline]
fn missing_field<
T: de::Deserialize<IsizeDeserializer, Error>
>(&mut self, _field: &'static str) -> Result<T, Error> {
Err(Error::SyntaxError)
}
}
*/
}
//////////////////////////////////////////////////////////////////////////////
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: Deserializer<Error=E>,
E: Debug,
T: Clone + PartialEq + Debug + Deserialize
>(mut d: D, value: T) {
let v: T = Deserialize::deserialize(&mut d).unwrap();
assert_eq!(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 @@
#![feature(custom_derive, plugin, test)]
#![plugin(serde_macros)]
extern crate serde;
extern crate rustc_serialize;
extern crate test;
use std::collections::HashMap;
use test::Bencher;
use rustc_serialize::{Decoder, Decodable};
use serde::de::{Deserializer, 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,
SyntaxError,
UnexpectedName,
ConversionError,
MissingField,
OtherError,
}
impl serde::de::Error for Error {
fn syntax_error() -> Error { Error::SyntaxError }
fn end_of_stream_error() -> Error { Error::EndOfStream }
fn unknown_field_error(_: &str) -> Error { Error::SyntaxError }
fn missing_field_error(_: &'static str) -> Error {
Error::MissingField
}
}
mod decoder {
use std::collections::HashMap;
use rustc_serialize::Decoder;
use super::{Outer, Inner, Error};
use self::State::{
OuterState,
InnerState,
NullState,
UsizeState,
CharState,
StringState,
FieldState,
VecState,
MapState,
OptionState,
};
#[derive(Debug)]
enum State {
OuterState(Outer),
InnerState(Inner),
NullState,
UsizeState(usize),
CharState(char),
StringState(String),
FieldState(&'static str),
VecState(Vec<Inner>),
MapState(HashMap<String, Option<char>>),
OptionState(bool),
}
pub struct OuterDecoder {
stack: Vec<State>,
}
impl OuterDecoder {
#[inline]
pub fn new(animal: Outer) -> OuterDecoder {
OuterDecoder {
stack: vec!(OuterState(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(NullState) => Ok(()),
_ => Err(Error::SyntaxError),
}
}
#[inline]
fn read_usize(&mut self) -> Result<usize, Error> {
match self.stack.pop() {
Some(UsizeState(value)) => Ok(value),
_ => Err(Error::SyntaxError),
}
}
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::SyntaxError) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::SyntaxError) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::SyntaxError) }
fn read_u8(&mut self) -> Result<u8, Error> { Err(Error::SyntaxError) }
fn read_isize(&mut self) -> Result<isize, Error> { Err(Error::SyntaxError) }
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::SyntaxError) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::SyntaxError) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::SyntaxError) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::SyntaxError) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::SyntaxError) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::SyntaxError) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::SyntaxError) }
#[inline]
fn read_char(&mut self) -> Result<char, Error> {
match self.stack.pop() {
Some(CharState(c)) => Ok(c),
_ => Err(Error::SyntaxError),
}
}
#[inline]
fn read_str(&mut self) -> Result<String, Error> {
match self.stack.pop() {
Some(StringState(value)) => Ok(value),
_ => Err(Error::SyntaxError),
}
}
// 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::SyntaxError)
}
fn read_enum_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_enum_struct_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
#[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(OuterState(Outer { inner })) => {
if s_name == "Outer" {
self.stack.push(VecState(inner));
self.stack.push(FieldState("inner"));
f(self)
} else {
Err(Error::SyntaxError)
}
}
Some(InnerState(Inner { a: (), b, c })) => {
if s_name == "Inner" {
self.stack.push(MapState(c));
self.stack.push(FieldState("c"));
self.stack.push(UsizeState(b));
self.stack.push(FieldState("b"));
self.stack.push(NullState);
self.stack.push(FieldState("a"));
f(self)
} else {
Err(Error::SyntaxError)
}
}
_ => Err(Error::SyntaxError),
}
}
#[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(FieldState(name)) => {
if f_name == name {
f(self)
} else {
Err(Error::SyntaxError)
}
}
_ => Err(Error::SyntaxError)
}
}
fn read_tuple<T, F>(&mut self, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
// 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(OptionState(b)) => f(self, b),
_ => Err(Error::SyntaxError),
}
}
#[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(VecState(value)) => {
let len = value.len();
for inner in value.into_iter().rev() {
self.stack.push(InnerState(inner));
}
f(self, len)
}
_ => Err(Error::SyntaxError)
}
}
#[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(MapState(map)) => {
let len = map.len();
for (key, value) in map {
match value {
Some(c) => {
self.stack.push(CharState(c));
self.stack.push(OptionState(true));
}
None => {
self.stack.push(OptionState(false));
}
}
self.stack.push(StringState(key));
}
f(self, len)
}
_ => Err(Error::SyntaxError),
}
}
#[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 {
OuterState(Outer),
InnerState(Inner),
StrState(&'static str),
NullState,
UsizeState(usize),
CharState(char),
StringState(String),
OptionState(bool),
VecState(Vec<Inner>),
MapState(HashMap<String, Option<char>>),
}
pub struct OuterDeserializer {
stack: Vec<State>,
}
impl OuterDeserializer {
#[inline]
pub fn new(outer: Outer) -> OuterDeserializer {
OuterDeserializer {
stack: vec!(State::OuterState(outer)),
}
}
}
impl de::Deserializer for OuterDeserializer {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.stack.pop() {
Some(State::VecState(value)) => {
visitor.visit_seq(OuterSeqVisitor {
de: self,
iter: value.into_iter(),
})
}
Some(State::MapState(value)) => {
visitor.visit_map(MapVisitor {
de: self,
iter: value.into_iter(),
})
}
Some(State::NullState) => {
visitor.visit_unit()
}
Some(State::UsizeState(x)) => {
visitor.visit_usize(x)
}
Some(State::CharState(x)) => {
visitor.visit_char(x)
}
Some(State::StrState(x)) => {
visitor.visit_str(x)
}
Some(State::StringState(x)) => {
visitor.visit_string(x)
}
Some(State::OptionState(false)) => {
visitor.visit_none()
}
Some(State::OptionState(true)) => {
visitor.visit_some(self)
}
Some(_) => Err(Error::SyntaxError),
None => Err(Error::EndOfStream),
}
}
fn visit_named_map<V>(&mut self, name: &str, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.stack.pop() {
Some(State::OuterState(Outer { inner })) => {
if name != "Outer" {
return Err(Error::SyntaxError);
}
self.stack.push(State::VecState(inner));
self.stack.push(State::StrState("inner"));
visitor.visit_map(OuterMapVisitor {
de: self,
state: 0,
})
}
Some(State::InnerState(Inner { a: (), b, c })) => {
if name != "Inner" {
return Err(Error::SyntaxError);
}
self.stack.push(State::MapState(c));
self.stack.push(State::StrState("c"));
self.stack.push(State::UsizeState(b));
self.stack.push(State::StrState("b"));
self.stack.push(State::NullState);
self.stack.push(State::StrState("a"));
visitor.visit_map(InnerMapVisitor {
de: self,
state: 0,
})
}
_ => {
Err(Error::SyntaxError)
}
}
}
}
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::SyntaxError)
}
}
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::InnerState(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::SyntaxError),
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::SyntaxError)
}
}
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::CharState(value));
self.de.stack.push(State::OptionState(true));
self.de.stack.push(State::StringState(key));
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
Some((key, None)) => {
self.de.stack.push(State::OptionState(false));
self.de.stack.push(State::StringState(key));
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::SyntaxError),
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_string(), 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_string(), Some('a'));
map.insert("2".to_string(), None);
map.insert("3".to_string(), Some('b'));
map.insert("4".to_string(), None);
map.insert("5".to_string(), Some('c'));
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_string(), Some('a'));
map.insert("2".to_string(), None);
map.insert("3".to_string(), Some('b'));
map.insert("4".to_string(), None);
map.insert("5".to_string(), Some('c'));
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));
})
}
-617
View File
@@ -1,617 +0,0 @@
#![feature(plugin, test)]
#![plugin(serde_macros)]
extern crate serde;
extern crate rustc_serialize;
extern crate test;
use std::fmt::Debug;
use test::Bencher;
use rustc_serialize::{Decoder, Decodable};
use serde::de::{Deserializer, Deserialize};
//////////////////////////////////////////////////////////////////////////////
#[derive(PartialEq, Debug)]
pub enum Error {
EndOfStreamError,
SyntaxError,
}
impl serde::de::Error for Error {
fn syntax_error() -> Error { Error::SyntaxError }
fn end_of_stream_error() -> Error { Error::EndOfStreamError }
fn unknown_field_error(_: &str) -> Error { Error::SyntaxError }
fn missing_field_error(_: &'static str) -> Error { Error::SyntaxError }
}
//////////////////////////////////////////////////////////////////////////////
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::SyntaxError }
// Primitive types:
fn read_nil(&mut self) -> Result<(), Error> { Err(Error::SyntaxError) }
#[inline]
fn read_usize(&mut self) -> Result<usize, Error> {
match self.iter.next() {
Some(value) => Ok(value),
None => Err(Error::EndOfStreamError),
}
}
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::SyntaxError) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::SyntaxError) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::SyntaxError) }
fn read_u8(&mut self) -> Result<u8, Error> { Err(Error::SyntaxError) }
fn read_isize(&mut self) -> Result<isize, Error> { Err(Error::SyntaxError) }
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::SyntaxError) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::SyntaxError) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::SyntaxError) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::SyntaxError) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::SyntaxError) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::SyntaxError) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::SyntaxError) }
fn read_char(&mut self) -> Result<char, Error> { Err(Error::SyntaxError) }
fn read_str(&mut self) -> Result<String, Error> { Err(Error::SyntaxError) }
// Compound types:
fn read_enum<T, F>(&mut self, _name: &str, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_enum_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_enum_struct_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_struct_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple<T, F>(&mut self, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
// Specialized types:
fn read_option<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder, bool) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
#[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::SyntaxError)
}
fn read_map_elt_key<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_map_elt_val<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
}
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::SyntaxError }
// Primitive types:
fn read_nil(&mut self) -> Result<(), Error> { Err(Error::SyntaxError) }
fn read_usize(&mut self) -> Result<usize, Error> { Err(Error::SyntaxError) }
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::SyntaxError) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::SyntaxError) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::SyntaxError) }
#[inline]
fn read_u8(&mut self) -> Result<u8, Error> {
match self.iter.next() {
Some(value) => Ok(value),
None => Err(Error::EndOfStreamError),
}
}
#[inline]
fn read_isize(&mut self) -> Result<isize, Error> { Err(Error::SyntaxError) }
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::SyntaxError) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::SyntaxError) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::SyntaxError) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::SyntaxError) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::SyntaxError) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::SyntaxError) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::SyntaxError) }
fn read_char(&mut self) -> Result<char, Error> { Err(Error::SyntaxError) }
fn read_str(&mut self) -> Result<String, Error> { Err(Error::SyntaxError) }
// Compound types:
fn read_enum<T, F>(&mut self, _name: &str, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_enum_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_enum_struct_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_struct_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple<T, F>(&mut self, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
// Specialized types:
fn read_option<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder, bool) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
#[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::SyntaxError)
}
fn read_map_elt_key<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
fn read_map_elt_val<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
}
}
}
//////////////////////////////////////////////////////////////////////////////
mod deserializer {
//use std::num;
use std::vec;
use super::Error;
use serde::de;
#[derive(PartialEq, Debug)]
enum State {
StartState,
SepOrEndState,
EndState,
}
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::StartState,
iter: values.into_iter(),
len: len,
value: None,
}
}
}
impl de::Deserializer for Deserializer<usize> {
type Error = Error;
#[inline]
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.state {
State::StartState => {
self.state = State::SepOrEndState;
visitor.visit_seq(self)
}
State::SepOrEndState => {
visitor.visit_usize(self.value.take().unwrap())
}
State::EndState => {
Err(Error::EndOfStreamError)
}
}
}
}
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::EndState;
Ok(None)
}
}
}
#[inline]
fn end(&mut self) -> Result<(), Error> {
match self.iter.next() {
Some(_) => Err(Error::SyntaxError),
None => {
self.state = State::EndState;
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 visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.state {
State::StartState => {
self.state = State::SepOrEndState;
visitor.visit_seq(self)
}
State::SepOrEndState => {
visitor.visit_u8(self.value.take().unwrap())
}
State::EndState => {
Err(Error::EndOfStreamError)
}
}
}
}
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::EndState;
Ok(None)
}
}
}
#[inline]
fn end(&mut self) -> Result<(), Error> {
match self.iter.next() {
Some(_) => Err(Error::SyntaxError),
None => {
self.state = State::EndState;
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: Deserializer<Error=E>,
E: Debug,
T: Clone + PartialEq + Debug + Deserialize
>(mut d: D, value: T) {
let v: T = Deserialize::deserialize(&mut d).unwrap();
assert_eq!(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)
})
}
-64
View File
@@ -1,64 +0,0 @@
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
use std::collections::BTreeMap;
use serde::json;
// Creating serializable types with serde is quite simple with `serde_macros`. It implements a
// syntax extension that automatically generates the necessary serde trait implementations.
#[derive(Debug, Serialize, Deserialize)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 5, y: 6 };
// Serializing to JSON is pretty simple by using the `to_string` method:
let serialized_point = json::to_string(&point).unwrap();
println!("{}", serialized_point);
// prints:
//
// {"x":5,"y":6}
// There is also support for pretty printing using `to_string_pretty`:
let serialized_point = json::to_string_pretty(&point).unwrap();
println!("{}", serialized_point);
// prints:
//
// {
// "x":5,
// "y":6
// }
// Values can also be deserialized with the same style using `from_str`:
let deserialized_point: Point = json::from_str(&serialized_point).unwrap();
println!("{:?}", deserialized_point);
// prints:
//
// Point { x: 5, y: 6 }
// `Point`s aren't the only type that can be serialized to. Because `Point` members have the
// same type, they can be also serialized into a map. Also,
let deserialized_map: BTreeMap<String, i64> = json::from_str(&serialized_point).unwrap();
println!("{:?}", deserialized_map);
// prints:
//
// {"x": 5, "y": 6}
// If you need to accept arbitrary data, you can also deserialize into `json::Value`, which
// can represent all JSON values.
let deserialized_value: json::Value = json::from_str(&serialized_point).unwrap();
println!("{:?}", deserialized_value);
// prints:
//
// {"x":5,"y":6}
}
+5
View File
@@ -0,0 +1,5 @@
fn_args_layout = "Block"
array_layout = "Block"
where_style = "Rfc"
generics_indent = "Block"
fn_call_style = "Block"
+75
View File
@@ -0,0 +1,75 @@
[package]
name = "serde"
version = "1.0.7" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde/"
keywords = ["serde", "serialization", "no_std"]
categories = ["encoding"]
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[badges]
travis-ci = { repository = "serde-rs/serde" }
appveyor = { repository = "serde-rs/serde" }
[dependencies]
serde_derive = { version = "1.0", optional = true, path = "../serde_derive" }
[dev-dependencies]
serde_derive = { version = "1.0", path = "../serde_derive" }
### FEATURES #################################################################
[features]
default = ["std"]
# Re-export the derive(Serialize, Deserialize) macros. This is specifically
# intended for library crates that provide optional Serde impls behind a Cargo
# cfg of their own. All other crates should depend on serde_derive directly.
#
# Please refer to the long comment above the line `pub use serde_derive::*` in
# src/lib.rs before enabling this feature. If you think you need this feature
# and your use case does not precisely match the one described in the comment,
# please open an issue to let us know about your use case.
derive = ["serde_derive"]
# Provide impls for common standard library types like Vec<T> and HashMap<K, V>.
# Requires a dependency on the Rust standard library.
std = []
# Provide impls for types that require unstable functionality. For tracking and
# discussion of unstable functionality please refer to this issue:
#
# https://github.com/serde-rs/serde/issues/812
unstable = []
# Provide impls for types that require memory allocation like Box<T> and Rc<T>.
# This is a subset of std but may be enabled without depending on all of std.
#
# Requires a dependency on the unstable core allocation library:
#
# https://doc.rust-lang.org/alloc/
alloc = ["unstable"]
# Provide impls for collection types like String and Cow<T>. This is a subset of
# std but may be enabled without depending on all of std.
#
# Requires a dependency on the unstable collections library:
#
# https://doc.rust-lang.org/collections/
collections = ["alloc"]
# Opt into impls for Rc<T> and Arc<T>. Serializing and deserializing these types
# does not preserve identity and may result in multiple copies of the same data.
# Be sure that this is what you want before enabling this feature.
rc = []
# Get serde_derive picked up by the Integer 32 playground. Not public API.
#
# http://play.integer32.com/
playground = ["serde_derive"]
+1
View File
@@ -0,0 +1 @@
../LICENSE-APACHE
+1
View File
@@ -0,0 +1 @@
../LICENSE-MIT
+1
View File
@@ -0,0 +1 @@
../README.md
+116
View File
@@ -0,0 +1,116 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use lib::*;
macro_rules! int_to_int {
($dst:ident, $n:ident) => (
if $dst::MIN as i64 <= $n as i64 && $n as i64 <= $dst::MAX as i64 {
Some($n as $dst)
} else {
None
}
)
}
macro_rules! int_to_uint {
($dst:ident, $n:ident) => (
if 0 <= $n && $n as u64 <= $dst::MAX as u64 {
Some($n as $dst)
} else {
None
}
)
}
macro_rules! uint_to {
($dst:ident, $n:ident) => (
if $n as u64 <= $dst::MAX as u64 {
Some($n as $dst)
} else {
None
}
)
}
pub trait FromPrimitive: Sized {
fn from_isize(n: isize) -> Option<Self>;
fn from_i8(n: i8) -> Option<Self>;
fn from_i16(n: i16) -> Option<Self>;
fn from_i32(n: i32) -> Option<Self>;
fn from_i64(n: i64) -> Option<Self>;
fn from_usize(n: usize) -> Option<Self>;
fn from_u8(n: u8) -> Option<Self>;
fn from_u16(n: u16) -> Option<Self>;
fn from_u32(n: u32) -> Option<Self>;
fn from_u64(n: u64) -> Option<Self>;
}
macro_rules! impl_from_primitive_for_int {
($t:ident) => (
impl FromPrimitive for $t {
#[inline] fn from_isize(n: isize) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_i8(n: i8) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_i16(n: i16) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_i32(n: i32) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_i64(n: i64) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_usize(n: usize) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u16(n: u16) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u32(n: u32) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u64(n: u64) -> Option<Self> { uint_to!($t, n) }
}
)
}
macro_rules! impl_from_primitive_for_uint {
($t:ident) => (
impl FromPrimitive for $t {
#[inline] fn from_isize(n: isize) -> Option<Self> { int_to_uint!($t, n) }
#[inline] fn from_i8(n: i8) -> Option<Self> { int_to_uint!($t, n) }
#[inline] fn from_i16(n: i16) -> Option<Self> { int_to_uint!($t, n) }
#[inline] fn from_i32(n: i32) -> Option<Self> { int_to_uint!($t, n) }
#[inline] fn from_i64(n: i64) -> Option<Self> { int_to_uint!($t, n) }
#[inline] fn from_usize(n: usize) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u16(n: u16) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u32(n: u32) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u64(n: u64) -> Option<Self> { uint_to!($t, n) }
}
)
}
macro_rules! impl_from_primitive_for_float {
($t:ident) => (
impl FromPrimitive for $t {
#[inline] fn from_isize(n: isize) -> Option<Self> { Some(n as Self) }
#[inline] fn from_i8(n: i8) -> Option<Self> { Some(n as Self) }
#[inline] fn from_i16(n: i16) -> Option<Self> { Some(n as Self) }
#[inline] fn from_i32(n: i32) -> Option<Self> { Some(n as Self) }
#[inline] fn from_i64(n: i64) -> Option<Self> { Some(n as Self) }
#[inline] fn from_usize(n: usize) -> Option<Self> { Some(n as Self) }
#[inline] fn from_u8(n: u8) -> Option<Self> { Some(n as Self) }
#[inline] fn from_u16(n: u16) -> Option<Self> { Some(n as Self) }
#[inline] fn from_u32(n: u32) -> Option<Self> { Some(n as Self) }
#[inline] fn from_u64(n: u64) -> Option<Self> { Some(n as Self) }
}
)
}
impl_from_primitive_for_int!(isize);
impl_from_primitive_for_int!(i8);
impl_from_primitive_for_int!(i16);
impl_from_primitive_for_int!(i32);
impl_from_primitive_for_int!(i64);
impl_from_primitive_for_uint!(usize);
impl_from_primitive_for_uint!(u8);
impl_from_primitive_for_uint!(u16);
impl_from_primitive_for_uint!(u32);
impl_from_primitive_for_uint!(u64);
impl_from_primitive_for_float!(f32);
impl_from_primitive_for_float!(f64);
+215
View File
@@ -0,0 +1,215 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use lib::*;
use de::{Deserialize, Deserializer, Visitor, SeqAccess, MapAccess, Error};
/// An efficient way of discarding data from a deserializer.
///
/// Think of this like `serde_json::Value` in that it can be deserialized from
/// any type, except that it does not store any information about the data that
/// gets deserialized.
///
/// ```rust
/// use std::fmt;
/// use std::marker::PhantomData;
///
/// use serde::de::{self, Deserialize, DeserializeSeed, Deserializer, Visitor, SeqAccess, IgnoredAny};
///
/// /// A seed that can be used to deserialize only the `n`th element of a sequence
/// /// while efficiently discarding elements of any type before or after index `n`.
/// ///
/// /// For example to deserialize only the element at index 3:
/// ///
/// /// ```rust
/// /// NthElement::new(3).deserialize(deserializer)
/// /// ```
/// pub struct NthElement<T> {
/// n: usize,
/// marker: PhantomData<T>,
/// }
///
/// impl<T> NthElement<T> {
/// pub fn new(n: usize) -> Self {
/// NthElement {
/// n: n,
/// marker: PhantomData,
/// }
/// }
/// }
///
/// impl<'de, T> Visitor<'de> for NthElement<T>
/// where T: Deserialize<'de>
/// {
/// type Value = T;
///
/// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
/// write!(formatter, "a sequence in which we care about element {}", self.n)
/// }
///
/// fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
/// where A: SeqAccess<'de>
/// {
/// // Skip over the first `n` elements.
/// for i in 0..self.n {
/// // It is an error if the sequence ends before we get to element `n`.
/// if seq.next_element::<IgnoredAny>()?.is_none() {
/// return Err(de::Error::invalid_length(i, &self));
/// }
/// }
///
/// // Deserialize the one we care about.
/// let nth = match seq.next_element()? {
/// Some(nth) => nth,
/// None => {
/// return Err(de::Error::invalid_length(self.n, &self));
/// }
/// };
///
/// // Skip over any remaining elements in the sequence after `n`.
/// while let Some(IgnoredAny) = seq.next_element()? {
/// // ignore
/// }
///
/// Ok(nth)
/// }
/// }
///
/// impl<'de, T> DeserializeSeed<'de> for NthElement<T>
/// where T: Deserialize<'de>
/// {
/// type Value = T;
///
/// fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
/// where D: Deserializer<'de>
/// {
/// deserializer.deserialize_seq(self)
/// }
/// }
///
/// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error>
/// # where D: Deserializer<'de>
/// # {
/// // Deserialize only the sequence element at index 3 from this deserializer.
/// // The element at index 3 is required to be a string. Elements before and
/// // after index 3 are allowed to be of any type.
/// let s: String = NthElement::new(3).deserialize(deserializer)?;
/// # Ok(())
/// # }
/// ```
#[derive(Copy, Clone, Debug, Default)]
pub struct IgnoredAny;
impl<'de> Visitor<'de> for IgnoredAny {
type Value = IgnoredAny;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("anything at all")
}
#[inline]
fn visit_bool<E>(self, x: bool) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
fn visit_i64<E>(self, x: i64) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
fn visit_u64<E>(self, x: u64) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
fn visit_f64<E>(self, x: f64) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
let _ = s;
Ok(IgnoredAny)
}
#[inline]
fn visit_none<E>(self) -> Result<Self::Value, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
IgnoredAny::deserialize(deserializer)
}
#[inline]
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
IgnoredAny::deserialize(deserializer)
}
#[inline]
fn visit_unit<E>(self) -> Result<Self::Value, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
while let Some(IgnoredAny) = try!(seq.next_element()) {
// Gobble
}
Ok(IgnoredAny)
}
#[inline]
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
while let Some((IgnoredAny, IgnoredAny)) = try!(map.next_entry()) {
// Gobble
}
Ok(IgnoredAny)
}
#[inline]
fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
let _ = bytes;
Ok(IgnoredAny)
}
}
impl<'de> Deserialize<'de> for IgnoredAny {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<IgnoredAny, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_ignored_any(IgnoredAny)
}
}
File diff suppressed because it is too large Load Diff
+1944
View File
File diff suppressed because it is too large Load Diff
+54
View File
@@ -0,0 +1,54 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use lib::*;
const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
const TAG_THREE_B: u8 = 0b1110_0000;
const TAG_FOUR_B: u8 = 0b1111_0000;
const MAX_ONE_B: u32 = 0x80;
const MAX_TWO_B: u32 = 0x800;
const MAX_THREE_B: u32 = 0x10000;
#[inline]
pub fn encode(c: char) -> Encode {
let code = c as u32;
let mut buf = [0; 4];
let pos = if code < MAX_ONE_B {
buf[3] = code as u8;
3
} else if code < MAX_TWO_B {
buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
2
} else if code < MAX_THREE_B {
buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
1
} else {
buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
0
};
Encode { buf: buf, pos: pos }
}
pub struct Encode {
buf: [u8; 4],
pos: usize,
}
impl Encode {
pub fn as_str(&self) -> &str {
str::from_utf8(&self.buf[self.pos..]).unwrap()
}
}
File diff suppressed because it is too large Load Diff
+41
View File
@@ -0,0 +1,41 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub use lib::clone::Clone;
pub use lib::convert::{From, Into};
pub use lib::default::Default;
pub use lib::fmt::{self, Formatter};
pub use lib::marker::PhantomData;
pub use lib::option::Option::{self, None, Some};
pub use lib::result::Result::{self, Ok, Err};
pub use self::string::from_utf8_lossy;
mod string {
use lib::*;
#[cfg(any(feature = "std", feature = "collections"))]
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 = "std", feature = "collections")))]
pub fn from_utf8_lossy(bytes: &[u8]) -> &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}")
}
}
+264
View File
@@ -0,0 +1,264 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! # 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.
//!
//! [https://serde.rs/]: https://serde.rs/
//!
//! ## 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 derive
//! attribute to automatically generate 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 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], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//! used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//! size without the need for version negotiation.
//! - [YAML], a popular human-friendly configuration language that ain't markup
//! language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [Hjson], a variant of JSON designed to be readable and writable by humans.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [URL], the x-www-form-urlencoded format.
//! - [XML], the flexible machine-friendly W3C standard.
//! *(deserialization only)*
//! - [Envy], a way to deserialize environment variables into Rust structs.
//! *(deserialization only)*
//! - [Redis], deserialize values from Redis when using [redis-rs].
//! *(deserialization only)*
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/TyOverby/bincode
//! [CBOR]: https://github.com/pyfisch/cbor
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [Hjson]: https://github.com/laktak/hjson-rust
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [URL]: https://github.com/nox/serde_urlencoded
//! [XML]: https://github.com/RReverser/serde-xml-rs
//! [Envy]: https://github.com/softprops/envy
//! [Redis]: https://github.com/OneSignal/serde-redis
//! [Cargo]: http://doc.crates.io/manifest.html
//! [redis-rs]: https://crates.io/crates/redis
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.7")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
// https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(nonzero, specialization))]
#![cfg_attr(all(feature = "std", feature = "unstable"), feature(into_boxed_c_str))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "collections", feature(collections))]
// Whitelisted clippy lints.
#![cfg_attr(feature = "cargo-clippy", allow(doc_markdown))]
#![cfg_attr(feature = "cargo-clippy", allow(linkedlist))]
#![cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
#![cfg_attr(feature = "cargo-clippy", allow(zero_prefixed_literal))]
// Blacklisted Rust lints.
#![deny(missing_docs, unused_imports)]
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "collections")]
extern crate collections;
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(all(feature = "unstable", feature = "std"))]
extern crate core;
/// A facade around all the types we need from the `std`, `core`, `alloc`, and
/// `collections` crates. This avoids elaborate import wrangling having to
/// happen in every module.
mod lib {
mod core {
#[cfg(feature = "std")]
pub use std::*;
#[cfg(not(feature = "std"))]
pub use core::*;
}
pub use self::core::{cmp, iter, mem, ops, slice, str};
pub use self::core::{i8, i16, i32, i64, isize};
pub use self::core::{u8, u16, u32, u64, usize};
pub use self::core::{f32, f64};
pub use self::core::cell::{Cell, RefCell};
pub use self::core::clone::{self, Clone};
pub use self::core::convert::{self, From, Into};
pub use self::core::default::{self, Default};
pub use self::core::fmt::{self, Debug, Display};
pub use self::core::marker::{self, PhantomData};
pub use self::core::option::{self, Option};
pub use self::core::result::{self, Result};
#[cfg(feature = "std")]
pub use std::borrow::{Cow, ToOwned};
#[cfg(all(feature = "collections", not(feature = "std")))]
pub use collections::borrow::{Cow, ToOwned};
#[cfg(feature = "std")]
pub use std::string::String;
#[cfg(all(feature = "collections", not(feature = "std")))]
pub use collections::string::{String, ToString};
#[cfg(feature = "std")]
pub use std::vec::Vec;
#[cfg(all(feature = "collections", not(feature = "std")))]
pub use collections::vec::Vec;
#[cfg(feature = "std")]
pub use std::boxed::Box;
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::boxed::Box;
#[cfg(all(feature = "rc", feature = "std"))]
pub use std::rc::Rc;
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::rc::Rc;
#[cfg(all(feature = "rc", feature = "std"))]
pub use std::sync::Arc;
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::arc::Arc;
#[cfg(feature = "std")]
pub use std::collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
#[cfg(all(feature = "collections", not(feature = "std")))]
pub use collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
#[cfg(feature = "std")]
pub use std::{error, net};
#[cfg(feature = "std")]
pub use std::collections::{HashMap, HashSet};
#[cfg(feature = "std")]
pub use std::ffi::{CString, CStr, OsString, OsStr};
#[cfg(feature = "std")]
pub use std::hash::{Hash, BuildHasher};
#[cfg(feature = "std")]
pub use std::io::Write;
#[cfg(feature = "std")]
pub use std::path::{Path, PathBuf};
#[cfg(feature = "std")]
pub use std::time::Duration;
#[cfg(feature = "std")]
pub use std::sync::{Mutex, RwLock};
#[cfg(feature = "unstable")]
pub use core::nonzero::{NonZero, Zeroable};
}
////////////////////////////////////////////////////////////////////////////////
#[macro_use]
mod macros;
pub mod ser;
pub mod de;
#[doc(inline)]
pub use ser::{Serialize, Serializer};
#[doc(inline)]
pub use de::{Deserialize, Deserializer};
// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;
// Helpers used by generated code and doc tests. Not public API.
#[doc(hidden)]
pub mod private;
// Re-export #[derive(Serialize, Deserialize)].
//
// This is a workaround for https://github.com/rust-lang/cargo/issues/1286.
// Without this re-export, crates that put Serde derives behind a cfg_attr would
// need to use some silly feature name that depends on both serde and
// serde_derive.
//
// [features]
// serde-impls = ["serde", "serde_derive"]
//
// [dependencies]
// serde = { version = "1.0", optional = true }
// serde_derive = { version = "1.0", optional = true }
//
// # Used like this:
// # #[cfg(feature = "serde-impls")]
// # #[macro_use]
// # extern crate serde_derive;
// #
// # #[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
// # struct S { /* ... */ }
//
// The re-exported derives allow crates to use "serde" as the name of their
// Serde feature which is more intuitive.
//
// [dependencies]
// serde = { version = "1.0", optional = true, features = ["derive"] }
//
// # Used like this:
// # #[cfg(feature = "serde")]
// # #[macro_use]
// # extern crate serde;
// #
// # #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
// # struct S { /* ... */ }
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;
+242
View File
@@ -0,0 +1,242 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// 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};
/// #
/// # struct MyDeserializer;
/// #
/// # impl<'de> Deserializer<'de> for MyDeserializer {
/// # type Error = value::Error;
/// #
/// # fn deserialize_any<V>(self, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de>
/// # {
/// # unimplemented!()
/// # }
/// #
/// #[inline]
/// fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor<'de>
/// {
/// self.deserialize_any(visitor)
/// }
/// #
/// # forward_to_deserialize_any! {
/// # i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
/// # byte_buf option unit unit_struct newtype_struct seq tuple
/// # tuple_struct map struct enum identifier ignored_any
/// # }
/// # }
/// #
/// # fn main() {}
/// ```
///
/// The `forward_to_deserialize_any!` macro implements these simple forwarding
/// methods so that they forward directly to [`Deserializer::deserialize_any`].
/// You can choose which methods to forward.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::de::{value, Deserializer, Visitor};
/// #
/// # struct MyDeserializer;
/// #
/// impl<'de> Deserializer<'de> for MyDeserializer {
/// # type Error = value::Error;
/// #
/// fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor<'de>
/// {
/// /* ... */
/// # let _ = visitor;
/// # unimplemented!()
/// }
///
/// forward_to_deserialize_any! {
/// bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
/// byte_buf option unit unit_struct newtype_struct seq tuple
/// tuple_struct map struct enum identifier ignored_any
/// }
/// }
/// #
/// # fn main() {}
/// ```
///
/// The macro assumes the convention that your `Deserializer` lifetime parameter
/// is called `'de` and that the `Visitor` type parameters on each method are
/// called `V`. A different type parameter and a different lifetime can be
/// specified explicitly if necessary.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use std::marker::PhantomData;
/// #
/// # use serde::de::{value, Deserializer, Visitor};
/// #
/// # struct MyDeserializer<V>(PhantomData<V>);
/// #
/// # impl<'q, V> Deserializer<'q> for MyDeserializer<V> {
/// # type Error = value::Error;
/// #
/// # fn deserialize_any<W>(self, visitor: W) -> Result<W::Value, Self::Error>
/// # where W: Visitor<'q>
/// # {
/// # unimplemented!()
/// # }
/// #
/// forward_to_deserialize_any! {
/// <W: Visitor<'q>>
/// bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
/// byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
/// map struct enum identifier ignored_any
/// }
/// # }
/// #
/// # fn main() {}
/// ```
///
/// [`Deserializer`]: trait.Deserializer.html
/// [`Visitor`]: de/trait.Visitor.html
/// [`Deserializer::deserialize_any`]: trait.Deserializer.html#tymethod.deserialize_any
#[macro_export]
macro_rules! forward_to_deserialize_any {
(<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => {
$(forward_to_deserialize_any_helper!{$func<$lifetime, $visitor>})*
};
// This case must be after the previous one.
($($func:ident)*) => {
$(forward_to_deserialize_any_helper!{$func<'de, V>})*
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_any_method {
($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => {
#[inline]
fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::export::Result<$v::Value, Self::Error>
where
$v: $crate::de::Visitor<$l>,
{
$(
let _ = $arg;
)*
self.deserialize_any(visitor)
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_any_helper {
(bool<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_bool<$l, $v>()}
};
(i8<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_i8<$l, $v>()}
};
(i16<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_i16<$l, $v>()}
};
(i32<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_i32<$l, $v>()}
};
(i64<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()}
};
(u8<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()}
};
(u16<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u16<$l, $v>()}
};
(u32<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u32<$l, $v>()}
};
(u64<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()}
};
(f32<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()}
};
(f64<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_f64<$l, $v>()}
};
(char<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_char<$l, $v>()}
};
(str<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_str<$l, $v>()}
};
(string<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_string<$l, $v>()}
};
(bytes<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_bytes<$l, $v>()}
};
(byte_buf<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_byte_buf<$l, $v>()}
};
(option<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_option<$l, $v>()}
};
(unit<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_unit<$l, $v>()}
};
(unit_struct<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_unit_struct<$l, $v>(name: &'static str)}
};
(newtype_struct<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_newtype_struct<$l, $v>(name: &'static str)}
};
(seq<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_seq<$l, $v>()}
};
(tuple<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_tuple<$l, $v>(len: usize)}
};
(tuple_struct<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_tuple_struct<$l, $v>(name: &'static str, len: usize)}
};
(map<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_map<$l, $v>()}
};
(struct<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_struct<$l, $v>(name: &'static str, fields: &'static [&'static str])}
};
(enum<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_enum<$l, $v>(name: &'static str, variants: &'static [&'static str])}
};
(identifier<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_identifier<$l, $v>()}
};
(ignored_any<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_ignored_any<$l, $v>()}
};
}
File diff suppressed because it is too large Load Diff
+148
View File
@@ -0,0 +1,148 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[doc(hidden)]
#[macro_export]
macro_rules! __private_serialize {
() => {
trait Serialize {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: $crate::Serializer;
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __private_deserialize {
() => {
trait Deserialize<'de>: Sized {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: $crate::Deserializer<'de>;
}
};
}
/// Used only by Serde doc tests. Not public API.
#[doc(hidden)]
#[macro_export]
macro_rules! __serialize_unimplemented {
($($func:ident)*) => {
$(
__serialize_unimplemented_helper!($func);
)*
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __serialize_unimplemented_method {
($func:ident $(<$t:ident>)* ($($arg:ty),*) -> $ret:ident) => {
fn $func $(<$t: ?Sized + $crate::Serialize>)* (self $(, _: $arg)*) -> $crate::export::Result<Self::$ret, Self::Error> {
unimplemented!()
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __serialize_unimplemented_helper {
(bool) => {
__serialize_unimplemented_method!(serialize_bool(bool) -> Ok);
};
(i8) => {
__serialize_unimplemented_method!(serialize_i8(i8) -> Ok);
};
(i16) => {
__serialize_unimplemented_method!(serialize_i16(i16) -> Ok);
};
(i32) => {
__serialize_unimplemented_method!(serialize_i32(i32) -> Ok);
};
(i64) => {
__serialize_unimplemented_method!(serialize_i64(i64) -> Ok);
};
(u8) => {
__serialize_unimplemented_method!(serialize_u8(u8) -> Ok);
};
(u16) => {
__serialize_unimplemented_method!(serialize_u16(u16) -> Ok);
};
(u32) => {
__serialize_unimplemented_method!(serialize_u32(u32) -> Ok);
};
(u64) => {
__serialize_unimplemented_method!(serialize_u64(u64) -> Ok);
};
(f32) => {
__serialize_unimplemented_method!(serialize_f32(f32) -> Ok);
};
(f64) => {
__serialize_unimplemented_method!(serialize_f64(f64) -> Ok);
};
(char) => {
__serialize_unimplemented_method!(serialize_char(char) -> Ok);
};
(str) => {
__serialize_unimplemented_method!(serialize_str(&str) -> Ok);
};
(bytes) => {
__serialize_unimplemented_method!(serialize_bytes(&[u8]) -> Ok);
};
(none) => {
__serialize_unimplemented_method!(serialize_none() -> Ok);
};
(some) => {
__serialize_unimplemented_method!(serialize_some<T>(&T) -> Ok);
};
(unit) => {
__serialize_unimplemented_method!(serialize_unit() -> Ok);
};
(unit_struct) => {
__serialize_unimplemented_method!(serialize_unit_struct(&str) -> Ok);
};
(unit_variant) => {
__serialize_unimplemented_method!(serialize_unit_variant(&str, u32, &str) -> Ok);
};
(newtype_struct) => {
__serialize_unimplemented_method!(serialize_newtype_struct<T>(&str, &T) -> Ok);
};
(newtype_variant) => {
__serialize_unimplemented_method!(serialize_newtype_variant<T>(&str, u32, &str, &T) -> Ok);
};
(seq) => {
type SerializeSeq = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_seq(Option<usize>) -> SerializeSeq);
};
(tuple) => {
type SerializeTuple = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_tuple(usize) -> SerializeTuple);
};
(tuple_struct) => {
type SerializeTupleStruct = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_tuple_struct(&str, usize) -> SerializeTupleStruct);
};
(tuple_variant) => {
type SerializeTupleVariant = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_tuple_variant(&str, u32, &str, usize) -> SerializeTupleVariant);
};
(map) => {
type SerializeMap = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_map(Option<usize>) -> SerializeMap);
};
(struct) => {
type SerializeStruct = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_struct(&str, usize) -> SerializeStruct);
};
(struct_variant) => {
type SerializeStructVariant = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_struct_variant(&str, u32, &str, usize) -> SerializeStructVariant);
};
}
+12
View File
@@ -0,0 +1,12 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
mod macros;
pub mod ser;
pub mod de;
File diff suppressed because it is too large Load Diff
+613
View File
@@ -0,0 +1,613 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use lib::*;
use ser::{Serialize, SerializeTuple, Serializer};
#[cfg(feature = "std")]
use ser::Error;
////////////////////////////////////////////////////////////////////////////////
macro_rules! primitive_impl {
($ty:ident, $method:ident $($cast:tt)*) => {
impl Serialize for $ty {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.$method(*self $($cast)*)
}
}
}
}
primitive_impl!(bool, serialize_bool);
primitive_impl!(isize, serialize_i64 as i64);
primitive_impl!(i8, serialize_i8);
primitive_impl!(i16, serialize_i16);
primitive_impl!(i32, serialize_i32);
primitive_impl!(i64, serialize_i64);
primitive_impl!(usize, serialize_u64 as u64);
primitive_impl!(u8, serialize_u8);
primitive_impl!(u16, serialize_u16);
primitive_impl!(u32, serialize_u32);
primitive_impl!(u64, serialize_u64);
primitive_impl!(f32, serialize_f32);
primitive_impl!(f64, serialize_f64);
primitive_impl!(char, serialize_char);
////////////////////////////////////////////////////////////////////////////////
impl Serialize for str {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self)
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl Serialize for String {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self)
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl Serialize for CStr {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_bytes(self.to_bytes())
}
}
#[cfg(feature = "std")]
impl Serialize for CString {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_bytes(self.to_bytes())
}
}
////////////////////////////////////////////////////////////////////////////////
impl<T> Serialize for Option<T>
where
T: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
Some(ref value) => serializer.serialize_some(value),
None => serializer.serialize_none(),
}
}
}
////////////////////////////////////////////////////////////////////////////////
impl<T> Serialize for PhantomData<T> {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_unit_struct("PhantomData")
}
}
////////////////////////////////////////////////////////////////////////////////
// Does not require T: Serialize.
impl<T> Serialize for [T; 0] {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
try!(serializer.serialize_tuple(0)).end()
}
}
macro_rules! array_impls {
($($len:tt)+) => {
$(
impl<T> Serialize for [T; $len]
where
T: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = try!(serializer.serialize_tuple($len));
for e in self {
try!(seq.serialize_element(e));
}
seq.end()
}
}
)+
}
}
array_impls!(01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32);
////////////////////////////////////////////////////////////////////////////////
impl<T> Serialize for [T]
where
T: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_seq(self)
}
}
macro_rules! seq_impl {
($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => {
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
where
T: Serialize $(+ $tbound1 $(+ $tbound2)*)*,
$($typaram: $bound,)*
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_seq(self)
}
}
}
}
#[cfg(any(feature = "std", feature = "collections"))]
seq_impl!(BinaryHeap<T: Ord>);
#[cfg(any(feature = "std", feature = "collections"))]
seq_impl!(BTreeSet<T: Ord>);
#[cfg(feature = "std")]
seq_impl!(HashSet<T: Eq + Hash, H: BuildHasher>);
#[cfg(any(feature = "std", feature = "collections"))]
seq_impl!(LinkedList<T>);
#[cfg(any(feature = "std", feature = "collections"))]
seq_impl!(Vec<T>);
#[cfg(any(feature = "std", feature = "collections"))]
seq_impl!(VecDeque<T>);
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl<Idx> Serialize for ops::Range<Idx>
where
Idx: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("Range", 2));
try!(state.serialize_field("start", &self.start));
try!(state.serialize_field("end", &self.end));
state.end()
}
}
////////////////////////////////////////////////////////////////////////////////
impl Serialize for () {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_unit()
}
}
////////////////////////////////////////////////////////////////////////////////
macro_rules! tuple_impls {
($($len:expr => ($($n:tt $name:ident)+))+) => {
$(
impl<$($name),+> Serialize for ($($name,)+)
where
$($name: Serialize,)+
{
#[inline]
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.$n));
)+
tuple.end()
}
}
)+
}
}
tuple_impls! {
1 => (0 T0)
2 => (0 T0 1 T1)
3 => (0 T0 1 T1 2 T2)
4 => (0 T0 1 T1 2 T2 3 T3)
5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
}
////////////////////////////////////////////////////////////////////////////////
macro_rules! map_impl {
($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => {
impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
where
K: Serialize $(+ $kbound1 $(+ $kbound2)*)*,
V: Serialize,
$($typaram: $bound,)*
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_map(self)
}
}
}
}
#[cfg(any(feature = "std", feature = "collections"))]
map_impl!(BTreeMap<K: Ord, V>);
#[cfg(feature = "std")]
map_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
////////////////////////////////////////////////////////////////////////////////
macro_rules! deref_impl {
($($desc:tt)+) => {
impl $($desc)+ {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
(**self).serialize(serializer)
}
}
};
}
deref_impl!(<'a, T: ?Sized> Serialize for &'a T where T: Serialize);
deref_impl!(<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize);
#[cfg(any(feature = "std", feature = "alloc"))]
deref_impl!(<T: ?Sized> Serialize for Box<T> where T: Serialize);
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
deref_impl!(<T> Serialize for Rc<T> where T: Serialize);
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
deref_impl!(<T> Serialize for Arc<T> where T: Serialize);
#[cfg(any(feature = "std", feature = "collections"))]
deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned);
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")]
impl<T> Serialize for NonZero<T>
where
T: Serialize + Zeroable + Clone,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.clone().get().serialize(serializer)
}
}
impl<T> Serialize for Cell<T>
where
T: Serialize + Copy,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.get().serialize(serializer)
}
}
impl<T> Serialize for RefCell<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.borrow().serialize(serializer)
}
}
#[cfg(feature = "std")]
impl<T> Serialize for Mutex<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self.lock() {
Ok(locked) => locked.serialize(serializer),
Err(_) => Err(S::Error::custom("lock poison error while serializing")),
}
}
}
#[cfg(feature = "std")]
impl<T> Serialize for RwLock<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self.read() {
Ok(locked) => locked.serialize(serializer),
Err(_) => Err(S::Error::custom("lock poison error while serializing")),
}
}
}
////////////////////////////////////////////////////////////////////////////////
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),
Result::Err(ref value) => {
serializer.serialize_newtype_variant("Result", 1, "Err", value)
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl Serialize for Duration {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: 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()
}
}
////////////////////////////////////////////////////////////////////////////////
/// Serialize a value that implements `Display` as a string, when that string is
/// statically known to never have more than a constant `MAX_LEN` bytes.
///
/// Panics if the `Display` impl tries to write more than `MAX_LEN` bytes.
#[cfg(feature = "std")]
macro_rules! serialize_display_bounded_length {
($value:expr, $max:expr, $serializer:expr) => {{
let mut buffer: [u8; $max] = unsafe { mem::uninitialized() };
let remaining_len = {
let mut remaining = &mut buffer[..];
write!(remaining, "{}", $value).unwrap();
remaining.len()
};
let written_len = buffer.len() - remaining_len;
let written = &buffer[..written_len];
// write! only provides fmt::Formatter to Display implementations, which
// has methods write_str and write_char but no method to write arbitrary
// bytes. Therefore `written` must be valid UTF-8.
let written_str = unsafe {
str::from_utf8_unchecked(written)
};
$serializer.serialize_str(written_str)
}}
}
#[cfg(feature = "std")]
impl Serialize for net::IpAddr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
net::IpAddr::V4(ref a) => a.serialize(serializer),
net::IpAddr::V6(ref a) => a.serialize(serializer),
}
}
}
#[cfg(feature = "std")]
impl Serialize for net::Ipv4Addr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
/// "101.102.103.104".len()
const MAX_LEN: usize = 15;
serialize_display_bounded_length!(self, MAX_LEN, serializer)
}
}
#[cfg(feature = "std")]
impl Serialize for net::Ipv6Addr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
/// "1000:1002:1003:1004:1005:1006:1007:1008".len()
const MAX_LEN: usize = 39;
serialize_display_bounded_length!(self, MAX_LEN, serializer)
}
}
#[cfg(feature = "std")]
impl Serialize for net::SocketAddr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
net::SocketAddr::V4(ref addr) => addr.serialize(serializer),
net::SocketAddr::V6(ref addr) => addr.serialize(serializer),
}
}
}
#[cfg(feature = "std")]
impl Serialize for net::SocketAddrV4 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
/// "101.102.103.104:65000".len()
const MAX_LEN: usize = 21;
serialize_display_bounded_length!(self, MAX_LEN, serializer)
}
}
#[cfg(feature = "std")]
impl Serialize for net::SocketAddrV6 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
/// "[1000:1002:1003:1004:1005:1006:1007:1008]:65000".len()
const MAX_LEN: usize = 47;
serialize_display_bounded_length!(self, MAX_LEN, serializer)
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl Serialize for Path {
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::custom("path contains invalid UTF-8 characters")),
}
}
}
#[cfg(feature = "std")]
impl Serialize for PathBuf {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.as_path().serialize(serializer)
}
}
#[cfg(all(feature = "std", any(unix, windows)))]
impl Serialize for OsStr {
#[cfg(unix)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use std::os::unix::ffi::OsStrExt;
serializer.serialize_newtype_variant("OsString", 0, "Unix", self.as_bytes())
}
#[cfg(windows)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use std::os::windows::ffi::OsStrExt;
let val = self.encode_wide().collect::<Vec<_>>();
serializer.serialize_newtype_variant("OsString", 1, "Windows", &val)
}
}
#[cfg(all(feature = "std", any(unix, windows)))]
impl Serialize for OsString {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.as_os_str().serialize(serializer)
}
}
+227
View File
@@ -0,0 +1,227 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! This module contains `Impossible` serializer and its implementations.
use lib::*;
use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
SerializeTupleVariant, SerializeMap, SerializeStruct, SerializeStructVariant};
/// Helper type for implementing a `Serializer` that does not support
/// serializing one of the compound types.
///
/// This type cannot be instantiated, but implements every one of the traits
/// corresponding to the [`Serializer`] compound types: [`SerializeSeq`],
/// [`SerializeTuple`], [`SerializeTupleStruct`], [`SerializeTupleVariant`],
/// [`SerializeMap`], [`SerializeStruct`], and [`SerializeStructVariant`].
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::ser::{Serializer, Impossible};
/// # use serde::private::ser::Error;
/// #
/// # struct MySerializer;
/// #
/// impl Serializer for MySerializer {
/// type Ok = ();
/// type Error = Error;
///
/// type SerializeSeq = Impossible<(), Error>;
/// /* other associated types */
///
/// /// This data format does not support serializing sequences.
/// fn serialize_seq(self,
/// len: Option<usize>)
/// -> Result<Self::SerializeSeq, Error> {
/// // Given Impossible cannot be instantiated, the only
/// // thing we can do here is to return an error.
/// # stringify! {
/// Err(...)
/// # };
/// # unimplemented!()
/// }
///
/// /* other Serializer methods */
/// # __serialize_unimplemented! {
/// # bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str bytes none some
/// # unit unit_struct unit_variant newtype_struct newtype_variant
/// # tuple tuple_struct tuple_variant map struct struct_variant
/// # }
/// }
/// #
/// # fn main() {}
/// ```
///
/// [`Serializer`]: trait.Serializer.html
/// [`SerializeSeq`]: trait.SerializeSeq.html
/// [`SerializeTuple`]: trait.SerializeTuple.html
/// [`SerializeTupleStruct`]: trait.SerializeTupleStruct.html
/// [`SerializeTupleVariant`]: trait.SerializeTupleVariant.html
/// [`SerializeMap`]: trait.SerializeMap.html
/// [`SerializeStruct`]: trait.SerializeStruct.html
/// [`SerializeStructVariant`]: trait.SerializeStructVariant.html
pub struct Impossible<Ok, Error> {
void: Void,
ok: PhantomData<Ok>,
error: PhantomData<Error>,
}
enum Void {}
impl<Ok, Error> SerializeSeq for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
impl<Ok, Error> SerializeTuple for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
impl<Ok, Error> SerializeTupleStruct for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
impl<Ok, Error> SerializeTupleVariant for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
impl<Ok, Error> SerializeMap for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = Error;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = key;
match self.void {}
}
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
impl<Ok, Error> SerializeStruct for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = key;
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
impl<Ok, Error> SerializeStructVariant for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = key;
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
+1815
View File
File diff suppressed because it is too large Load Diff
+24
View File
@@ -0,0 +1,24 @@
[package]
name = "serde_derive"
version = "1.0.7" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@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", "no_std"]
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[badges]
travis-ci = { repository = "serde-rs/serde" }
[lib]
name = "serde_derive"
proc-macro = true
[dependencies]
quote = "0.3.8"
serde_derive_internals = { version = "=0.15.0", default-features = false, path = "../serde_derive_internals" }
syn = { version = "0.11", features = ["visit"] }
+1
View File
@@ -0,0 +1 @@
../LICENSE-APACHE
+1
View File
@@ -0,0 +1 @@
../LICENSE-MIT
+1
View File
@@ -0,0 +1 @@
../README.md
+256
View File
@@ -0,0 +1,256 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::collections::HashSet;
use syn::{self, visit};
use internals::ast::Container;
use internals::attr;
macro_rules! path {
($($path:tt)+) => {
syn::parse_path(stringify!($($path)+)).unwrap()
};
}
// Remove the default from every type parameter because in the generated impls
// they look like associated types: "error: associated type bindings are not
// allowed here".
pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
syn::Generics {
ty_params: generics
.ty_params
.iter()
.map(
|ty_param| {
syn::TyParam {
default: None,
..ty_param.clone()
}
},
)
.collect(),
..generics.clone()
}
}
pub fn with_where_predicates(
generics: &syn::Generics,
predicates: &[syn::WherePredicate],
) -> syn::Generics {
let mut generics = generics.clone();
generics
.where_clause
.predicates
.extend_from_slice(predicates);
generics
}
pub fn with_where_predicates_from_fields<F>(
cont: &Container,
generics: &syn::Generics,
from_field: F,
) -> syn::Generics
where
F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
{
let predicates = cont.body
.all_fields()
.flat_map(|field| from_field(&field.attrs))
.flat_map(|predicates| predicates.to_vec());
let mut generics = generics.clone();
generics.where_clause.predicates.extend(predicates);
generics
}
// Puts the given bound on any generic type parameters that are used in fields
// for which filter returns true.
//
// For example, the following struct needs the bound `A: Serialize, B: Serialize`.
//
// struct S<'b, A, B: 'b, C> {
// a: A,
// b: Option<&'b B>
// #[serde(skip_serializing)]
// c: C,
// }
pub fn with_bound<F>(
cont: &Container,
generics: &syn::Generics,
filter: F,
bound: &syn::Path,
) -> syn::Generics
where
F: Fn(&attr::Field) -> bool,
{
struct FindTyParams {
// Set of all generic type parameters on the current struct (A, B, C in
// the example). Initialized up front.
all_ty_params: HashSet<syn::Ident>,
// Set of generic type parameters used in fields for which filter
// returns true (A and B in the example). Filled in as the visitor sees
// them.
relevant_ty_params: HashSet<syn::Ident>,
}
impl visit::Visitor for FindTyParams {
fn visit_path(&mut self, path: &syn::Path) {
if let Some(seg) = path.segments.last() {
if seg.ident == "PhantomData" {
// Hardcoded exception, because PhantomData<T> implements
// Serialize and Deserialize whether or not T implements it.
return;
}
}
if !path.global && path.segments.len() == 1 {
let id = path.segments[0].ident.clone();
if self.all_ty_params.contains(&id) {
self.relevant_ty_params.insert(id);
}
}
visit::walk_path(self, path);
}
}
let all_ty_params: HashSet<_> = generics
.ty_params
.iter()
.map(|ty_param| ty_param.ident.clone())
.collect();
let relevant_tys = cont.body
.all_fields()
.filter(|&field| filter(&field.attrs))
.map(|field| &field.ty);
let mut visitor = FindTyParams {
all_ty_params: all_ty_params,
relevant_ty_params: HashSet::new(),
};
for ty in relevant_tys {
visit::walk_ty(&mut visitor, ty);
}
let new_predicates = generics
.ty_params
.iter()
.map(|ty_param| ty_param.ident.clone())
.filter(|id| visitor.relevant_ty_params.contains(id))
.map(
|id| {
syn::WherePredicate::BoundPredicate(
syn::WhereBoundPredicate {
bound_lifetimes: Vec::new(),
// the type parameter that is being bounded e.g. T
bounded_ty: syn::Ty::Path(None, id.into()),
// the bound e.g. Serialize
bounds: vec![
syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None,
),
],
},
)
},
);
let mut generics = generics.clone();
generics.where_clause.predicates.extend(new_predicates);
generics
}
pub fn with_self_bound(
cont: &Container,
generics: &syn::Generics,
bound: &syn::Path,
) -> syn::Generics {
let mut generics = generics.clone();
generics
.where_clause
.predicates
.push(
syn::WherePredicate::BoundPredicate(
syn::WhereBoundPredicate {
bound_lifetimes: Vec::new(),
// the type that is being bounded e.g. MyStruct<'a, T>
bounded_ty: type_of_item(cont),
// the bound e.g. Default
bounds: vec![
syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None,
),
],
},
),
);
generics
}
pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics {
let mut generics = generics.clone();
for lifetime_def in &mut generics.lifetimes {
lifetime_def.bounds.push(syn::Lifetime::new(lifetime));
}
for ty_param in &mut generics.ty_params {
ty_param
.bounds
.push(syn::TyParamBound::Region(syn::Lifetime::new(lifetime)));
}
generics
.lifetimes
.push(
syn::LifetimeDef {
attrs: Vec::new(),
lifetime: syn::Lifetime::new(lifetime),
bounds: Vec::new(),
},
);
generics
}
fn type_of_item(cont: &Container) -> syn::Ty {
syn::Ty::Path(
None,
syn::Path {
global: false,
segments: vec![
syn::PathSegment {
ident: cont.ident.clone(),
parameters: syn::PathParameters::AngleBracketed(
syn::AngleBracketedParameterData {
lifetimes: cont.generics
.lifetimes
.iter()
.map(|def| def.lifetime.clone())
.collect(),
types: cont.generics
.ty_params
.iter()
.map(|param| syn::Ty::Path(None, param.ident.clone().into()))
.collect(),
bindings: Vec::new(),
},
),
},
],
},
)
}
File diff suppressed because it is too large Load Diff
+75
View File
@@ -0,0 +1,75 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use quote::{Tokens, ToTokens};
pub enum Fragment {
/// Tokens that can be used as an expression.
Expr(Tokens),
/// Tokens that can be used inside a block. The surrounding curly braces are
/// not part of these tokens.
Block(Tokens),
}
macro_rules! quote_expr {
($($tt:tt)*) => {
$crate::fragment::Fragment::Expr(quote!($($tt)*))
}
}
macro_rules! quote_block {
($($tt:tt)*) => {
$crate::fragment::Fragment::Block(quote!($($tt)*))
}
}
/// Interpolate a fragment in place of an expression. This involves surrounding
/// Block fragments in curly braces.
pub struct Expr(pub Fragment);
impl ToTokens for Expr {
fn to_tokens(&self, out: &mut Tokens) {
match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => {
out.append("{");
block.to_tokens(out);
out.append("}");
}
}
}
}
/// Interpolate a fragment as the statements of a block.
pub struct Stmts(pub Fragment);
impl ToTokens for Stmts {
fn to_tokens(&self, out: &mut Tokens) {
match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => block.to_tokens(out),
}
}
}
/// Interpolate a fragment as the value part of a `match` expression. This
/// involves putting a comma after expressions and curly braces around blocks.
pub struct Match(pub Fragment);
impl ToTokens for Match {
fn to_tokens(&self, out: &mut Tokens) {
match self.0 {
Fragment::Expr(ref expr) => {
expr.to_tokens(out);
out.append(",");
}
Fragment::Block(ref block) => {
out.append("{");
block.to_tokens(out);
out.append("}");
}
}
}
}
+60
View File
@@ -0,0 +1,60 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! This crate provides Serde's two derive macros.
//!
//! ```rust,ignore
//! #[derive(Serialize, Deserialize)]
//! ```
//!
//! Please refer to [https://serde.rs/derive.html] for how to set this up.
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.7")]
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "192"]
extern crate syn;
#[macro_use]
extern crate quote;
extern crate serde_derive_internals as internals;
extern crate proc_macro;
use proc_macro::TokenStream;
#[macro_use]
mod bound;
#[macro_use]
mod fragment;
mod ser;
mod de;
#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
let input = syn::parse_derive_input(&input.to_string()).unwrap();
match ser::expand_derive_serialize(&input) {
Ok(expanded) => expanded.parse().unwrap(),
Err(msg) => panic!(msg),
}
}
#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
let input = syn::parse_derive_input(&input.to_string()).unwrap();
match de::expand_derive_deserialize(&input) {
Ok(expanded) => expanded.parse().unwrap(),
Err(msg) => panic!(msg),
}
}
+934
View File
@@ -0,0 +1,934 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use syn::{self, Ident};
use quote::Tokens;
use bound;
use fragment::{Fragment, Stmts, Match};
use internals::ast::{Body, Container, Field, Style, Variant};
use internals::{attr, Ctxt};
use std::u32;
pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, String> {
let ctxt = Ctxt::new();
let cont = Container::from_ast(&ctxt, input);
precondition(&ctxt, &cont);
try!(ctxt.check());
let ident = &cont.ident;
let params = Parameters::new(&cont);
let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
let dummy_const = Ident::new(format!("_IMPL_SERIALIZE_FOR_{}", ident));
let body = Stmts(serialize_body(&cont, &params));
let impl_block = if let Some(remote) = cont.attrs.remote() {
quote! {
impl #impl_generics #ident #ty_generics #where_clause {
fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
{
#body
}
}
}
} else {
quote! {
#[automatically_derived]
impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
{
#body
}
}
}
};
let generated = quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
extern crate serde as _serde;
#impl_block
};
};
Ok(generated)
}
fn precondition(cx: &Ctxt, cont: &Container) {
match cont.attrs.identifier() {
attr::Identifier::No => {}
attr::Identifier::Field => {
cx.error("field identifiers cannot be serialized");
}
attr::Identifier::Variant => {
cx.error("variant identifiers cannot be serialized");
}
}
}
struct Parameters {
/// Variable holding the value being serialized. Either `self` for local
/// types or `__self` for remote types.
self_var: Ident,
/// Path to the type the impl is for. Either a single `Ident` for local
/// types or `some::remote::Ident` for remote types. Does not include
/// generic parameters.
this: syn::Path,
/// Generics including any explicit and inferred bounds for the impl.
generics: syn::Generics,
/// Type has a `serde(remote = "...")` attribute.
is_remote: bool,
}
impl Parameters {
fn new(cont: &Container) -> Self {
let is_remote = cont.attrs.remote().is_some();
let self_var = if is_remote {
Ident::new("__self")
} else {
Ident::new("self")
};
let this = match cont.attrs.remote() {
Some(remote) => remote.clone(),
None => cont.ident.clone().into(),
};
let generics = build_generics(cont);
Parameters {
self_var: self_var,
this: this,
generics: generics,
is_remote: is_remote,
}
}
/// Type name to use in error messages and `&'static str` arguments to
/// various Serializer methods.
fn type_name(&self) -> &str {
self.this.segments.last().unwrap().ident.as_ref()
}
}
// All the generics in the input, plus a bound `T: Serialize` for each generic
// field type that will be serialized by us.
fn build_generics(cont: &Container) -> syn::Generics {
let generics = bound::without_defaults(cont.generics);
let generics =
bound::with_where_predicates_from_fields(cont, &generics, attr::Field::ser_bound);
match cont.attrs.ser_bound() {
Some(predicates) => bound::with_where_predicates(&generics, predicates),
None => {
bound::with_bound(
cont,
&generics,
needs_serialize_bound,
&path!(_serde::Serialize),
)
}
}
}
// Fields with a `skip_serializing` or `serialize_with` attribute are not
// serialized by us so we do not generate a bound. Fields with a `bound`
// attribute specify their own bound so we do not generate one. All other fields
// may need a `T: Serialize` bound where T is the type of the field.
fn needs_serialize_bound(attrs: &attr::Field) -> bool {
!attrs.skip_serializing() && attrs.serialize_with().is_none() && attrs.ser_bound().is_none()
}
fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
if let Some(into_type) = cont.attrs.into_type() {
serialize_into(params, into_type)
} else {
match cont.body {
Body::Enum(ref variants) => serialize_enum(params, variants, &cont.attrs),
Body::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) {
panic!("struct has unnamed fields");
}
serialize_struct(params, fields, &cont.attrs)
}
Body::Struct(Style::Tuple, ref fields) => {
if fields.iter().any(|field| field.ident.is_some()) {
panic!("tuple struct has named fields");
}
serialize_tuple_struct(params, fields, &cont.attrs)
}
Body::Struct(Style::Newtype, ref fields) => {
serialize_newtype_struct(params, &fields[0], &cont.attrs)
}
Body::Struct(Style::Unit, _) => serialize_unit_struct(&cont.attrs),
}
}
}
fn serialize_into(params: &Parameters, into_type: &syn::Ty) -> Fragment {
let self_var = &params.self_var;
quote_block! {
_serde::Serialize::serialize(
&_serde::export::Into::<#into_type>::into(_serde::export::Clone::clone(#self_var)),
__serializer)
}
}
fn serialize_unit_struct(cattrs: &attr::Container) -> Fragment {
let type_name = cattrs.name().serialize_name();
quote_expr! {
_serde::Serializer::serialize_unit_struct(__serializer, #type_name)
}
}
fn serialize_newtype_struct(
params: &Parameters,
field: &Field,
cattrs: &attr::Container,
) -> Fragment {
let type_name = cattrs.name().serialize_name();
let mut field_expr = get_field(params, field, 0);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(params, field.ty, path, field_expr);
}
quote_expr! {
_serde::Serializer::serialize_newtype_struct(__serializer, #type_name, #field_expr)
}
}
fn serialize_tuple_struct(
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
) -> Fragment {
let serialize_stmts = serialize_tuple_struct_visitor(
fields,
params,
false,
quote!(_serde::ser::SerializeTupleStruct::serialize_field),
);
let type_name = cattrs.name().serialize_name();
let len = serialize_stmts.len();
let let_mut = mut_if(len > 0);
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len));
#(#serialize_stmts)*
_serde::ser::SerializeTupleStruct::end(__serde_state)
}
}
fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment {
assert!(fields.len() as u64 <= u32::MAX as u64);
let serialize_fields = serialize_struct_visitor(
fields,
params,
false,
quote!(_serde::ser::SerializeStruct::serialize_field),
);
let type_name = cattrs.name().serialize_name();
let mut serialized_fields = fields
.iter()
.filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields
.map(
|field| match field.attrs.skip_serializing_if() {
None => quote!(1),
Some(path) => {
let ident = field.ident.clone().expect("struct has unnamed fields");
let field_expr = get_field(params, field, ident);
quote!(if #path(#field_expr) { 0 } else { 1 })
}
},
)
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(__serializer, #type_name, #len));
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
}
fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
assert!(variants.len() as u64 <= u32::MAX as u64);
let self_var = &params.self_var;
let arms: Vec<_> = variants
.iter()
.enumerate()
.map(
|(variant_index, variant)| {
serialize_variant(params, variant, variant_index as u32, cattrs)
},
)
.collect();
quote_expr! {
match *#self_var {
#(#arms)*
}
}
}
fn serialize_variant(
params: &Parameters,
variant: &Variant,
variant_index: u32,
cattrs: &attr::Container,
) -> Tokens {
let this = &params.this;
let variant_ident = variant.ident.clone();
if variant.attrs.skip_serializing() {
let skipped_msg = format!(
"the enum variant {}::{} cannot be serialized",
params.type_name(),
variant_ident
);
let skipped_err = quote! {
_serde::export::Err(_serde::ser::Error::custom(#skipped_msg))
};
let fields_pat = match variant.style {
Style::Unit => quote!(),
Style::Newtype | Style::Tuple => quote!((..)),
Style::Struct => {
quote!(
{
..
}
)
}
};
quote! {
#this::#variant_ident #fields_pat => #skipped_err,
}
} else {
// variant wasn't skipped
let case = match variant.style {
Style::Unit => {
quote! {
#this::#variant_ident
}
}
Style::Newtype => {
quote! {
#this::#variant_ident(ref __field0)
}
}
Style::Tuple => {
let field_names =
(0..variant.fields.len()).map(|i| Ident::new(format!("__field{}", i)));
quote! {
#this::#variant_ident(#(ref #field_names),*)
}
}
Style::Struct => {
let fields = variant
.fields
.iter()
.map(
|f| {
f.ident
.clone()
.expect("struct variant has unnamed fields")
},
);
quote! {
#this::#variant_ident { #(ref #fields),* }
}
}
};
let body = Match(
match *cattrs.tag() {
attr::EnumTag::External => {
serialize_externally_tagged_variant(params, variant, variant_index, cattrs)
}
attr::EnumTag::Internal { ref tag } => {
serialize_internally_tagged_variant(params, variant, cattrs, tag)
}
attr::EnumTag::Adjacent {
ref tag,
ref content,
} => serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content),
attr::EnumTag::None => serialize_untagged_variant(params, variant, cattrs),
},
);
quote! {
#case => #body
}
}
}
fn serialize_externally_tagged_variant(
params: &Parameters,
variant: &Variant,
variant_index: u32,
cattrs: &attr::Container,
) -> Fragment {
let type_name = cattrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name();
match variant.style {
Style::Unit => {
quote_expr! {
_serde::Serializer::serialize_unit_variant(
__serializer,
#type_name,
#variant_index,
#variant_name,
)
}
}
Style::Newtype => {
let field = &variant.fields[0];
let mut field_expr = quote!(__field0);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(params, field.ty, path, field_expr);
}
quote_expr! {
_serde::Serializer::serialize_newtype_variant(
__serializer,
#type_name,
#variant_index,
#variant_name,
#field_expr,
)
}
}
Style::Tuple => {
serialize_tuple_variant(
TupleVariant::ExternallyTagged {
type_name: type_name,
variant_index: variant_index,
variant_name: variant_name,
},
params,
&variant.fields,
)
}
Style::Struct => {
serialize_struct_variant(
StructVariant::ExternallyTagged {
variant_index: variant_index,
variant_name: variant_name,
},
params,
&variant.fields,
&type_name,
)
}
}
}
fn serialize_internally_tagged_variant(
params: &Parameters,
variant: &Variant,
cattrs: &attr::Container,
tag: &str,
) -> Fragment {
let type_name = cattrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name();
let enum_ident_str = params.type_name();
let variant_ident_str = variant.ident.as_ref();
match variant.style {
Style::Unit => {
quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
__serializer, #type_name, 1));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
_serde::ser::SerializeStruct::end(__struct)
}
}
Style::Newtype => {
let field = &variant.fields[0];
let mut field_expr = quote!(__field0);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(params, field.ty, path, field_expr);
}
quote_expr! {
_serde::private::ser::serialize_tagged_newtype(
__serializer,
#enum_ident_str,
#variant_ident_str,
#tag,
#variant_name,
#field_expr,
)
}
}
Style::Struct => {
serialize_struct_variant(
StructVariant::InternallyTagged {
tag: tag,
variant_name: variant_name,
},
params,
&variant.fields,
&type_name,
)
}
Style::Tuple => unreachable!("checked in serde_derive_internals"),
}
}
fn serialize_adjacently_tagged_variant(
params: &Parameters,
variant: &Variant,
cattrs: &attr::Container,
tag: &str,
content: &str,
) -> Fragment {
let this = &params.this;
let type_name = cattrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name();
let inner = Stmts(
match variant.style {
Style::Unit => {
return quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
__serializer, #type_name, 1));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
_serde::ser::SerializeStruct::end(__struct)
};
}
Style::Newtype => {
let field = &variant.fields[0];
let mut field_expr = quote!(__field0);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(params, field.ty, path, field_expr);
}
quote_expr! {
_serde::Serialize::serialize(#field_expr, __serializer)
}
}
Style::Tuple => {
serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
}
Style::Struct => {
serialize_struct_variant(
StructVariant::Untagged,
params,
&variant.fields,
&variant_name,
)
}
},
);
let fields_ty = variant.fields.iter().map(|f| &f.ty);
let ref fields_ident: Vec<_> = match variant.style {
Style::Unit => unreachable!(),
Style::Newtype => vec![Ident::new("__field0")],
Style::Tuple => {
(0..variant.fields.len())
.map(|i| Ident::new(format!("__field{}", i)))
.collect()
}
Style::Struct => {
variant
.fields
.iter()
.map(
|f| {
f.ident
.clone()
.expect("struct variant has unnamed fields")
},
)
.collect()
}
};
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
let wrapper_generics = bound::with_lifetime_bound(&params.generics, "'__a");
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
quote_block! {
struct __AdjacentlyTagged #wrapper_generics #where_clause {
data: (#(&'__a #fields_ty,)*),
phantom: _serde::export::PhantomData<#this #ty_generics>,
}
impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
{
let (#(#fields_ident,)*) = self.data;
#inner
}
}
let mut __struct = try!(_serde::Serializer::serialize_struct(
__serializer, #type_name, 2));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #content, &__AdjacentlyTagged {
data: (#(#fields_ident,)*),
phantom: _serde::export::PhantomData::<#this #ty_generics>,
}));
_serde::ser::SerializeStruct::end(__struct)
}
}
fn serialize_untagged_variant(
params: &Parameters,
variant: &Variant,
cattrs: &attr::Container,
) -> Fragment {
match variant.style {
Style::Unit => {
quote_expr! {
_serde::Serializer::serialize_unit(__serializer)
}
}
Style::Newtype => {
let field = &variant.fields[0];
let mut field_expr = quote!(__field0);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(params, field.ty, path, field_expr);
}
quote_expr! {
_serde::Serialize::serialize(#field_expr, __serializer)
}
}
Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields),
Style::Struct => {
let type_name = cattrs.name().serialize_name();
serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, &type_name)
}
}
}
enum TupleVariant {
ExternallyTagged {
type_name: String,
variant_index: u32,
variant_name: String,
},
Untagged,
}
fn serialize_tuple_variant(
context: TupleVariant,
params: &Parameters,
fields: &[Field],
) -> Fragment {
let method = match context {
TupleVariant::ExternallyTagged { .. } => {
quote!(_serde::ser::SerializeTupleVariant::serialize_field)
}
TupleVariant::Untagged => quote!(_serde::ser::SerializeTuple::serialize_element),
};
let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, method);
let len = serialize_stmts.len();
let let_mut = mut_if(len > 0);
match context {
TupleVariant::ExternallyTagged {
type_name,
variant_index,
variant_name,
} => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_variant(
__serializer,
#type_name,
#variant_index,
#variant_name,
#len));
#(#serialize_stmts)*
_serde::ser::SerializeTupleVariant::end(__serde_state)
}
}
TupleVariant::Untagged => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple(
__serializer,
#len));
#(#serialize_stmts)*
_serde::ser::SerializeTuple::end(__serde_state)
}
}
}
}
enum StructVariant<'a> {
ExternallyTagged {
variant_index: u32,
variant_name: String,
},
InternallyTagged { tag: &'a str, variant_name: String },
Untagged,
}
fn serialize_struct_variant<'a>(
context: StructVariant<'a>,
params: &Parameters,
fields: &[Field],
name: &str,
) -> Fragment {
let method = match context {
StructVariant::ExternallyTagged { .. } => {
quote!(_serde::ser::SerializeStructVariant::serialize_field)
}
StructVariant::InternallyTagged { .. } |
StructVariant::Untagged => quote!(_serde::ser::SerializeStruct::serialize_field),
};
let serialize_fields = serialize_struct_visitor(fields, params, true, method);
let mut serialized_fields = fields
.iter()
.filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields
.map(
|field| {
let ident = field.ident.clone().expect("struct has unnamed fields");
match field.attrs.skip_serializing_if() {
Some(path) => quote!(if #path(#ident) { 0 } else { 1 }),
None => quote!(1),
}
},
)
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
match context {
StructVariant::ExternallyTagged {
variant_index,
variant_name,
} => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct_variant(
__serializer,
#name,
#variant_index,
#variant_name,
#len,
));
#(#serialize_fields)*
_serde::ser::SerializeStructVariant::end(__serde_state)
}
}
StructVariant::InternallyTagged { tag, variant_name } => {
quote_block! {
let mut __serde_state = try!(_serde::Serializer::serialize_struct(
__serializer,
#name,
#len + 1,
));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __serde_state,
#tag,
#variant_name,
));
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
}
StructVariant::Untagged => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(
__serializer,
#name,
#len,
));
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
}
}
}
fn serialize_tuple_struct_visitor(
fields: &[Field],
params: &Parameters,
is_enum: bool,
func: Tokens,
) -> Vec<Tokens> {
fields
.iter()
.enumerate()
.map(
|(i, field)| {
let mut field_expr = if is_enum {
let id = Ident::new(format!("__field{}", i));
quote!(#id)
} else {
get_field(params, field, i)
};
let skip = field
.attrs
.skip_serializing_if()
.map(|path| quote!(#path(#field_expr)));
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(params, field.ty, path, field_expr);
}
let ser = quote! {
try!(#func(&mut __serde_state, #field_expr));
};
match skip {
None => ser,
Some(skip) => quote!(if !#skip { #ser }),
}
},
)
.collect()
}
fn serialize_struct_visitor(
fields: &[Field],
params: &Parameters,
is_enum: bool,
func: Tokens,
) -> Vec<Tokens> {
fields
.iter()
.filter(|&field| !field.attrs.skip_serializing())
.map(
|field| {
let field_ident = field.ident.clone().expect("struct has unnamed field");
let mut field_expr = if is_enum {
quote!(#field_ident)
} else {
get_field(params, field, field_ident)
};
let key_expr = field.attrs.name().serialize_name();
let skip = field
.attrs
.skip_serializing_if()
.map(|path| quote!(#path(#field_expr)));
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(params, field.ty, path, field_expr)
}
let ser = quote! {
try!(#func(&mut __serde_state, #key_expr, #field_expr));
};
match skip {
None => ser,
Some(skip) => quote!(if !#skip { #ser }),
}
},
)
.collect()
}
fn wrap_serialize_with(
params: &Parameters,
field_ty: &syn::Ty,
serialize_with: &syn::Path,
value: Tokens,
) -> Tokens {
let this = &params.this;
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
let wrapper_generics = bound::with_lifetime_bound(&params.generics, "'__a");
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
quote!({
struct __SerializeWith #wrapper_impl_generics #where_clause {
value: &'__a #field_ty,
phantom: _serde::export::PhantomData<#this #ty_generics>,
}
impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __s: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
{
#serialize_with(self.value, __s)
}
}
&__SerializeWith {
value: #value,
phantom: _serde::export::PhantomData::<#this #ty_generics>,
}
})
}
// Serialization of an empty struct results in code like:
//
// let mut __serde_state = try!(serializer.serialize_struct("S", 0));
// _serde::ser::SerializeStruct::end(__serde_state)
//
// where we want to omit the `mut` to avoid a warning.
fn mut_if(is_mut: bool) -> Option<Tokens> {
if is_mut { Some(quote!(mut)) } else { None }
}
fn get_field<I>(params: &Parameters, field: &Field, ident: I) -> Tokens
where
I: Into<Ident>,
{
let self_var = &params.self_var;
match (params.is_remote, field.attrs.getter()) {
(false, None) => {
let ident = ident.into();
quote!(&#self_var.#ident)
}
(true, None) => {
let ty = field.ty;
let ident = ident.into();
quote!(_serde::private::ser::constrain::<#ty>(&#self_var.#ident))
}
(true, Some(getter)) => {
let ty = field.ty;
quote!(_serde::private::ser::constrain::<#ty>(&#getter(#self_var)))
}
(false, Some(_)) => {
unreachable!("getter is only allowed for remote impls");
}
}
}
+19
View File
@@ -0,0 +1,19 @@
[package]
name = "serde_derive_internals"
version = "0.15.0" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "AST representation used by Serde derive macros. Unstable."
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_derive_internals/"
keywords = ["serde", "serialization"]
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[dependencies]
syn = { version = "0.11.10", default-features = false, features = ["parsing"] }
synom = "0.11"
[badges]
travis-ci = { repository = "serde-rs/serde" }
+1
View File
@@ -0,0 +1 @@
../LICENSE-APACHE
+1
View File
@@ -0,0 +1 @@
../LICENSE-MIT
+1
View File
@@ -0,0 +1 @@
../README.md
+143
View File
@@ -0,0 +1,143 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use syn;
use attr;
use check;
use Ctxt;
pub struct Container<'a> {
pub ident: syn::Ident,
pub attrs: attr::Container,
pub body: Body<'a>,
pub generics: &'a syn::Generics,
}
pub enum Body<'a> {
Enum(Vec<Variant<'a>>),
Struct(Style, Vec<Field<'a>>),
}
pub struct Variant<'a> {
pub ident: syn::Ident,
pub attrs: attr::Variant,
pub style: Style,
pub fields: Vec<Field<'a>>,
}
pub struct Field<'a> {
pub ident: Option<syn::Ident>,
pub attrs: attr::Field,
pub ty: &'a syn::Ty,
}
#[derive(Copy, Clone)]
pub enum Style {
Struct,
Tuple,
Newtype,
Unit,
}
impl<'a> Container<'a> {
pub fn from_ast(cx: &Ctxt, item: &'a syn::DeriveInput) -> Container<'a> {
let attrs = attr::Container::from_ast(cx, item);
let mut body = match item.body {
syn::Body::Enum(ref variants) => Body::Enum(enum_from_ast(cx, variants)),
syn::Body::Struct(ref variant_data) => {
let (style, fields) = struct_from_ast(cx, variant_data);
Body::Struct(style, fields)
}
};
match body {
Body::Enum(ref mut variants) => {
for ref mut variant in variants {
variant.attrs.rename_by_rule(attrs.rename_all());
for ref mut field in &mut variant.fields {
field.attrs.rename_by_rule(variant.attrs.rename_all());
}
}
}
Body::Struct(_, ref mut fields) => {
for field in fields {
field.attrs.rename_by_rule(attrs.rename_all());
}
}
}
let item = Container {
ident: item.ident.clone(),
attrs: attrs,
body: body,
generics: &item.generics,
};
check::check(cx, &item);
item
}
}
impl<'a> Body<'a> {
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
match *self {
Body::Enum(ref variants) => {
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
}
Body::Struct(_, ref fields) => Box::new(fields.iter()),
}
}
pub fn has_getter(&self) -> bool {
self.all_fields().any(|f| f.attrs.getter().is_some())
}
}
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.data);
Variant {
ident: variant.ident.clone(),
attrs: attr::Variant::from_ast(cx, variant),
style: style,
fields: fields,
}
},
)
.collect()
}
fn struct_from_ast<'a>(cx: &Ctxt, data: &'a syn::VariantData) -> (Style, Vec<Field<'a>>) {
match *data {
syn::VariantData::Struct(ref fields) => (Style::Struct, fields_from_ast(cx, fields)),
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
(Style::Newtype, fields_from_ast(cx, fields))
}
syn::VariantData::Tuple(ref fields) => (Style::Tuple, fields_from_ast(cx, fields)),
syn::VariantData::Unit => (Style::Unit, Vec::new()),
}
}
fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field]) -> Vec<Field<'a>> {
fields
.iter()
.enumerate()
.map(
|(i, field)| {
Field {
ident: field.ident.clone(),
attrs: attr::Field::from_ast(cx, i, field),
ty: &field.ty,
}
},
)
.collect()
}
File diff suppressed because it is too large Load Diff
+132
View File
@@ -0,0 +1,132 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::ascii::AsciiExt;
use std::str::FromStr;
use self::RenameRule::*;
#[derive(Debug, PartialEq)]
pub enum RenameRule {
/// Don't apply a default rename rule.
None,
/// Rename direct children to "lowercase" style.
LowerCase,
/// Rename direct children to "PascalCase" style, as typically used for enum variants.
PascalCase,
/// Rename direct children to "camelCase" style.
CamelCase,
/// Rename direct children to "snake_case" style, as commonly used for fields.
SnakeCase,
/// Rename direct children to "SCREAMING_SNAKE_CASE" style, as commonly used for constants.
ScreamingSnakeCase,
/// Rename direct children to "kebab-case" style.
KebabCase,
}
impl RenameRule {
pub fn apply_to_variant(&self, variant: &str) -> String {
match *self {
None | PascalCase => variant.to_owned(),
LowerCase => variant.to_ascii_lowercase(),
CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
SnakeCase => {
let mut snake = String::new();
for (i, ch) in variant.char_indices() {
if i > 0 && ch.is_uppercase() {
snake.push('_');
}
snake.push(ch.to_ascii_lowercase());
}
snake
}
ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(),
KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"),
}
}
pub fn apply_to_field(&self, field: &str) -> String {
match *self {
None | LowerCase | SnakeCase => field.to_owned(),
PascalCase => {
let mut pascal = String::new();
let mut capitalize = true;
for ch in field.chars() {
if ch == '_' {
capitalize = true;
} else if capitalize {
pascal.push(ch.to_ascii_uppercase());
capitalize = false;
} else {
pascal.push(ch);
}
}
pascal
}
CamelCase => {
let pascal = PascalCase.apply_to_field(field);
pascal[..1].to_ascii_lowercase() + &pascal[1..]
}
ScreamingSnakeCase => field.to_ascii_uppercase(),
KebabCase => field.replace('_', "-"),
}
}
}
impl FromStr for RenameRule {
type Err = ();
fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> {
match rename_all_str {
"lowercase" => Ok(LowerCase),
"PascalCase" => Ok(PascalCase),
"camelCase" => Ok(CamelCase),
"snake_case" => Ok(SnakeCase),
"SCREAMING_SNAKE_CASE" => Ok(ScreamingSnakeCase),
"kebab-case" => Ok(KebabCase),
_ => Err(()),
}
}
}
#[test]
fn rename_variants() {
for &(original, lower, camel, snake, screaming, kebab) in
&[
("Outcome", "outcome", "outcome", "outcome", "OUTCOME", "outcome"),
("VeryTasty", "verytasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty"),
("A", "a", "a", "a", "A", "a"),
("Z42", "z42", "z42", "z42", "Z42", "z42"),
] {
assert_eq!(None.apply_to_variant(original), original);
assert_eq!(LowerCase.apply_to_variant(original), lower);
assert_eq!(PascalCase.apply_to_variant(original), original);
assert_eq!(CamelCase.apply_to_variant(original), camel);
assert_eq!(SnakeCase.apply_to_variant(original), snake);
assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming);
assert_eq!(KebabCase.apply_to_variant(original), kebab);
}
}
#[test]
fn rename_fields() {
for &(original, pascal, camel, screaming, kebab) in
&[
("outcome", "Outcome", "outcome", "OUTCOME", "outcome"),
("very_tasty", "VeryTasty", "veryTasty", "VERY_TASTY", "very-tasty"),
("a", "A", "a", "A", "a"),
("z42", "Z42", "z42", "Z42", "z42"),
] {
assert_eq!(None.apply_to_field(original), original);
assert_eq!(PascalCase.apply_to_field(original), pascal);
assert_eq!(CamelCase.apply_to_field(original), camel);
assert_eq!(SnakeCase.apply_to_field(original), original);
assert_eq!(ScreamingSnakeCase.apply_to_field(original), screaming);
assert_eq!(KebabCase.apply_to_field(original), kebab);
}
}
+96
View File
@@ -0,0 +1,96 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ast::{Body, Container, Style};
use attr::Identifier;
use Ctxt;
/// Cross-cutting checks that require looking at more than a single attrs
/// object. Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &Container) {
check_getter(cx, cont);
check_identifier(cx, cont);
}
/// Getters are only allowed inside structs (not enums) with the `remote`
/// attribute.
fn check_getter(cx: &Ctxt, cont: &Container) {
match cont.body {
Body::Enum(_) => {
if cont.body.has_getter() {
cx.error("#[serde(getter = \"...\")] is not allowed in an enum");
}
}
Body::Struct(_, _) => {
if cont.body.has_getter() && cont.attrs.remote().is_none() {
cx.error(
"#[serde(getter = \"...\")] can only be used in structs \
that have #[serde(remote = \"...\")]",
);
}
}
}
}
/// The `other` attribute must be used at most once and it must be the last
/// variant of an enum that has the `field_identifier` attribute.
///
/// Inside a `variant_identifier` all variants must be unit variants. Inside a
/// `field_identifier` all but possibly one variant must be unit variants. The
/// last variant may be a newtype variant which is an implicit "other" case.
fn check_identifier(cx: &Ctxt, cont: &Container) {
let variants = match cont.body {
Body::Enum(ref variants) => variants,
Body::Struct(_, _) => {
return;
}
};
for (i, variant) in variants.iter().enumerate() {
match (variant.style, cont.attrs.identifier(), variant.attrs.other()) {
// The `other` attribute may only be used in a field_identifier.
(_, Identifier::Variant, true) |
(_, Identifier::No, true) => {
cx.error("#[serde(other)] may only be used inside a field_identifier");
}
// Variant with `other` attribute must be the last one.
(Style::Unit, Identifier::Field, true) => {
if i < variants.len() - 1 {
cx.error("#[serde(other)] must be the last variant");
}
}
// Variant with `other` attribute must be a unit variant.
(_, Identifier::Field, true) => {
cx.error("#[serde(other)] must be on a unit variant");
}
// Any sort of variant is allowed if this is not an identifier.
(_, Identifier::No, false) => {}
// Unit variant without `other` attribute is always fine.
(Style::Unit, _, false) => {}
// The last field is allowed to be a newtype catch-all.
(Style::Newtype, Identifier::Field, false) => {
if i < variants.len() - 1 {
cx.error(format!("`{}` must be the last variant", variant.ident));
}
}
(_, Identifier::Field, false) => {
cx.error("field_identifier may only contain unit variants");
}
(_, Identifier::Variant, false) => {
cx.error("variant_identifier may only contain unit variants");
}
}
}
}
+53
View File
@@ -0,0 +1,53 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
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");
}
}
}
+22
View File
@@ -0,0 +1,22 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.15.0")]
extern crate syn;
#[macro_use]
extern crate synom;
pub mod ast;
pub mod attr;
mod ctxt;
pub use ctxt::Ctxt;
mod case;
mod check;
-2
View File
@@ -1,2 +0,0 @@
/target
/Cargo.lock
-16
View File
@@ -1,16 +0,0 @@
[package]
name = "serde_macros"
version = "0.3.3"
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/erickt/rust-serde"
[lib]
name = "serde_macros"
plugin = true
[dependencies]
aster = "*"
quasi = "*"
quasi_macros = "*"
-695
View File
@@ -1,695 +0,0 @@
use syntax::ast::{
Ident,
MetaItem,
Item,
Expr,
StructDef,
EnumDef,
};
use syntax::ast;
use syntax::codemap::Span;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;
use aster;
use field;
pub fn expand_derive_deserialize(
cx: &mut ExtCtxt,
span: Span,
_mitem: &MetaItem,
item: &Item,
push: &mut FnMut(P<ast::Item>)
) {
let builder = aster::AstBuilder::new().span(span);
let generics = match item.node {
ast::ItemStruct(_, ref generics) => generics,
ast::ItemEnum(_, ref generics) => generics,
_ => cx.bug("expected ItemStruct or ItemEnum in #[derive(Deserialize)]")
};
let impl_generics = builder.from_generics(generics.clone())
.add_ty_param_bound(
builder.path().global().ids(&["serde", "de", "Deserialize"]).build()
)
.build();
let ty = builder.ty().path()
.segment(item.ident).with_generics(impl_generics.clone()).build()
.build();
let body = deserialize_body(
cx,
&builder,
item,
&impl_generics,
ty.clone(),
);
let where_clause = &impl_generics.where_clause;
let impl_item = quote_item!(cx,
#[automatically_derived]
impl $impl_generics ::serde::de::Deserialize for $ty $where_clause {
fn deserialize<__D>(deserializer: &mut __D) -> ::std::result::Result<$ty, __D::Error>
where __D: ::serde::de::Deserializer,
{
$body
}
}
).unwrap();
push(impl_item)
}
fn deserialize_body(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
item: &Item,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
) -> P<ast::Expr> {
match item.node {
ast::ItemStruct(ref struct_def, _) => {
deserialize_item_struct(
cx,
builder,
item,
impl_generics,
ty,
struct_def,
)
}
ast::ItemEnum(ref enum_def, _) => {
deserialize_item_enum(
cx,
builder,
item.ident,
impl_generics,
ty,
enum_def,
)
}
_ => cx.bug("expected ItemStruct or ItemEnum in #[derive(Deserialize)]")
}
}
fn deserialize_item_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
item: &Item,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
struct_def: &ast::StructDef,
) -> P<ast::Expr> {
let mut named_fields = vec![];
let mut unnamed_fields = 0;
for field in struct_def.fields.iter() {
match field.node.kind {
ast::NamedField(name, _) => { named_fields.push(name); }
ast::UnnamedField(_) => { unnamed_fields += 1; }
}
}
match (named_fields.is_empty(), unnamed_fields == 0) {
(true, true) => {
deserialize_unit_struct(
cx,
&builder,
item.ident,
)
}
(true, false) => {
deserialize_tuple_struct(
cx,
&builder,
item.ident,
impl_generics,
ty,
unnamed_fields,
)
}
(false, true) => {
deserialize_struct(
cx,
&builder,
item.ident,
impl_generics,
ty,
struct_def,
)
}
(false, false) => {
cx.bug("struct has named and unnamed fields")
}
}
}
// Build `__Visitor<A, B, ...>(PhantomData<A>, PhantomData<B>, ...)`
fn deserialize_visitor(
builder: &aster::AstBuilder,
trait_generics: &ast::Generics,
) -> (P<ast::Item>, P<ast::Ty>, P<ast::Expr>) {
if trait_generics.ty_params.is_empty() {
(
builder.item().tuple_struct("__Visitor").build(),
builder.ty().id("__Visitor"),
builder.expr().id("__Visitor"),
)
} else {
(
builder.item().tuple_struct("__Visitor")
.generics().with(trait_generics.clone()).build()
.with_tys(
trait_generics.ty_params.iter().map(|ty_param| {
builder.ty().phantom_data().id(ty_param.ident)
})
)
.build(),
builder.ty().path()
.segment("__Visitor").with_generics(trait_generics.clone()).build()
.build(),
builder.expr().call().id("__Visitor")
.with_args(
trait_generics.ty_params.iter().map(|_| {
builder.expr().phantom_data()
})
)
.build(),
)
}
}
fn deserialize_unit_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident,
) -> P<ast::Expr> {
let type_name = builder.expr().str(type_ident);
quote_expr!(cx, {
struct __Visitor;
impl ::serde::de::Visitor for __Visitor {
type Value = $type_ident;
#[inline]
fn visit_unit<E>(&mut self) -> ::std::result::Result<$type_ident, E>
where E: ::serde::de::Error,
{
Ok($type_ident)
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> ::std::result::Result<$type_ident, V::Error>
where V: ::serde::de::SeqVisitor,
{
try!(visitor.end());
self.visit_unit()
}
}
deserializer.visit_named_unit($type_name, __Visitor)
})
}
fn deserialize_tuple_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
fields: usize,
) -> P<ast::Expr> {
let where_clause = &impl_generics.where_clause;
let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(
builder,
impl_generics,
);
let visit_seq_expr = deserialize_seq(
cx,
builder,
builder.path().id(type_ident).build(),
fields,
);
let type_name = builder.expr().str(type_ident);
quote_expr!(cx, {
$visitor_item
impl $impl_generics ::serde::de::Visitor for $visitor_ty $where_clause {
type Value = $ty;
fn visit_seq<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
where __V: ::serde::de::SeqVisitor,
{
$visit_seq_expr
}
}
deserializer.visit_named_seq($type_name, $visitor_expr)
})
}
fn deserialize_seq(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
struct_path: ast::Path,
fields: usize,
) -> P<ast::Expr> {
let let_values: Vec<P<ast::Stmt>> = (0 .. fields)
.map(|i| {
let name = builder.id(format!("__field{}", i));
quote_stmt!(cx,
let $name = match try!(visitor.visit()) {
Some(value) => value,
None => {
return Err(::serde::de::Error::end_of_stream_error());
}
};
).unwrap()
})
.collect();
let result = builder.expr().call()
.build_path(struct_path)
.with_args((0 .. fields).map(|i| builder.expr().id(format!("__field{}", i))))
.build();
quote_expr!(cx, {
$let_values
try!(visitor.end());
Ok($result)
})
}
fn deserialize_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
struct_def: &StructDef,
) -> P<ast::Expr> {
let where_clause = &impl_generics.where_clause;
let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(
builder,
impl_generics,
);
let (field_visitor, visit_map_expr) = deserialize_struct_visitor(
cx,
builder,
struct_def,
builder.path().id(type_ident).build(),
);
let type_name = builder.expr().str(type_ident);
quote_expr!(cx, {
$field_visitor
$visitor_item
impl $impl_generics ::serde::de::Visitor for $visitor_ty $where_clause {
type Value = $ty;
#[inline]
fn visit_map<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
where __V: ::serde::de::MapVisitor,
{
$visit_map_expr
}
}
deserializer.visit_named_map($type_name, $visitor_expr)
})
}
fn deserialize_item_enum(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
enum_def: &EnumDef,
) -> P<ast::Expr> {
let where_clause = &impl_generics.where_clause;
let type_name = builder.expr().str(type_ident);
let variant_visitor = deserialize_field_visitor(
cx,
builder,
enum_def.variants.iter()
.map(|variant| builder.expr().str(variant.node.name))
.collect()
);
// Match arms to extract a variant from a string
let variant_arms: Vec<_> = enum_def.variants.iter()
.enumerate()
.map(|(i, variant)| {
let variant_name = builder.pat().enum_()
.id("__Field").id(format!("__field{}", i)).build()
.build();
let expr = deserialize_variant(
cx,
builder,
type_ident,
impl_generics,
ty.clone(),
variant,
);
quote_arm!(cx, $variant_name => { $expr })
})
.collect();
let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(
builder,
impl_generics,
);
quote_expr!(cx, {
$variant_visitor
$visitor_item
impl $impl_generics ::serde::de::EnumVisitor for $visitor_ty $where_clause {
type Value = $ty;
fn visit<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
where __V: ::serde::de::VariantVisitor,
{
match try!(visitor.visit_variant()) {
$variant_arms
}
}
}
deserializer.visit_enum($type_name, $visitor_expr)
})
}
fn deserialize_variant(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident,
generics: &ast::Generics,
ty: P<ast::Ty>,
variant: &ast::Variant,
) -> P<ast::Expr> {
let variant_ident = variant.node.name;
match variant.node.kind {
ast::TupleVariantKind(ref args) if args.is_empty() => {
quote_expr!(cx, {
try!(visitor.visit_unit());
Ok($type_ident::$variant_ident)
})
}
ast::TupleVariantKind(ref args) => {
deserialize_tuple_variant(
cx,
builder,
type_ident,
variant_ident,
generics,
ty,
args.len(),
)
}
ast::StructVariantKind(ref struct_def) => {
deserialize_struct_variant(
cx,
builder,
type_ident,
variant_ident,
generics,
ty,
struct_def,
)
}
}
}
fn deserialize_tuple_variant(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: ast::Ident,
variant_ident: ast::Ident,
generics: &ast::Generics,
ty: P<ast::Ty>,
fields: usize,
) -> P<ast::Expr> {
let where_clause = &generics.where_clause;
let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(
builder,
generics,
);
let visit_seq_expr = deserialize_seq(
cx,
builder,
builder.path().id(type_ident).id(variant_ident).build(),
fields,
);
quote_expr!(cx, {
$visitor_item
impl $generics ::serde::de::Visitor for $visitor_ty $where_clause {
type Value = $ty;
fn visit_seq<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
where __V: ::serde::de::SeqVisitor,
{
$visit_seq_expr
}
}
visitor.visit_seq($visitor_expr)
})
}
fn deserialize_struct_variant(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: ast::Ident,
variant_ident: ast::Ident,
generics: &ast::Generics,
ty: P<ast::Ty>,
struct_def: &ast::StructDef,
) -> P<ast::Expr> {
let where_clause = &generics.where_clause;
let (field_visitor, field_expr) = deserialize_struct_visitor(
cx,
builder,
struct_def,
builder.path().id(type_ident).id(variant_ident).build(),
);
let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(
builder,
generics,
);
quote_expr!(cx, {
$field_visitor
$visitor_item
impl $generics ::serde::de::Visitor for $visitor_ty $where_clause {
type Value = $ty;
fn visit_map<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
where __V: ::serde::de::MapVisitor,
{
$field_expr
}
}
visitor.visit_map($visitor_expr)
})
}
fn deserialize_field_visitor(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
field_exprs: Vec<P<ast::Expr>>,
) -> Vec<P<ast::Item>> {
// Create the field names for the fields.
let field_idents: Vec<ast::Ident> = (0 .. field_exprs.len())
.map(|i| builder.id(format!("__field{}", i)))
.collect();
let field_enum = builder.item()
.attr().allow(&["non_camel_case_types"])
.enum_("__Field")
.with_variants(
field_idents.iter().map(|field_ident| {
builder.variant(field_ident).tuple().build()
})
)
.build();
// Match arms to extract a field from a string
let field_arms: Vec<_> = field_idents.iter()
.zip(field_exprs.into_iter())
.map(|(field_ident, field_expr)| {
quote_arm!(cx, $field_expr => { Ok(__Field::$field_ident) })
})
.collect();
vec![
field_enum,
quote_item!(cx,
impl ::serde::de::Deserialize for __Field {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> ::std::result::Result<__Field, D::Error>
where D: ::serde::de::Deserializer,
{
struct __FieldVisitor;
impl ::serde::de::Visitor for __FieldVisitor {
type Value = __Field;
fn visit_str<E>(&mut self, value: &str) -> ::std::result::Result<__Field, E>
where E: ::serde::de::Error,
{
match value {
$field_arms
_ => Err(::serde::de::Error::unknown_field_error(value)),
}
}
}
deserializer.visit(__FieldVisitor)
}
}
).unwrap(),
]
}
fn deserialize_struct_visitor(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
struct_def: &ast::StructDef,
struct_path: ast::Path,
) -> (Vec<P<ast::Item>>, P<ast::Expr>) {
let field_visitor = deserialize_field_visitor(
cx,
builder,
field::struct_field_strs(cx, builder, struct_def, field::Direction::Deserialize),
);
let visit_map_expr = deserialize_map(
cx,
builder,
struct_path,
struct_def,
);
(field_visitor, visit_map_expr)
}
fn deserialize_map(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
struct_path: ast::Path,
struct_def: &StructDef,
) -> P<ast::Expr> {
// Create the field names for the fields.
let field_names: Vec<ast::Ident> = (0 .. struct_def.fields.len())
.map(|i| builder.id(format!("__field{}", i)))
.collect();
// Declare each field.
let let_values: Vec<P<ast::Stmt>> = field_names.iter()
.map(|field_name| quote_stmt!(cx, let mut $field_name = None;).unwrap())
.collect();
// Match arms to extract a value for a field.
let value_arms: Vec<ast::Arm> = field_names.iter()
.map(|field_name| {
quote_arm!(cx,
__Field::$field_name => {
$field_name = Some(try!(visitor.visit_value()));
}
)
})
.collect();
let extract_values: Vec<P<ast::Stmt>> = field_names.iter()
.zip(struct_def.fields.iter())
.map(|(field_name, field)| {
let rename = field::field_rename(field, &field::Direction::Deserialize);
let name_str = match (rename, field.node.kind) {
(Some(rename), _) => builder.expr().build_lit(P(rename.clone())),
(None, ast::NamedField(name, _)) => builder.expr().str(name),
(None, ast::UnnamedField(_)) => panic!("struct contains unnamed fields"),
};
let missing_expr = if field::default_value(field) {
quote_expr!(cx, ::std::default::Default::default())
} else {
quote_expr!(cx, try!(visitor.missing_field($name_str)))
};
quote_stmt!(cx,
let $field_name = match $field_name {
Some($field_name) => $field_name,
None => $missing_expr,
};
).unwrap()
})
.collect();
let result = builder.expr().struct_path(struct_path)
.with_id_exprs(
struct_def.fields.iter()
.zip(field_names.iter())
.map(|(field, field_name)| {
(
match field.node.kind {
ast::NamedField(name, _) => name.clone(),
ast::UnnamedField(_) => panic!("struct contains unnamed fields"),
},
builder.expr().id(field_name),
)
})
)
.build();
quote_expr!(cx, {
$let_values
while let Some(key) = try!(visitor.visit_key()) {
match key {
$value_arms
}
}
$extract_values
try!(visitor.end());
Ok($result)
})
}
-96
View File
@@ -1,96 +0,0 @@
use syntax::ast;
use syntax::attr;
use syntax::ext::base::ExtCtxt;
use syntax::ptr::P;
use aster;
pub enum Direction {
Serialize,
Deserialize,
}
pub fn field_rename<'a>(
field: &'a ast::StructField,
direction: &Direction,
) -> Option<&'a ast::Lit> {
let dir_attr = match *direction {
Direction::Serialize => "rename_serialize",
Direction::Deserialize => "rename_deserialize",
};
field.node.attrs.iter()
.find(|sa| {
if let ast::MetaList(ref n, _) = sa.node.value.node {
n == &"serde"
} else {
false
}
})
.and_then(|sa| {
if let ast::MetaList(_, ref vals) = sa.node.value.node {
attr::mark_used(&sa);
vals.iter().fold(None, |v, mi| {
if let ast::MetaNameValue(ref n, ref lit) = mi.node {
if n == &"rename" || n == &dir_attr {
Some(lit)
} else {
v
}
} else {
v
}
})
} else {
None
}
})
}
pub fn struct_field_strs(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
struct_def: &ast::StructDef,
direction: Direction,
) -> Vec<P<ast::Expr>> {
struct_def.fields.iter()
.map(|field| {
match field_rename(field, &direction) {
Some(rename) => builder.expr().build_lit(P(rename.clone())),
None => {
match field.node.kind {
ast::NamedField(name, _) => {
builder.expr().str(name)
}
ast::UnnamedField(_) => {
cx.bug("struct has named and unnamed fields")
}
}
}
}
})
.collect()
}
pub fn default_value(field: &ast::StructField) -> bool {
field.node.attrs.iter()
.any(|sa| {
if let ast::MetaItem_::MetaList(ref n, ref vals) = sa.node.value.node {
if n == &"serde" {
attr::mark_used(&sa);
vals.iter()
.map(|mi|
if let ast::MetaItem_::MetaWord(ref n) = mi.node {
n == &"default"
} else {
false
})
.any(|x| x)
} else {
false
}
}
else {
false
}
})
}
-27
View File
@@ -1,27 +0,0 @@
#![feature(custom_derive, plugin, plugin_registrar, rustc_private, unboxed_closures)]
#![plugin(quasi_macros)]
extern crate aster;
extern crate quasi;
extern crate rustc;
extern crate syntax;
use syntax::ext::base::Decorator;
use syntax::parse::token;
use rustc::plugin::Registry;
mod ser;
mod de;
mod field;
#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_syntax_extension(
token::intern("derive_Serialize"),
Decorator(Box::new(ser::expand_derive_serialize)));
reg.register_syntax_extension(
token::intern("derive_Deserialize"),
Decorator(Box::new(de::expand_derive_deserialize)));
}
-585
View File
@@ -1,585 +0,0 @@
use syntax::ast::{
Ident,
MetaItem,
Item,
Expr,
StructDef,
};
use syntax::ast;
use syntax::codemap::Span;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;
use aster;
use field::{Direction, struct_field_strs};
pub fn expand_derive_serialize(
cx: &mut ExtCtxt,
span: Span,
_mitem: &MetaItem,
item: &Item,
push: &mut FnMut(P<ast::Item>)
) {
let builder = aster::AstBuilder::new().span(span);
let generics = match item.node {
ast::ItemStruct(_, ref generics) => generics,
ast::ItemEnum(_, ref generics) => generics,
_ => cx.bug("expected ItemStruct or ItemEnum in #[derive(Serialize)]")
};
let impl_generics = builder.from_generics(generics.clone())
.add_ty_param_bound(
builder.path().global().ids(&["serde", "ser", "Serialize"]).build()
)
.build();
let ty = builder.ty().path()
.segment(item.ident).with_generics(impl_generics.clone()).build()
.build();
let body = serialize_body(
cx,
&builder,
item,
&impl_generics,
ty.clone(),
);
let where_clause = &impl_generics.where_clause;
let impl_item = quote_item!(cx,
#[automatically_derived]
impl $impl_generics ::serde::ser::Serialize for $ty $where_clause {
fn serialize<__S>(&self, serializer: &mut __S) -> ::std::result::Result<(), __S::Error>
where __S: ::serde::ser::Serializer,
{
$body
}
}
).unwrap();
push(impl_item)
}
fn serialize_body(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
item: &Item,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
) -> P<ast::Expr> {
match item.node {
ast::ItemStruct(ref struct_def, _) => {
serialize_item_struct(
cx,
builder,
item,
impl_generics,
ty,
struct_def,
)
}
ast::ItemEnum(ref enum_def, _) => {
serialize_item_enum(
cx,
builder,
item.ident,
impl_generics,
enum_def,
)
}
_ => cx.bug("expected ItemStruct or ItemEnum in #[derive(Serialize)]")
}
}
fn serialize_item_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
item: &Item,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
struct_def: &ast::StructDef,
) -> P<ast::Expr> {
let mut named_fields = vec![];
let mut unnamed_fields = 0;
for field in struct_def.fields.iter() {
match field.node.kind {
ast::NamedField(name, _) => { named_fields.push(name); }
ast::UnnamedField(_) => { unnamed_fields += 1; }
}
}
match (named_fields.is_empty(), unnamed_fields == 0) {
(true, true) => {
serialize_unit_struct(
cx,
&builder,
item.ident,
)
}
(true, false) => {
serialize_tuple_struct(
cx,
&builder,
item.ident,
impl_generics,
ty,
unnamed_fields,
)
}
(false, true) => {
serialize_struct(
cx,
&builder,
item.ident,
impl_generics,
ty,
struct_def,
named_fields,
)
}
(false, false) => {
cx.bug("struct has named and unnamed fields")
}
}
}
fn serialize_unit_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident
) -> P<ast::Expr> {
let type_name = builder.expr().str(type_ident);
quote_expr!(cx, serializer.visit_named_unit($type_name))
}
fn serialize_tuple_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
fields: usize,
) -> P<ast::Expr> {
let value_ty = builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(ty);
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
cx,
builder,
value_ty,
fields,
impl_generics,
);
let type_name = builder.expr().str(type_ident);
quote_expr!(cx, {
$visitor_struct
$visitor_impl
serializer.visit_named_seq($type_name, Visitor {
value: self,
state: 0,
})
})
}
fn serialize_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
struct_def: &StructDef,
fields: Vec<Ident>,
) -> P<ast::Expr> {
let value_ty = builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(ty.clone());
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
cx,
builder,
value_ty,
struct_def,
impl_generics,
fields.iter().map(|field| quote_expr!(cx, &self.value.$field)),
);
let type_name = builder.expr().str(type_ident);
quote_expr!(cx, {
$visitor_struct
$visitor_impl
serializer.visit_named_map($type_name, Visitor {
value: self,
state: 0,
})
})
}
fn serialize_item_enum(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident,
impl_generics: &ast::Generics,
enum_def: &ast::EnumDef,
) -> P<ast::Expr> {
let arms: Vec<ast::Arm> = enum_def.variants.iter()
.map(|variant| {
serialize_variant(
cx,
builder,
type_ident,
impl_generics,
variant,
)
})
.collect();
quote_expr!(cx,
match *self {
$arms
}
)
}
fn serialize_variant(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident,
generics: &ast::Generics,
variant: &ast::Variant,
) -> ast::Arm {
let type_name = builder.expr().str(type_ident);
let variant_ident = variant.node.name;
let variant_name = builder.expr().str(variant_ident);
match variant.node.kind {
ast::TupleVariantKind(ref args) if args.is_empty() => {
let pat = builder.pat().enum_()
.id(type_ident).id(variant_ident).build()
.build();
quote_arm!(cx,
$pat => {
::serde::ser::Serializer::visit_enum_unit(
serializer,
$type_name,
$variant_name,
)
},
)
}
ast::TupleVariantKind(ref args) => {
let fields: Vec<ast::Ident> = (0 .. args.len())
.map(|i| builder.id(format!("__field{}", i)))
.collect();
let pat = builder.pat().enum_()
.id(type_ident).id(variant_ident).build()
.with_pats(fields.iter().map(|field| builder.pat().ref_id(field)))
.build();
let expr = serialize_tuple_variant(
cx,
builder,
type_name,
variant_name,
generics,
args,
fields,
);
quote_arm!(cx, $pat => { $expr })
}
ast::StructVariantKind(ref struct_def) => {
let fields: Vec<_> = (0 .. struct_def.fields.len())
.map(|i| builder.id(format!("__field{}", i)))
.collect();
let pat = builder.pat().struct_()
.id(type_ident).id(variant_ident).build()
.with_pats(
fields.iter()
.zip(struct_def.fields.iter())
.map(|(id, field)| {
let name = match field.node.kind {
ast::NamedField(name, _) => name,
ast::UnnamedField(_) => {
cx.bug("struct variant has unnamed fields")
}
};
(name, builder.pat().ref_id(id))
})
)
.build();
let expr = serialize_struct_variant(
cx,
builder,
type_name,
variant_name,
generics,
struct_def,
fields,
);
quote_arm!(cx, $pat => { $expr })
}
}
}
fn serialize_tuple_variant(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_name: P<ast::Expr>,
variant_name: P<ast::Expr>,
generics: &ast::Generics,
args: &[ast::VariantArg],
fields: Vec<Ident>,
) -> P<ast::Expr> {
let value_ty = builder.ty().tuple()
.with_tys(
args.iter().map(|arg| {
builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(arg.ty.clone())
})
)
.build();
let value_expr = builder.expr().tuple()
.with_exprs(
fields.iter().map(|field| {
builder.expr()
.addr_of()
.id(field)
})
)
.build();
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
cx,
builder,
value_ty,
args.len(),
generics,
);
quote_expr!(cx, {
$visitor_struct
$visitor_impl
serializer.visit_enum_seq($type_name, $variant_name, Visitor {
value: $value_expr,
state: 0,
})
})
}
fn serialize_struct_variant(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_name: P<ast::Expr>,
variant_name: P<ast::Expr>,
generics: &ast::Generics,
struct_def: &ast::StructDef,
fields: Vec<Ident>,
) -> P<ast::Expr> {
let value_ty = builder.ty().tuple()
.with_tys(
struct_def.fields.iter().map(|field| {
builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(field.node.ty.clone())
})
)
.build();
let value_expr = builder.expr().tuple()
.with_exprs(
fields.iter().map(|field| {
builder.expr()
.addr_of()
.id(field)
})
)
.build();
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
cx,
builder,
value_ty,
struct_def,
generics,
(0 .. fields.len()).map(|i| {
builder.expr()
.tup_field(i)
.field("value").self_()
})
);
quote_expr!(cx, {
$visitor_struct
$visitor_impl
serializer.visit_enum_map($type_name, $variant_name, Visitor {
value: $value_expr,
state: 0,
})
})
}
fn serialize_tuple_struct_visitor(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
value_ty: P<ast::Ty>,
fields: usize,
generics: &ast::Generics
) -> (P<ast::Item>, P<ast::Item>) {
let arms: Vec<ast::Arm> = (0 .. fields)
.map(|i| {
let expr = builder.expr()
.tup_field(i)
.field("value").self_();
quote_arm!(cx,
$i => {
self.state += 1;
let v = try!(serializer.visit_seq_elt(&$expr));
Ok(Some(v))
}
)
})
.collect();
let visitor_impl_generics = builder.from_generics(generics.clone())
.add_lifetime_bound("'__a")
.lifetime_name("'__a")
.build();
let where_clause = &visitor_impl_generics.where_clause;
let visitor_generics = builder.from_generics(visitor_impl_generics.clone())
.strip_bounds()
.build();
(
quote_item!(cx,
struct Visitor $visitor_impl_generics $where_clause {
state: usize,
value: $value_ty,
}
).unwrap(),
quote_item!(cx,
impl $visitor_impl_generics ::serde::ser::SeqVisitor
for Visitor $visitor_generics
$where_clause {
#[inline]
fn visit<S>(&mut self, serializer: &mut S) -> ::std::result::Result<Option<()>, S::Error>
where S: ::serde::ser::Serializer,
{
match self.state {
$arms
_ => Ok(None),
}
}
#[inline]
fn len(&self) -> Option<usize> {
Some($fields)
}
}
).unwrap(),
)
}
fn serialize_struct_visitor<I>(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
value_ty: P<ast::Ty>,
struct_def: &StructDef,
generics: &ast::Generics,
value_exprs: I,
) -> (P<ast::Item>, P<ast::Item>)
where I: Iterator<Item=P<ast::Expr>>,
{
let len = struct_def.fields.len();
let key_exprs = struct_field_strs(cx, builder, struct_def, Direction::Serialize);
let arms: Vec<ast::Arm> = key_exprs.iter()
.zip(value_exprs)
.enumerate()
.map(|(i, (key_expr, value_expr))| {
quote_arm!(cx,
$i => {
self.state += 1;
Ok(
Some(
try!(
serializer.visit_map_elt(
$key_expr,
$value_expr,
)
)
)
)
}
)
})
.collect();
let visitor_impl_generics = builder.from_generics(generics.clone())
.add_lifetime_bound("'__a")
.lifetime_name("'__a")
.build();
let where_clause = &visitor_impl_generics.where_clause;
let visitor_generics = builder.from_generics(visitor_impl_generics.clone())
.strip_bounds()
.build();
(
quote_item!(cx,
struct Visitor $visitor_impl_generics $where_clause {
state: usize,
value: $value_ty,
}
).unwrap(),
quote_item!(cx,
impl $visitor_impl_generics
::serde::ser::MapVisitor
for Visitor $visitor_generics
$where_clause {
#[inline]
fn visit<S>(&mut self, serializer: &mut S) -> ::std::result::Result<Option<()>, S::Error>
where S: ::serde::ser::Serializer,
{
match self.state {
$arms
_ => Ok(None),
}
}
#[inline]
fn len(&self) -> Option<usize> {
Some($len)
}
}
).unwrap(),
)
}
+22
View File
@@ -0,0 +1,22 @@
[package]
name = "serde_test"
version = "1.0.7" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_test/"
keywords = ["serde", "serialization"]
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[dependencies]
serde = { version = "1.0", path = "../serde" }
[dev-dependencies]
serde = { version = "1.0", path = "../serde", features = ["rc"] }
serde_derive = { version = "1.0", path = "../serde_derive" }
[badges]
travis-ci = { repository = "serde-rs/serde" }
+1
View File
@@ -0,0 +1 @@
../LICENSE-APACHE
+1
View File
@@ -0,0 +1 @@
../LICENSE-MIT
+1
View File
@@ -0,0 +1 @@
../README.md
+241
View File
@@ -0,0 +1,241 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde::{Serialize, Deserialize};
use de::Deserializer;
use ser::Serializer;
use token::Token;
use std::fmt::Debug;
/// Runs both `assert_ser_tokens` and `assert_de_tokens`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct S {
/// a: u8,
/// b: u8,
/// }
///
/// let s = S { a: 0, b: 0 };
/// assert_tokens(&s, &[
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("a"),
/// Token::U8(0),
/// Token::Str("b"),
/// Token::U8(0),
/// Token::StructEnd,
/// ]);
/// # }
/// ```
pub fn assert_tokens<'de, T>(value: &T, tokens: &'de [Token])
where
T: Serialize + Deserialize<'de> + PartialEq + Debug,
{
assert_ser_tokens(value, tokens);
assert_de_tokens(value, tokens);
}
/// Asserts that `value` serializes to the given `tokens`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_ser_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct S {
/// a: u8,
/// b: u8,
/// }
///
/// let s = S { a: 0, b: 0 };
/// assert_ser_tokens(&s, &[
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("a"),
/// Token::U8(0),
/// Token::Str("b"),
/// Token::U8(0),
/// Token::StructEnd,
/// ]);
/// # }
/// ```
pub fn assert_ser_tokens<T>(value: &T, tokens: &[Token])
where
T: Serialize,
{
let mut ser = Serializer::new(tokens);
match value.serialize(&mut ser) {
Ok(_) => {}
Err(err) => panic!("value failed to serialize: {}", err),
}
if ser.remaining() > 0 {
panic!("{} remaining tokens", ser.remaining());
}
}
/// Asserts that `value` serializes to the given `tokens`, and then yields `error`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde_test;
/// #
/// # fn main() {
/// use std::sync::{Arc, Mutex};
/// use std::thread;
///
/// use serde_test::{assert_ser_tokens_error, Token};
///
/// #[derive(Serialize)]
/// struct Example {
/// lock: Arc<Mutex<u32>>,
/// }
///
/// let example = Example { lock: Arc::new(Mutex::new(0)) };
/// let lock = example.lock.clone();
///
/// let _ = thread::spawn(move || {
/// // This thread will acquire the mutex first, unwrapping the result
/// // of `lock` because the lock has not been poisoned.
/// let _guard = lock.lock().unwrap();
///
/// // This panic while holding the lock (`_guard` is in scope) will
/// // poison the mutex.
/// panic!()
/// }).join();
///
/// let expected = &[
/// Token::Struct { name: "Example", len: 1 },
/// Token::Str("lock"),
/// ];
/// let error = "lock poison error while serializing";
/// assert_ser_tokens_error(&example, expected, error);
/// # }
/// ```
pub fn assert_ser_tokens_error<T>(value: &T, tokens: &[Token], error: &str)
where
T: Serialize,
{
let mut ser = Serializer::new(tokens);
match value.serialize(&mut ser) {
Ok(_) => panic!("value serialized successfully"),
Err(e) => assert_eq!(e, *error),
}
if ser.remaining() > 0 {
panic!("{} remaining tokens", ser.remaining());
}
}
/// Asserts that the given `tokens` deserialize into `value`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_de_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct S {
/// a: u8,
/// b: u8,
/// }
///
/// let s = S { a: 0, b: 0 };
/// assert_de_tokens(&s, &[
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("a"),
/// Token::U8(0),
/// Token::Str("b"),
/// Token::U8(0),
/// Token::StructEnd,
/// ]);
/// # }
/// ```
pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token])
where
T: Deserialize<'de> + PartialEq + Debug,
{
let mut de = Deserializer::new(tokens);
match T::deserialize(&mut de) {
Ok(v) => assert_eq!(v, *value),
Err(e) => panic!("tokens failed to deserialize: {}", e),
}
if de.remaining() > 0 {
panic!("{} remaining tokens", de.remaining());
}
}
/// Asserts that the given `tokens` yield `error` when deserializing.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_de_tokens_error, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// #[serde(deny_unknown_fields)]
/// struct S {
/// a: u8,
/// b: u8,
/// }
///
/// assert_de_tokens_error::<S>(
/// &[
/// Token::Struct { name: "S", len: 1 },
/// Token::Str("x"),
/// ],
/// "unknown field `x`, expected `a` or `b`",
/// );
/// # }
/// ```
pub fn assert_de_tokens_error<'de, T>(tokens: &'de [Token], error: &str)
where
T: Deserialize<'de>,
{
let mut de = Deserializer::new(tokens);
match T::deserialize(&mut de) {
Ok(_) => panic!("tokens deserialized successfully"),
Err(e) => assert_eq!(e, *error),
}
// There may be one token left if a peek caused the error
de.next_token_opt();
if de.remaining() > 0 {
panic!("{} remaining tokens", de.remaining());
}
}
+641
View File
@@ -0,0 +1,641 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde::de::{self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess,
SeqAccess, VariantAccess, Visitor};
use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer};
use error::Error;
use token::Token;
#[derive(Debug)]
pub struct Deserializer<'de> {
tokens: &'de [Token],
}
macro_rules! assert_next_token {
($de:expr, $expected:expr) => {
match $de.next_token_opt() {
Some(token) if token == $expected => {}
Some(other) => {
panic!("expected Token::{} but deserialization wants Token::{}",
other, $expected)
}
None => {
panic!("end of tokens but deserialization wants Token::{}",
$expected)
}
}
}
}
macro_rules! unexpected {
($token:expr) => {
panic!("deserialization did not expect this token: {}", $token)
}
}
macro_rules! end_of_tokens {
() => {
panic!("ran out of tokens to deserialize")
}
}
impl<'de> Deserializer<'de> {
pub fn new(tokens: &'de [Token]) -> Self {
Deserializer { tokens: tokens }
}
fn peek_token_opt(&self) -> Option<Token> {
self.tokens.first().cloned()
}
fn peek_token(&self) -> Token {
match self.peek_token_opt() {
Some(token) => token,
None => end_of_tokens!(),
}
}
pub fn next_token_opt(&mut self) -> Option<Token> {
match self.tokens.split_first() {
Some((&first, rest)) => {
self.tokens = rest;
Some(first)
}
None => None,
}
}
fn next_token(&mut self) -> Token {
match self.tokens.split_first() {
Some((&first, rest)) => {
self.tokens = rest;
first
}
None => end_of_tokens!(),
}
}
pub fn remaining(&self) -> usize {
self.tokens.len()
}
fn visit_seq<V>(
&mut self,
len: Option<usize>,
end: Token,
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
let value = try!(
visitor.visit_seq(
DeserializerSeqVisitor {
de: self,
len: len,
end: end.clone(),
},
)
);
assert_next_token!(self, end);
Ok(value)
}
fn visit_map<V>(
&mut self,
len: Option<usize>,
end: Token,
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
let value = try!(
visitor.visit_map(
DeserializerMapVisitor {
de: self,
len: len,
end: end.clone(),
},
)
);
assert_next_token!(self, end);
Ok(value)
}
}
impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
type Error = Error;
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf unit seq map identifier ignored_any
}
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
let token = self.next_token();
match token {
Token::Bool(v) => visitor.visit_bool(v),
Token::I8(v) => visitor.visit_i8(v),
Token::I16(v) => visitor.visit_i16(v),
Token::I32(v) => visitor.visit_i32(v),
Token::I64(v) => visitor.visit_i64(v),
Token::U8(v) => visitor.visit_u8(v),
Token::U16(v) => visitor.visit_u16(v),
Token::U32(v) => visitor.visit_u32(v),
Token::U64(v) => visitor.visit_u64(v),
Token::F32(v) => visitor.visit_f32(v),
Token::F64(v) => visitor.visit_f64(v),
Token::Char(v) => visitor.visit_char(v),
Token::Str(v) => visitor.visit_str(v),
Token::BorrowedStr(v) => visitor.visit_borrowed_str(v),
Token::String(v) => visitor.visit_string(v.to_owned()),
Token::Bytes(v) => visitor.visit_bytes(v),
Token::BorrowedBytes(v) => visitor.visit_borrowed_bytes(v),
Token::ByteBuf(v) => visitor.visit_byte_buf(v.to_vec()),
Token::None => visitor.visit_none(),
Token::Some => visitor.visit_some(self),
Token::Unit => visitor.visit_unit(),
Token::UnitStruct { name: _ } => visitor.visit_unit(),
Token::NewtypeStruct { name: _ } => visitor.visit_newtype_struct(self),
Token::Seq { len } => self.visit_seq(len, Token::SeqEnd, visitor),
Token::Tuple { len } => self.visit_seq(Some(len), Token::TupleEnd, visitor),
Token::TupleStruct { name: _, len } => self.visit_seq(Some(len), Token::TupleStructEnd, visitor),
Token::Map { len } => self.visit_map(len, Token::MapEnd, visitor),
Token::Struct { name: _, len } => self.visit_map(Some(len), Token::StructEnd, visitor),
Token::Enum { name: _ } => {
let variant = self.next_token();
let next = self.peek_token();
match (variant, next) {
(Token::Str(variant), Token::Unit) => {
self.next_token();
visitor.visit_str(variant)
}
(Token::Bytes(variant), Token::Unit) => {
self.next_token();
visitor.visit_bytes(variant)
}
(Token::U32(variant), Token::Unit) => {
self.next_token();
visitor.visit_u32(variant)
}
(variant, Token::Unit) => unexpected!(variant),
(variant, _) => {
visitor.visit_map(EnumMapVisitor::new(self, variant, EnumFormat::Any))
}
}
}
Token::UnitVariant { name: _, variant } => visitor.visit_str(variant),
Token::NewtypeVariant { name: _, variant } => {
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Any),)
}
Token::TupleVariant { name: _, variant, len: _ } => {
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Seq),)
}
Token::StructVariant { name: _, variant, len: _ } => {
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Map),)
}
Token::SeqEnd | Token::TupleEnd | Token::TupleStructEnd | Token::MapEnd |
Token::StructEnd | Token::TupleVariantEnd | Token::StructVariantEnd => {
unexpected!(token);
}
}
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.peek_token() {
Token::Unit |
Token::None => {
self.next_token();
visitor.visit_none()
}
Token::Some => {
self.next_token();
visitor.visit_some(self)
}
_ => self.deserialize_any(visitor),
}
}
fn deserialize_enum<V>(
self,
name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.peek_token() {
Token::Enum { name: n } if name == n => {
self.next_token();
visitor.visit_enum(DeserializerEnumVisitor { de: self })
}
Token::UnitVariant { name: n, variant: _ } |
Token::NewtypeVariant { name: n, variant: _ } |
Token::TupleVariant { name: n, variant: _, len: _ } |
Token::StructVariant { name: n, variant: _, len: _ } if name == n => {
visitor.visit_enum(DeserializerEnumVisitor { de: self })
}
_ => {
unexpected!(self.next_token());
}
}
}
fn deserialize_unit_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.peek_token() {
Token::UnitStruct { name: _ } => {
assert_next_token!(self, Token::UnitStruct { name: name });
visitor.visit_unit()
}
_ => self.deserialize_any(visitor),
}
}
fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.peek_token() {
Token::NewtypeStruct { name: _ } => {
assert_next_token!(self, Token::NewtypeStruct { name: name });
visitor.visit_newtype_struct(self)
}
_ => self.deserialize_any(visitor),
}
}
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.peek_token() {
Token::Unit |
Token::UnitStruct { name: _ } => {
self.next_token();
visitor.visit_unit()
}
Token::Seq { len: _ } => {
self.next_token();
self.visit_seq(Some(len), Token::SeqEnd, visitor)
}
Token::Tuple { len: _ } => {
self.next_token();
self.visit_seq(Some(len), Token::TupleEnd, visitor)
}
Token::TupleStruct { name: _, len: _ } => {
self.next_token();
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
}
_ => self.deserialize_any(visitor),
}
}
fn deserialize_tuple_struct<V>(
self,
name: &'static str,
len: usize,
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.peek_token() {
Token::Unit => {
self.next_token();
visitor.visit_unit()
}
Token::UnitStruct { name: _ } => {
assert_next_token!(self, Token::UnitStruct { name: name });
visitor.visit_unit()
}
Token::Seq { len: _ } => {
self.next_token();
self.visit_seq(Some(len), Token::SeqEnd, visitor)
}
Token::Tuple { len: _ } => {
self.next_token();
self.visit_seq(Some(len), Token::TupleEnd, visitor)
}
Token::TupleStruct { name: _, len: n } => {
assert_next_token!(self, Token::TupleStruct { name: name, len: n });
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
}
_ => self.deserialize_any(visitor),
}
}
fn deserialize_struct<V>(
self,
name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.peek_token() {
Token::Struct { name: _, len: n } => {
assert_next_token!(self, Token::Struct { name: name, len: n });
self.visit_map(Some(fields.len()), Token::StructEnd, visitor)
}
Token::Map { len: _ } => {
self.next_token();
self.visit_map(Some(fields.len()), Token::MapEnd, visitor)
}
_ => self.deserialize_any(visitor),
}
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerSeqVisitor<'a, 'de: 'a> {
de: &'a mut Deserializer<'de>,
len: Option<usize>,
end: Token,
}
impl<'de, 'a> SeqAccess<'de> for DeserializerSeqVisitor<'a, 'de> {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where
T: DeserializeSeed<'de>,
{
if self.de.peek_token_opt() == Some(self.end) {
return Ok(None);
}
self.len = self.len.map(|len| len.saturating_sub(1));
seed.deserialize(&mut *self.de).map(Some)
}
fn size_hint(&self) -> Option<usize> {
self.len
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerMapVisitor<'a, 'de: 'a> {
de: &'a mut Deserializer<'de>,
len: Option<usize>,
end: Token,
}
impl<'de, 'a> MapAccess<'de> for DeserializerMapVisitor<'a, 'de> {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where
K: DeserializeSeed<'de>,
{
if self.de.peek_token_opt() == Some(self.end) {
return Ok(None);
}
self.len = self.len.map(|len| len.saturating_sub(1));
seed.deserialize(&mut *self.de).map(Some)
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
where
V: DeserializeSeed<'de>,
{
seed.deserialize(&mut *self.de)
}
fn size_hint(&self) -> Option<usize> {
self.len
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerEnumVisitor<'a, 'de: 'a> {
de: &'a mut Deserializer<'de>,
}
impl<'de, 'a> EnumAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
type Error = Error;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self), Error>
where
V: DeserializeSeed<'de>,
{
match self.de.peek_token() {
Token::UnitVariant { name: _, variant: v } |
Token::NewtypeVariant { name: _, variant: v } |
Token::TupleVariant { name: _, variant: v, len: _ } |
Token::StructVariant { name: _, variant: v, len: _ } => {
let de = v.into_deserializer();
let value = try!(seed.deserialize(de));
Ok((value, self))
}
_ => {
let value = try!(seed.deserialize(&mut *self.de));
Ok((value, self))
}
}
}
}
impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
type Error = Error;
fn unit_variant(self) -> Result<(), Error> {
match self.de.peek_token() {
Token::UnitVariant { name: _, variant: _ } => {
self.de.next_token();
Ok(())
}
_ => Deserialize::deserialize(self.de),
}
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
where
T: DeserializeSeed<'de>,
{
match self.de.peek_token() {
Token::NewtypeVariant { name: _, variant: _ } => {
self.de.next_token();
seed.deserialize(self.de)
}
_ => seed.deserialize(self.de),
}
}
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.de.peek_token() {
Token::TupleVariant { name: _, variant: _, len: enum_len } => {
let token = self.de.next_token();
if len == enum_len {
self.de
.visit_seq(Some(len), Token::TupleVariantEnd, visitor)
} else {
unexpected!(token);
}
}
Token::Seq { len: Some(enum_len) } => {
let token = self.de.next_token();
if len == enum_len {
self.de.visit_seq(Some(len), Token::SeqEnd, visitor)
} else {
unexpected!(token);
}
}
_ => de::Deserializer::deserialize_any(self.de, visitor),
}
}
fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.de.peek_token() {
Token::StructVariant { name: _, variant: _, len: enum_len } => {
let token = self.de.next_token();
if fields.len() == enum_len {
self.de
.visit_map(Some(fields.len()), Token::StructVariantEnd, visitor)
} else {
unexpected!(token);
}
}
Token::Map { len: Some(enum_len) } => {
let token = self.de.next_token();
if fields.len() == enum_len {
self.de
.visit_map(Some(fields.len()), Token::MapEnd, visitor)
} else {
unexpected!(token);
}
}
_ => de::Deserializer::deserialize_any(self.de, visitor),
}
}
}
//////////////////////////////////////////////////////////////////////////
struct EnumMapVisitor<'a, 'de: 'a> {
de: &'a mut Deserializer<'de>,
variant: Option<Token>,
format: EnumFormat,
}
enum EnumFormat {
Seq,
Map,
Any,
}
impl<'a, 'de> EnumMapVisitor<'a, 'de> {
fn new(de: &'a mut Deserializer<'de>, variant: Token, format: EnumFormat) -> Self {
EnumMapVisitor {
de: de,
variant: Some(variant),
format: format,
}
}
}
impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where
K: DeserializeSeed<'de>,
{
match self.variant.take() {
Some(Token::Str(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
Some(Token::Bytes(variant)) => {
seed.deserialize(BytesDeserializer { value: variant })
.map(Some)
}
Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
Some(other) => unexpected!(other),
None => Ok(None),
}
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
where
V: DeserializeSeed<'de>,
{
match self.format {
EnumFormat::Seq => {
let value = {
let visitor = DeserializerSeqVisitor {
de: self.de,
len: None,
end: Token::TupleVariantEnd,
};
try!(seed.deserialize(SeqAccessDeserializer::new(visitor)))
};
assert_next_token!(self.de, Token::TupleVariantEnd);
Ok(value)
}
EnumFormat::Map => {
let value = {
let visitor = DeserializerMapVisitor {
de: self.de,
len: None,
end: Token::StructVariantEnd,
};
try!(seed.deserialize(MapAccessDeserializer::new(visitor)))
};
assert_next_token!(self.de, Token::StructVariantEnd);
Ok(value)
}
EnumFormat::Any => seed.deserialize(&mut *self.de),
}
}
}
struct BytesDeserializer {
value: &'static [u8],
}
impl<'de> de::Deserializer<'de> for BytesDeserializer {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_bytes(self.value)
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
map struct enum identifier ignored_any
}
}
+47
View File
@@ -0,0 +1,47 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::error;
use std::fmt::{self, Display};
use serde::{ser, de};
#[derive(Clone, Debug)]
pub struct Error {
msg: String,
}
impl ser::Error for Error {
fn custom<T: Display>(msg: T) -> Error {
Error { msg: msg.to_string() }
}
}
impl de::Error for Error {
fn custom<T: Display>(msg: T) -> Error {
Error { msg: msg.to_string() }
}
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(&self.msg)
}
}
impl error::Error for Error {
fn description(&self) -> &str {
&self.msg
}
}
impl PartialEq<str> for Error {
fn eq(&self, other: &str) -> bool {
self.msg == other
}
}
+176
View File
@@ -0,0 +1,176 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! This crate provides a convenient concise way to write unit tests for
//! implementations of [`Serialize`] and [`Deserialize`].
//!
//! [`Serialize`]: https://docs.serde.rs/serde/ser/trait.Serialize.html
//! [`Deserialize`]: https://docs.serde.rs/serde/de/trait.Deserialize.html
//!
//! The `Serialize` impl for a value can be characterized by the sequence of
//! [`Serializer`] calls that are made in the course of serializing the value,
//! so `serde_test` provides a [`Token`] abstraction which corresponds roughly
//! to `Serializer` method calls. There is an [`assert_ser_tokens`] function to
//! test that a value serializes to a particular sequence of method calls, an
//! [`assert_de_tokens`] function to test that a value can be deserialized from
//! a particular sequence of method calls, and an [`assert_tokens`] function to
//! test both directions. There are also functions to test expected failure
//! conditions.
//!
//! [`Serializer`]: https://docs.serde.rs/serde/ser/trait.Serializer.html
//! [`Token`]: https://docs.serde.rs/serde_test/enum.Token.html
//! [`assert_ser_tokens`]: https://docs.serde.rs/serde_test/fn.assert_ser_tokens.html
//! [`assert_de_tokens`]: https://docs.serde.rs/serde_test/fn.assert_de_tokens.html
//! [`assert_tokens`]: https://docs.serde.rs/serde_test/fn.assert_tokens.html
//!
//! Here is an example from the [`linked-hash-map`] crate.
//!
//! [`linked-hash-map`]: https://github.com/contain-rs/linked-hash-map
//!
//! ```rust
//! # extern crate serde;
//! #
//! # macro_rules! ignore {
//! # ($($tt:tt)+) => {}
//! # }
//! #
//! # ignore! {
//! extern crate linked_hash_map;
//! use linked_hash_map::LinkedHashMap;
//! # }
//!
//! extern crate serde_test;
//! use serde_test::{Token, assert_tokens};
//!
//! # use std::fmt;
//! # use std::marker::PhantomData;
//! #
//! # use serde::ser::{Serialize, Serializer, SerializeMap};
//! # use serde::de::{Deserialize, Deserializer, Visitor, MapAccess};
//! #
//! # // Dumb immitation of LinkedHashMap.
//! # #[derive(PartialEq, Debug)]
//! # struct LinkedHashMap<K, V>(Vec<(K, V)>);
//! #
//! # impl<K, V> LinkedHashMap<K, V> {
//! # fn new() -> Self {
//! # LinkedHashMap(Vec::new())
//! # }
//! #
//! # fn insert(&mut self, k: K, v: V) {
//! # self.0.push((k, v));
//! # }
//! # }
//! #
//! # impl<K, V> Serialize for LinkedHashMap<K, V>
//! # where K: Serialize,
//! # V: Serialize
//! # {
//! # fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
//! # where S: Serializer
//! # {
//! # let mut map = serializer.serialize_map(Some(self.0.len()))?;
//! # for &(ref k, ref v) in &self.0 {
//! # map.serialize_entry(k, v)?;
//! # }
//! # map.end()
//! # }
//! # }
//! #
//! # struct LinkedHashMapVisitor<K, V>(PhantomData<(K, V)>);
//! #
//! # impl<'de, K, V> Visitor<'de> for LinkedHashMapVisitor<K, V>
//! # where K: Deserialize<'de>,
//! # V: Deserialize<'de>
//! # {
//! # type Value = LinkedHashMap<K, V>;
//! #
//! # fn expecting(&self, _: &mut fmt::Formatter) -> fmt::Result {
//! # unimplemented!()
//! # }
//! #
//! # fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
//! # where M: MapAccess<'de>
//! # {
//! # let mut map = LinkedHashMap::new();
//! # while let Some((key, value)) = access.next_entry()? {
//! # map.insert(key, value);
//! # }
//! # Ok(map)
//! # }
//! # }
//! #
//! # impl<'de, K, V> Deserialize<'de> for LinkedHashMap<K, V>
//! # where K: Deserialize<'de>,
//! # V: Deserialize<'de>
//! # {
//! # fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
//! # where D: Deserializer<'de>
//! # {
//! # deserializer.deserialize_map(LinkedHashMapVisitor(PhantomData))
//! # }
//! # }
//! #
//! #[test]
//! # fn not_a_test_ser_de_empty() {}
//! fn test_ser_de_empty() {
//! let map = LinkedHashMap::<char, u32>::new();
//!
//! assert_tokens(&map, &[
//! Token::Map { len: Some(0) },
//! Token::MapEnd,
//! ]);
//! }
//!
//! #[test]
//! # fn not_a_test_ser_de() {}
//! fn test_ser_de() {
//! let mut map = LinkedHashMap::new();
//! map.insert('b', 20);
//! map.insert('a', 10);
//! map.insert('c', 30);
//!
//! assert_tokens(&map, &[
//! Token::Map { len: Some(3) },
//! Token::Char('b'),
//! Token::I32(20),
//!
//! Token::Char('a'),
//! Token::I32(10),
//!
//! Token::Char('c'),
//! Token::I32(30),
//! Token::MapEnd,
//! ]);
//! }
//! #
//! # fn main() {
//! # test_ser_de_empty();
//! # test_ser_de();
//! # }
//! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.7")]
#[macro_use]
extern crate serde;
mod ser;
mod de;
mod error;
mod token;
mod assert;
pub use token::Token;
pub use assert::{assert_tokens, assert_ser_tokens, assert_ser_tokens_error, assert_de_tokens,
assert_de_tokens_error};
// Not public API.
#[doc(hidden)]
pub use de::Deserializer;
+434
View File
@@ -0,0 +1,434 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde::{ser, Serialize};
use error::Error;
use token::Token;
/// A `Serializer` that ensures that a value serializes to a given list of tokens.
#[derive(Debug)]
pub struct Serializer<'a> {
tokens: &'a [Token],
}
impl<'a> Serializer<'a> {
/// Creates the serializer.
pub fn new(tokens: &'a [Token]) -> Self {
Serializer { tokens: tokens }
}
/// Pulls the next token off of the serializer, ignoring it.
fn next_token(&mut self) -> Option<Token> {
if let Some((&first, rest)) = self.tokens.split_first() {
self.tokens = rest;
Some(first)
} else {
None
}
}
pub fn remaining(&self) -> usize {
self.tokens.len()
}
}
macro_rules! assert_next_token {
($ser:expr, $expected:ident) => {
assert_next_token!($ser, $expected, Token::$expected, true);
};
($ser:expr, $expected:ident($v:expr)) => {
assert_next_token!($ser, $expected, Token::$expected(v), v == $v);
};
($ser:expr, $expected:ident { $($k:ident),* }) => {
let compare = ($($k,)*);
assert_next_token!($ser, $expected, Token::$expected { $($k),* }, ($($k,)*) == compare);
};
($ser:expr, $expected:ident, $pat:pat, $guard:expr) => {
match $ser.next_token() {
Some($pat) if $guard => {}
Some(other) => {
panic!("expected Token::{} but serialized as {}",
stringify!($expected), other);
}
None => {
panic!("expected Token::{} after end of serialized tokens",
stringify!($expected));
}
}
};
}
impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
type Ok = ();
type Error = Error;
type SerializeSeq = Self;
type SerializeTuple = Self;
type SerializeTupleStruct = Self;
type SerializeTupleVariant = Variant<'s, 'a>;
type SerializeMap = Self;
type SerializeStruct = Self;
type SerializeStructVariant = Variant<'s, 'a>;
fn serialize_bool(self, v: bool) -> Result<(), Error> {
assert_next_token!(self, Bool(v));
Ok(())
}
fn serialize_i8(self, v: i8) -> Result<(), Error> {
assert_next_token!(self, I8(v));
Ok(())
}
fn serialize_i16(self, v: i16) -> Result<(), Error> {
assert_next_token!(self, I16(v));
Ok(())
}
fn serialize_i32(self, v: i32) -> Result<(), Error> {
assert_next_token!(self, I32(v));
Ok(())
}
fn serialize_i64(self, v: i64) -> Result<(), Error> {
assert_next_token!(self, I64(v));
Ok(())
}
fn serialize_u8(self, v: u8) -> Result<(), Error> {
assert_next_token!(self, U8(v));
Ok(())
}
fn serialize_u16(self, v: u16) -> Result<(), Error> {
assert_next_token!(self, U16(v));
Ok(())
}
fn serialize_u32(self, v: u32) -> Result<(), Error> {
assert_next_token!(self, U32(v));
Ok(())
}
fn serialize_u64(self, v: u64) -> Result<(), Error> {
assert_next_token!(self, U64(v));
Ok(())
}
fn serialize_f32(self, v: f32) -> Result<(), Error> {
assert_next_token!(self, F32(v));
Ok(())
}
fn serialize_f64(self, v: f64) -> Result<(), Error> {
assert_next_token!(self, F64(v));
Ok(())
}
fn serialize_char(self, v: char) -> Result<(), Error> {
assert_next_token!(self, Char(v));
Ok(())
}
fn serialize_str(self, v: &str) -> Result<(), Error> {
match self.tokens.first() {
Some(&Token::BorrowedStr(_)) => assert_next_token!(self, BorrowedStr(v)),
Some(&Token::String(_)) => assert_next_token!(self, String(v)),
_ => assert_next_token!(self, Str(v)),
}
Ok(())
}
fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> {
match self.tokens.first() {
Some(&Token::BorrowedBytes(_)) => assert_next_token!(self, BorrowedBytes(v)),
Some(&Token::ByteBuf(_)) => assert_next_token!(self, ByteBuf(v)),
_ => assert_next_token!(self, Bytes(v)),
}
Ok(())
}
fn serialize_unit(self) -> Result<(), Error> {
assert_next_token!(self, Unit);
Ok(())
}
fn serialize_unit_struct(self, name: &'static str) -> Result<(), Error> {
assert_next_token!(self, UnitStruct { name });
Ok(())
}
fn serialize_unit_variant(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
) -> Result<(), Error> {
if self.tokens.first() == Some(&Token::Enum { name: name }) {
self.next_token();
assert_next_token!(self, Str(variant));
assert_next_token!(self, Unit);
} else {
assert_next_token!(self, UnitVariant { name, variant });
}
Ok(())
}
fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<(), Error>
where
T: Serialize,
{
assert_next_token!(self, NewtypeStruct { name });
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<(), Error>
where
T: Serialize,
{
if self.tokens.first() == Some(&Token::Enum { name: name }) {
self.next_token();
assert_next_token!(self, Str(variant));
} else {
assert_next_token!(self, NewtypeVariant { name, variant });
}
value.serialize(self)
}
fn serialize_none(self) -> Result<(), Error> {
assert_next_token!(self, None);
Ok(())
}
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
assert_next_token!(self, Some);
value.serialize(self)
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> {
assert_next_token!(self, Seq { len });
Ok(self)
}
fn serialize_tuple(self, len: usize) -> Result<Self, Error> {
assert_next_token!(self, Tuple { len });
Ok(self)
}
fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
assert_next_token!(self, TupleStruct { name, len });
Ok(self)
}
fn serialize_tuple_variant(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant, Error> {
if self.tokens.first() == Some(&Token::Enum { name: name }) {
self.next_token();
assert_next_token!(self, Str(variant));
let len = Some(len);
assert_next_token!(self, Seq { len });
Ok(Variant { ser: self, end: Token::SeqEnd })
} else {
assert_next_token!(self, TupleVariant { name, variant, len });
Ok(Variant { ser: self, end: Token::TupleVariantEnd })
}
}
fn serialize_map(self, len: Option<usize>) -> Result<Self, Error> {
assert_next_token!(self, Map { len });
Ok(self)
}
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
assert_next_token!(self, Struct { name, len });
Ok(self)
}
fn serialize_struct_variant(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeStructVariant, Error> {
if self.tokens.first() == Some(&Token::Enum { name: name }) {
self.next_token();
assert_next_token!(self, Str(variant));
let len = Some(len);
assert_next_token!(self, Map { len });
Ok(Variant { ser: self, end: Token::MapEnd })
} else {
assert_next_token!(self, StructVariant { name, variant, len });
Ok(Variant { ser: self, end: Token::StructVariantEnd })
}
}
}
pub struct Variant<'s, 'a: 's> {
ser: &'s mut Serializer<'a>,
end: Token,
}
impl<'s, 'a> ser::SerializeSeq for &'s mut Serializer<'a> {
type Ok = ();
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_next_token!(self, SeqEnd);
Ok(())
}
}
impl<'s, 'a> ser::SerializeTuple for &'s mut Serializer<'a> {
type Ok = ();
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_next_token!(self, TupleEnd);
Ok(())
}
}
impl<'s, 'a> ser::SerializeTupleStruct for &'s mut Serializer<'a> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_next_token!(self, TupleStructEnd);
Ok(())
}
}
impl<'s, 'a> ser::SerializeTupleVariant for Variant<'s, 'a> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
value.serialize(&mut *self.ser)
}
fn end(self) -> Result<(), Error> {
match self.end {
Token::TupleVariantEnd => assert_next_token!(self.ser, TupleVariantEnd),
Token::SeqEnd => assert_next_token!(self.ser, SeqEnd),
_ => unreachable!(),
}
Ok(())
}
}
impl<'s, 'a> ser::SerializeMap for &'s mut Serializer<'a> {
type Ok = ();
type Error = Error;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
where
T: Serialize,
{
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_next_token!(self, MapEnd);
Ok(())
}
}
impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error>
where
T: Serialize,
{
try!(key.serialize(&mut **self));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Self::Error> {
assert_next_token!(self, StructEnd);
Ok(())
}
}
impl<'s, 'a> ser::SerializeStructVariant for Variant<'s, 'a> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error>
where
T: Serialize,
{
try!(key.serialize(&mut *self.ser));
value.serialize(&mut *self.ser)
}
fn end(self) -> Result<(), Self::Error> {
match self.end {
Token::StructVariantEnd => assert_next_token!(self.ser, StructVariantEnd),
Token::MapEnd => assert_next_token!(self.ser, MapEnd),
_ => unreachable!(),
}
Ok(())
}
}
+558
View File
@@ -0,0 +1,558 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::{self, Debug, Display};
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Token {
/// A serialized `bool`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&true, &[Token::Bool(true)]);
/// ```
Bool(bool),
/// A serialized `i8`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0i8, &[Token::I8(0)]);
/// ```
I8(i8),
/// A serialized `i16`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0i16, &[Token::I16(0)]);
/// ```
I16(i16),
/// A serialized `i32`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0i32, &[Token::I32(0)]);
/// ```
I32(i32),
/// A serialized `i64`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0i64, &[Token::I64(0)]);
/// ```
I64(i64),
/// A serialized `u8`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0u8, &[Token::U8(0)]);
/// ```
U8(u8),
/// A serialized `u16`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0u16, &[Token::U16(0)]);
/// ```
U16(u16),
/// A serialized `u32`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0u32, &[Token::U32(0)]);
/// ```
U32(u32),
/// A serialized `u64`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0u64, &[Token::U64(0)]);
/// ```
U64(u64),
/// A serialized `f32`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0f32, &[Token::F32(0.0)]);
/// ```
F32(f32),
/// A serialized `f64`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0f64, &[Token::F64(0.0)]);
/// ```
F64(f64),
/// A serialized `char`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&'\n', &[Token::Char('\n')]);
/// ```
Char(char),
/// A serialized `str`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// let s = String::from("transient");
/// assert_tokens(&s, &[Token::Str("transient")]);
/// ```
Str(&'static str),
/// A borrowed `str`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// let s: &str = "borrowed";
/// assert_tokens(&s, &[Token::BorrowedStr("borrowed")]);
/// ```
BorrowedStr(&'static str),
/// A serialized `String`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// let s = String::from("owned");
/// assert_tokens(&s, &[Token::String("owned")]);
/// ```
String(&'static str),
/// A serialized `[u8]`
Bytes(&'static [u8]),
/// A borrowed `[u8]`.
BorrowedBytes(&'static [u8]),
/// A serialized `ByteBuf`
ByteBuf(&'static [u8]),
/// A serialized `Option<T>` containing none.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// let opt = None::<char>;
/// assert_tokens(&opt, &[Token::None]);
/// ```
None,
/// The header to a serialized `Option<T>` containing some value.
///
/// The tokens of the value follow after this header.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// let opt = Some('c');
/// assert_tokens(&opt, &[
/// Token::Some,
/// Token::Char('c'),
/// ]);
/// ```
Some,
/// A serialized `()`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&(), &[Token::Unit]);
/// ```
Unit,
/// A serialized unit struct of the given name.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct X;
///
/// assert_tokens(&X, &[Token::UnitStruct { name: "X" }]);
/// # }
/// ```
UnitStruct { name: &'static str },
/// A unit variant of an enum.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// enum E {
/// A,
/// }
///
/// let a = E::A;
/// assert_tokens(&a, &[Token::UnitVariant { name: "E", variant: "A" }]);
/// # }
/// ```
UnitVariant { name: &'static str, variant: &'static str },
/// The header to a serialized newtype struct of the given name.
///
/// After this header is the value contained in the newtype struct.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct N(String);
///
/// let n = N("newtype".to_owned());
/// assert_tokens(&n, &[
/// Token::NewtypeStruct { name: "N" },
/// Token::String("newtype"),
/// ]);
/// # }
/// ```
NewtypeStruct { name: &'static str },
/// The header to a newtype variant of an enum.
///
/// After this header is the value contained in the newtype variant.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// enum E {
/// B(u8),
/// }
///
/// let b = E::B(0);
/// assert_tokens(&b, &[
/// Token::NewtypeVariant { name: "E", variant: "B" },
/// Token::U8(0),
/// ]);
/// # }
/// ```
NewtypeVariant { name: &'static str, variant: &'static str },
/// The header to a sequence.
///
/// After this header are the elements of the sequence, followed by
/// `SeqEnd`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// let vec = vec!['a', 'b', 'c'];
/// assert_tokens(&vec, &[
/// Token::Seq { len: Some(3) },
/// Token::Char('a'),
/// Token::Char('b'),
/// Token::Char('c'),
/// Token::SeqEnd,
/// ]);
/// ```
Seq { len: Option<usize> },
/// An indicator of the end of a sequence.
SeqEnd,
/// The header to a tuple.
///
/// After this header are the elements of the tuple, followed by `TupleEnd`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// let tuple = ('a', 100);
/// assert_tokens(&tuple, &[
/// Token::Tuple { len: 2 },
/// Token::Char('a'),
/// Token::I32(100),
/// Token::TupleEnd,
/// ]);
/// ```
Tuple { len: usize },
/// An indicator of the end of a tuple.
TupleEnd,
/// The header to a tuple struct.
///
/// After this header are the fields of the tuple struct, followed by
/// `TupleStructEnd`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct T(u8, u8);
///
/// let t = T(0, 0);
/// assert_tokens(&t, &[
/// Token::TupleStruct { name: "T", len: 2 },
/// Token::U8(0),
/// Token::U8(0),
/// Token::TupleStructEnd,
/// ]);
/// # }
/// ```
TupleStruct { name: &'static str, len: usize },
/// An indicator of the end of a tuple struct.
TupleStructEnd,
/// The header to a tuple variant of an enum.
///
/// After this header are the fields of the tuple variant, followed by
/// `TupleVariantEnd`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// enum E {
/// C(u8, u8),
/// }
///
/// let c = E::C(0, 0);
/// assert_tokens(&c, &[
/// Token::TupleVariant { name: "E", variant: "C", len: 2 },
/// Token::U8(0),
/// Token::U8(0),
/// Token::TupleVariantEnd,
/// ]);
/// # }
/// ```
TupleVariant { name: &'static str, variant: &'static str, len: usize },
/// An indicator of the end of a tuple variant.
TupleVariantEnd,
/// The header to a map.
///
/// After this header are the entries of the map, followed by `MapEnd`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert('A', 65);
/// map.insert('Z', 90);
///
/// assert_tokens(&map, &[
/// Token::Map { len: Some(2) },
/// Token::Char('A'),
/// Token::I32(65),
/// Token::Char('Z'),
/// Token::I32(90),
/// Token::MapEnd,
/// ]);
/// ```
Map { len: Option<usize> },
/// An indicator of the end of a map.
MapEnd,
/// The header of a struct.
///
/// After this header are the fields of the struct, followed by `StructEnd`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct S {
/// a: u8,
/// b: u8,
/// }
///
/// let s = S { a: 0, b: 0 };
/// assert_tokens(&s, &[
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("a"),
/// Token::U8(0),
/// Token::Str("b"),
/// Token::U8(0),
/// Token::StructEnd,
/// ]);
/// # }
/// ```
Struct { name: &'static str, len: usize },
/// An indicator of the end of a struct.
StructEnd,
/// The header of a struct variant of an enum.
///
/// After this header are the fields of the struct variant, followed by
/// `StructVariantEnd`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// enum E {
/// D { d: u8 },
/// }
///
/// let d = E::D { d: 0 };
/// assert_tokens(&d, &[
/// Token::StructVariant { name: "E", variant: "D", len: 1 },
/// Token::Str("d"),
/// Token::U8(0),
/// Token::StructVariantEnd,
/// ]);
/// # }
/// ```
StructVariant { name: &'static str, variant: &'static str, len: usize },
/// An indicator of the end of a struct variant.
StructVariantEnd,
/// The header to an enum of the given name.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// enum E {
/// A,
/// B(u8),
/// C(u8, u8),
/// D { d: u8 },
/// }
///
/// let a = E::A;
/// assert_tokens(&a, &[
/// Token::Enum { name: "E" },
/// Token::Str("A"),
/// Token::Unit,
/// ]);
///
/// let b = E::B(0);
/// assert_tokens(&b, &[
/// Token::Enum { name: "E" },
/// Token::Str("B"),
/// Token::U8(0),
/// ]);
///
/// let c = E::C(0, 0);
/// assert_tokens(&c, &[
/// Token::Enum { name: "E" },
/// Token::Str("C"),
/// Token::Seq { len: Some(2) },
/// Token::U8(0),
/// Token::U8(0),
/// Token::SeqEnd,
/// ]);
///
/// let d = E::D { d: 0 };
/// assert_tokens(&d, &[
/// Token::Enum { name: "E" },
/// Token::Str("D"),
/// Token::Map { len: Some(1) },
/// Token::Str("d"),
/// Token::U8(0),
/// Token::MapEnd,
/// ]);
/// # }
/// ```
Enum { name: &'static str },
}
impl Display for Token {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(self, formatter)
}
}
-174
View File
@@ -1,174 +0,0 @@
//! Helper module to enable serializing bytes more efficiently
use std::ops;
use ser;
use de;
///////////////////////////////////////////////////////////////////////////////
/// `Bytes` wraps a `&[u8]` in order to serialize into a byte array.
pub struct Bytes<'a> {
bytes: &'a [u8],
}
impl<'a> From<&'a [u8]> for Bytes<'a> {
fn from(bytes: &'a [u8]) -> Self {
Bytes {
bytes: bytes,
}
}
}
impl<'a> From<&'a Vec<u8>> for Bytes<'a> {
fn from(bytes: &'a Vec<u8>) -> Self {
Bytes {
bytes: &bytes,
}
}
}
impl<'a> ops::Deref for Bytes<'a> {
type Target = [u8];
fn deref(&self) -> &[u8] { self.bytes }
}
impl<'a> ser::Serialize for Bytes<'a> {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: ser::Serializer
{
serializer.visit_bytes(self.bytes)
}
}
///////////////////////////////////////////////////////////////////////////////
/// `ByteBuf` wraps a `Vec<u8>` in order to hook into serialize and from deserialize a byte array.
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct ByteBuf {
bytes: Vec<u8>,
}
impl ByteBuf {
pub fn new() -> Self {
ByteBuf {
bytes: Vec::new(),
}
}
pub fn with_capacity(cap: usize) -> Self {
ByteBuf {
bytes: Vec::with_capacity(cap)
}
}
}
impl<T> From<T> for ByteBuf where T: Into<Vec<u8>> {
fn from(bytes: T) -> Self {
ByteBuf {
bytes: bytes.into(),
}
}
}
impl AsRef<Vec<u8>> for ByteBuf {
fn as_ref(&self) -> &Vec<u8> {
&self.bytes
}
}
impl AsRef<[u8]> for ByteBuf {
fn as_ref(&self) -> &[u8] {
&self.bytes
}
}
impl AsMut<Vec<u8>> for ByteBuf {
fn as_mut(&mut self) -> &mut Vec<u8> {
&mut self.bytes
}
}
impl AsMut<[u8]> for ByteBuf {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.bytes
}
}
impl ops::Deref for ByteBuf {
type Target = [u8];
fn deref(&self) -> &[u8] { &self.bytes[..] }
}
impl ops::DerefMut for ByteBuf {
fn deref_mut(&mut self) -> &mut [u8] { &mut self.bytes[..] }
}
impl ser::Serialize for ByteBuf {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: ser::Serializer
{
serializer.visit_bytes(&self)
}
}
pub struct ByteBufVisitor;
impl de::Visitor for ByteBufVisitor {
type Value = ByteBuf;
#[inline]
fn visit_unit<E>(&mut self) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf {
bytes: Vec::new(),
})
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<ByteBuf, V::Error>
where V: de::SeqVisitor,
{
let (len, _) = visitor.size_hint();
let mut values = Vec::with_capacity(len);
while let Some(value) = try!(visitor.visit()) {
values.push(value);
}
try!(visitor.end());
Ok(ByteBuf {
bytes: values,
})
}
#[inline]
fn visit_bytes<E>(&mut self, v: &[u8]) -> Result<ByteBuf, E>
where E: de::Error,
{
self.visit_byte_buf(v.to_vec())
}
#[inline]
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf {
bytes: v,
})
}
}
impl de::Deserialize for ByteBuf {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<ByteBuf, D::Error>
where D: de::Deserializer
{
deserializer.visit_bytes(ByteBufVisitor)
}
}
-686
View File
@@ -1,686 +0,0 @@
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::hash::Hash;
use std::marker::PhantomData;
use std::path;
use std::rc::Rc;
use std::sync::Arc;
use num::FromPrimitive;
use de::{
Deserialize,
Deserializer,
Error,
MapVisitor,
SeqVisitor,
Visitor,
};
///////////////////////////////////////////////////////////////////////////////
pub struct UnitVisitor;
impl Visitor for UnitVisitor {
type Value = ();
fn visit_unit<E>(&mut self) -> Result<(), E>
where E: Error,
{
Ok(())
}
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<(), V::Error>
where V: SeqVisitor,
{
visitor.end()
}
}
impl Deserialize for () {
fn deserialize<D>(deserializer: &mut D) -> Result<(), D::Error>
where D: Deserializer,
{
deserializer.visit(UnitVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
struct BoolVisitor;
impl Visitor for BoolVisitor {
type Value = bool;
fn visit_bool<E>(&mut self, v: bool) -> Result<bool, E>
where E: Error,
{
Ok(v)
}
}
impl Deserialize for bool {
fn deserialize<D>(deserializer: &mut D) -> Result<bool, D::Error>
where D: Deserializer,
{
deserializer.visit(BoolVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! impl_deserialize_num_method {
($src_ty:ty, $method:ident, $from_method:ident) => {
#[inline]
fn $method<E>(&mut self, v: $src_ty) -> Result<T, E>
where E: Error,
{
match FromPrimitive::$from_method(v) {
Some(v) => Ok(v),
None => Err(Error::syntax_error()),
}
}
}
}
pub struct PrimitiveVisitor<T> {
marker: PhantomData<T>,
}
impl<T> PrimitiveVisitor<T> {
#[inline]
pub fn new() -> Self {
PrimitiveVisitor {
marker: PhantomData,
}
}
}
impl<
T: Deserialize + FromPrimitive
> Visitor for PrimitiveVisitor<T> {
type Value = T;
impl_deserialize_num_method!(isize, visit_isize, from_isize);
impl_deserialize_num_method!(i8, visit_i8, from_i8);
impl_deserialize_num_method!(i16, visit_i16, from_i16);
impl_deserialize_num_method!(i32, visit_i32, from_i32);
impl_deserialize_num_method!(i64, visit_i64, from_i64);
impl_deserialize_num_method!(usize, visit_usize, from_usize);
impl_deserialize_num_method!(u8, visit_u8, from_u8);
impl_deserialize_num_method!(u16, visit_u16, from_u16);
impl_deserialize_num_method!(u32, visit_u32, from_u32);
impl_deserialize_num_method!(u64, visit_u64, from_u64);
impl_deserialize_num_method!(f32, visit_f32, from_f32);
impl_deserialize_num_method!(f64, visit_f64, from_f64);
}
macro_rules! impl_deserialize_num {
($ty:ty) => {
impl Deserialize for $ty {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<$ty, D::Error>
where D: Deserializer,
{
deserializer.visit(PrimitiveVisitor::new())
}
}
}
}
impl_deserialize_num!(isize);
impl_deserialize_num!(i8);
impl_deserialize_num!(i16);
impl_deserialize_num!(i32);
impl_deserialize_num!(i64);
impl_deserialize_num!(usize);
impl_deserialize_num!(u8);
impl_deserialize_num!(u16);
impl_deserialize_num!(u32);
impl_deserialize_num!(u64);
impl_deserialize_num!(f32);
impl_deserialize_num!(f64);
///////////////////////////////////////////////////////////////////////////////
struct CharVisitor;
impl Visitor for CharVisitor {
type Value = char;
#[inline]
fn visit_char<E>(&mut self, v: char) -> Result<char, E>
where E: Error,
{
Ok(v)
}
#[inline]
fn visit_str<E>(&mut self, v: &str) -> Result<char, E>
where E: Error,
{
let mut iter = v.chars();
if let Some(v) = iter.next() {
if iter.next().is_some() {
Err(Error::syntax_error())
} else {
Ok(v)
}
} else {
Err(Error::end_of_stream_error())
}
}
}
impl Deserialize for char {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<char, D::Error>
where D: Deserializer,
{
deserializer.visit(CharVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
struct StringVisitor;
impl Visitor for StringVisitor {
type Value = String;
fn visit_str<E>(&mut self, v: &str) -> Result<String, E>
where E: Error,
{
Ok(v.to_string())
}
fn visit_string<E>(&mut self, v: String) -> Result<String, E>
where E: Error,
{
Ok(v)
}
}
impl Deserialize for String {
fn deserialize<D>(deserializer: &mut D) -> Result<String, D::Error>
where D: Deserializer,
{
deserializer.visit(StringVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
struct OptionVisitor<T> {
marker: PhantomData<T>,
}
impl<
T: Deserialize,
> Visitor for OptionVisitor<T> {
type Value = Option<T>;
#[inline]
fn visit_none<E>(&mut self) -> Result<Option<T>, E>
where E: Error,
{
Ok(None)
}
#[inline]
fn visit_some<D>(&mut self, deserializer: &mut D) -> Result<Option<T>, D::Error>
where D: Deserializer,
{
Ok(Some(try!(Deserialize::deserialize(deserializer))))
}
}
impl<T> Deserialize for Option<T> where T: Deserialize {
fn deserialize<D>(deserializer: &mut D) -> Result<Option<T>, D::Error>
where D: Deserializer,
{
deserializer.visit_option(OptionVisitor { marker: PhantomData })
}
}
///////////////////////////////////////////////////////////////////////////////
pub struct BTreeSetVisitor<T> {
marker: PhantomData<T>,
}
impl<T> BTreeSetVisitor<T> {
pub fn new() -> Self {
BTreeSetVisitor {
marker: PhantomData,
}
}
}
impl<T> Visitor for BTreeSetVisitor<T>
where T: Deserialize + Eq + Ord,
{
type Value = BTreeSet<T>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<BTreeSet<T>, E>
where E: Error,
{
Ok(BTreeSet::new())
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<BTreeSet<T>, V::Error>
where V: SeqVisitor,
{
let mut values = BTreeSet::new();
while let Some(value) = try!(visitor.visit()) {
values.insert(value);
}
try!(visitor.end());
Ok(values)
}
}
impl<T> Deserialize for BTreeSet<T>
where T: Deserialize + Eq + Ord,
{
fn deserialize<D>(deserializer: &mut D) -> Result<BTreeSet<T>, D::Error>
where D: Deserializer,
{
deserializer.visit(BTreeSetVisitor::new())
}
}
///////////////////////////////////////////////////////////////////////////////
pub struct HashSetVisitor<T> {
marker: PhantomData<T>,
}
impl<T> HashSetVisitor<T> {
pub fn new() -> Self {
HashSetVisitor {
marker: PhantomData,
}
}
}
impl<T> Visitor for HashSetVisitor<T>
where T: Deserialize + Eq + Hash,
{
type Value = HashSet<T>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<HashSet<T>, E>
where E: Error,
{
Ok(HashSet::new())
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<HashSet<T>, V::Error>
where V: SeqVisitor,
{
let (len, _) = visitor.size_hint();
let mut values = HashSet::with_capacity(len);
while let Some(value) = try!(visitor.visit()) {
values.insert(value);
}
try!(visitor.end());
Ok(values)
}
}
impl<T> Deserialize for HashSet<T>
where T: Deserialize + Eq + Hash,
{
fn deserialize<D>(deserializer: &mut D) -> Result<HashSet<T>, D::Error>
where D: Deserializer,
{
deserializer.visit(HashSetVisitor::new())
}
}
///////////////////////////////////////////////////////////////////////////////
pub struct VecVisitor<T> {
marker: PhantomData<T>,
}
impl<T> VecVisitor<T> {
pub fn new() -> Self {
VecVisitor {
marker: PhantomData,
}
}
}
impl<T> Visitor for VecVisitor<T> where T: Deserialize {
type Value = Vec<T>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<Vec<T>, E>
where E: Error,
{
Ok(Vec::new())
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<Vec<T>, V::Error>
where V: SeqVisitor,
{
let (len, _) = visitor.size_hint();
let mut values = Vec::with_capacity(len);
while let Some(value) = try!(visitor.visit()) {
values.push(value);
}
try!(visitor.end());
Ok(values)
}
}
impl<T> Deserialize for Vec<T>
where T: Deserialize,
{
fn deserialize<D>(deserializer: &mut D) -> Result<Vec<T>, D::Error>
where D: Deserializer,
{
deserializer.visit(VecVisitor::new())
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! tuple_impls {
() => {};
($($visitor:ident => ($($name:ident),+),)+) => {
$(
struct $visitor<$($name,)+> {
marker: PhantomData<($($name,)+)>,
}
impl<
$($name: Deserialize,)+
> Visitor for $visitor<$($name,)+> {
type Value = ($($name,)+);
#[inline]
#[allow(non_snake_case)]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<($($name,)+), V::Error>
where V: SeqVisitor,
{
$(
let $name = match try!(visitor.visit()) {
Some(value) => value,
None => { return Err(Error::end_of_stream_error()); }
};
)+;
try!(visitor.end());
Ok(($($name,)+))
}
}
impl<
$($name: Deserialize),+
> Deserialize for ($($name,)+) {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<($($name,)+), D::Error>
where D: Deserializer,
{
deserializer.visit($visitor { marker: PhantomData })
}
}
)+
}
}
tuple_impls! {
TupleVisitor1 => (T0),
TupleVisitor2 => (T0, T1),
TupleVisitor3 => (T0, T1, T2),
TupleVisitor4 => (T0, T1, T2, T3),
TupleVisitor5 => (T0, T1, T2, T3, T4),
TupleVisitor6 => (T0, T1, T2, T3, T4, T5),
TupleVisitor7 => (T0, T1, T2, T3, T4, T5, T6),
TupleVisitor8 => (T0, T1, T2, T3, T4, T5, T6, T7),
TupleVisitor9 => (T0, T1, T2, T3, T4, T5, T6, T7, T8),
TupleVisitor10 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9),
TupleVisitor11 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10),
TupleVisitor12 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11),
}
///////////////////////////////////////////////////////////////////////////////
pub struct BTreeMapVisitor<K, V> {
marker: PhantomData<BTreeMap<K, V>>,
}
impl<K, V> BTreeMapVisitor<K, V> {
#[inline]
pub fn new() -> Self {
BTreeMapVisitor {
marker: PhantomData,
}
}
}
impl<K, V> Visitor for BTreeMapVisitor<K, V>
where K: Deserialize + Ord,
V: Deserialize
{
type Value = BTreeMap<K, V>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<BTreeMap<K, V>, E>
where E: Error,
{
Ok(BTreeMap::new())
}
#[inline]
fn visit_map<Visitor>(&mut self, mut visitor: Visitor) -> Result<BTreeMap<K, V>, Visitor::Error>
where Visitor: MapVisitor,
{
let mut values = BTreeMap::new();
while let Some((key, value)) = try!(visitor.visit()) {
values.insert(key, value);
}
try!(visitor.end());
Ok(values)
}
}
impl<K, V> Deserialize for BTreeMap<K, V>
where K: Deserialize + Eq + Ord,
V: Deserialize,
{
fn deserialize<D>(deserializer: &mut D) -> Result<BTreeMap<K, V>, D::Error>
where D: Deserializer,
{
deserializer.visit(BTreeMapVisitor::new())
}
}
///////////////////////////////////////////////////////////////////////////////
pub struct HashMapVisitor<K, V> {
marker: PhantomData<HashMap<K, V>>,
}
impl<K, V> HashMapVisitor<K, V> {
#[inline]
pub fn new() -> Self {
HashMapVisitor {
marker: PhantomData,
}
}
}
impl<K, V> Visitor for HashMapVisitor<K, V>
where K: Deserialize + Eq + Hash,
V: Deserialize,
{
type Value = HashMap<K, V>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<HashMap<K, V>, E>
where E: Error,
{
Ok(HashMap::new())
}
#[inline]
fn visit_map<V_>(&mut self, mut visitor: V_) -> Result<HashMap<K, V>, V_::Error>
where V_: MapVisitor,
{
let (len, _) = visitor.size_hint();
let mut values = HashMap::with_capacity(len);
while let Some((key, value)) = try!(visitor.visit()) {
values.insert(key, value);
}
try!(visitor.end());
Ok(values)
}
}
impl<K, V> Deserialize for HashMap<K, V>
where K: Deserialize + Eq + Hash,
V: Deserialize,
{
fn deserialize<D>(deserializer: &mut D) -> Result<HashMap<K, V>, D::Error>
where D: Deserializer,
{
deserializer.visit(HashMapVisitor::new())
}
}
///////////////////////////////////////////////////////////////////////////////
// FIXME: `VecMap` is unstable.
/*
pub struct VecMapVisitor<V> {
marker: PhantomData<VecMap<V>>,
}
impl<V> VecMapVisitor<V> {
#[inline]
pub fn new() -> Self {
VecMapVisitor {
marker: PhantomData,
}
}
}
impl<V> Visitor for VecMapVisitor<V>
where V: Deserialize,
{
type Value = VecMap<V>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<VecMap<V>, E>
where E: Error,
{
Ok(VecMap::new())
}
#[inline]
fn visit_map<V_>(&mut self, mut visitor: V_) -> Result<VecMap<V>, V_::Error>
where V_: MapVisitor,
{
let (len, _) = visitor.size_hint();
let mut values = VecMap::with_capacity(len);
while let Some((key, value)) = try!(visitor.visit()) {
values.insert(key, value);
}
try!(visitor.end());
Ok(values)
}
}
impl<V> Deserialize for VecMap<V>
where V: Deserialize,
{
fn deserialize<D>(deserializer: &mut D) -> Result<VecMap<V>, D::Error>
where D: Deserializer,
{
deserializer.visit(VecMapVisitor::new())
}
}
*/
///////////////////////////////////////////////////////////////////////////////
struct PathBufVisitor;
impl Visitor for PathBufVisitor {
type Value = path::PathBuf;
fn visit_str<E>(&mut self, v: &str) -> Result<path::PathBuf, E>
where E: Error,
{
Ok(From::from(v))
}
fn visit_string<E>(&mut self, v: String) -> Result<path::PathBuf, E>
where E: Error,
{
self.visit_str(&v)
}
}
impl Deserialize for path::PathBuf {
fn deserialize<D>(deserializer: &mut D) -> Result<path::PathBuf, D::Error>
where D: Deserializer,
{
deserializer.visit(PathBufVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
impl<T: Deserialize> Deserialize for Box<T> {
fn deserialize<D>(deserializer: &mut D) -> Result<Box<T>, D::Error>
where D: Deserializer,
{
let val = try!(Deserialize::deserialize(deserializer));
Ok(Box::new(val))
}
}
impl<T: Deserialize> Deserialize for Arc<T> {
fn deserialize<D>(deserializer: &mut D) -> Result<Arc<T>, D::Error>
where D: Deserializer,
{
let val = try!(Deserialize::deserialize(deserializer));
Ok(Arc::new(val))
}
}
impl<T: Deserialize> Deserialize for Rc<T> {
fn deserialize<D>(deserializer: &mut D) -> Result<Rc<T>, D::Error>
where D: Deserializer,
{
let val = try!(Deserialize::deserialize(deserializer));
Ok(Rc::new(val))
}
}
-469
View File
@@ -1,469 +0,0 @@
//! Generic deserialization framework.
pub mod impls;
pub mod value;
///////////////////////////////////////////////////////////////////////////////
pub trait Error {
fn syntax_error() -> Self;
fn end_of_stream_error() -> Self;
fn unknown_field_error(field: &str) -> Self;
fn missing_field_error(field: &'static str) -> Self;
}
///////////////////////////////////////////////////////////////////////////////
pub trait Deserialize {
/// Deserialize this value given this `Deserializer`.
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer;
}
///////////////////////////////////////////////////////////////////////////////
/// `Deserializer` is an abstract trait that can deserialize values into a `Visitor`.
pub trait Deserializer {
type Error: Error;
/// The `visit` method walks a visitor through a value as it is being deserialized.
fn visit<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
/// The `visit_option` method allows a `Deserialize` type to inform the `Deserializer` that
/// it's expecting an optional value. This allows deserializers that encode an optional value
/// as a nullable value to convert the null value into a `None`, and a regular value as
/// `Some(value)`.
#[inline]
fn visit_option<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// The `visit_seq` method allows a `Deserialize` type to inform the `Deserializer` that it's
/// expecting a sequence of values. This allows deserializers to parse sequences that aren't
/// tagged as sequences.
#[inline]
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// The `visit_map` method allows a `Deserialize` type to inform the `Deserializer` that it's
/// expecting a map of values. This allows deserializers to parse sequences that aren't tagged
/// as maps.
#[inline]
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// The `visit_named_unit` method allows a `Deserialize` type to inform the `Deserializer` that
/// it's expecting a named unit. This allows deserializers to a named unit that aren't tagged
/// as a named unit.
#[inline]
fn visit_named_unit<V>(&mut self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// The `visit_named_seq` method allows a `Deserialize` type to inform the `Deserializer` that
/// it's expecting a named sequence of values. This allows deserializers to parse sequences
/// that aren't tagged as sequences.
#[inline]
fn visit_named_seq<V>(&mut self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_seq(visitor)
}
/// The `visit_named_map` method allows a `Deserialize` type to inform the `Deserializer` that
/// it's expecting a map of values. This allows deserializers to parse sequences that aren't
/// tagged as maps.
#[inline]
fn visit_named_map<V>(&mut self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_map(visitor)
}
/// The `visit_enum` method allows a `Deserialize` type to inform the `Deserializer` that it's
/// expecting an enum value. This allows deserializers that provide a custom enumeration
/// serialization to properly deserialize the type.
#[inline]
fn visit_enum<V>(&mut self, _enum: &str, _visitor: V) -> Result<V::Value, Self::Error>
where V: EnumVisitor,
{
Err(Error::syntax_error())
}
/// The `visit_bytes` method allows a `Deserialize` type to inform the `Deserializer` that it's
/// expecting a `Vec<u8>`. This allows deserializers that provide a custom byte vector
/// serialization to properly deserialize the type.
#[inline]
fn visit_bytes<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
}
///////////////////////////////////////////////////////////////////////////////
pub trait Visitor {
type Value;
fn visit_bool<E>(&mut self, _v: bool) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
}
fn visit_isize<E>(&mut self, v: isize) -> Result<Self::Value, E>
where E: Error,
{
self.visit_i64(v as i64)
}
fn visit_i8<E>(&mut self, v: i8) -> Result<Self::Value, E>
where E: Error,
{
self.visit_i64(v as i64)
}
fn visit_i16<E>(&mut self, v: i16) -> Result<Self::Value, E>
where E: Error,
{
self.visit_i64(v as i64)
}
fn visit_i32<E>(&mut self, v: i32) -> Result<Self::Value, E>
where E: Error,
{
self.visit_i64(v as i64)
}
fn visit_i64<E>(&mut self, _v: i64) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
}
fn visit_usize<E>(&mut self, v: usize) -> Result<Self::Value, E>
where E: Error,
{
self.visit_u64(v as u64)
}
fn visit_u8<E>(&mut self, v: u8) -> Result<Self::Value, E>
where E: Error,
{
self.visit_u64(v as u64)
}
fn visit_u16<E>(&mut self, v: u16) -> Result<Self::Value, E>
where E: Error,
{
self.visit_u64(v as u64)
}
fn visit_u32<E>(&mut self, v: u32) -> Result<Self::Value, E>
where E: Error,
{
self.visit_u64(v as u64)
}
fn visit_u64<E>(&mut self, _v: u64) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
}
fn visit_f32<E>(&mut self, v: f32) -> Result<Self::Value, E>
where E: Error,
{
self.visit_f64(v as f64)
}
fn visit_f64<E>(&mut self, _v: f64) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
}
#[inline]
fn visit_char<E>(&mut self, v: char) -> Result<Self::Value, E>
where E: Error,
{
// FIXME: this allocation is required in order to be compatible with stable rust, which
// doesn't support encoding a `char` into a stack buffer.
self.visit_string(v.to_string())
}
fn visit_str<E>(&mut self, _v: &str) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
}
#[inline]
fn visit_string<E>(&mut self, v: String) -> Result<Self::Value, E>
where E: Error,
{
self.visit_str(&v)
}
fn visit_unit<E>(&mut self) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
}
#[inline]
fn visit_named_unit<E>(&mut self, _name: &str) -> Result<Self::Value, E>
where E: Error,
{
self.visit_unit()
}
fn visit_none<E>(&mut self) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
}
fn visit_some<D>(&mut self, _deserializer: &mut D) -> Result<Self::Value, D::Error>
where D: Deserializer,
{
Err(Error::syntax_error())
}
fn visit_seq<V>(&mut self, _visitor: V) -> Result<Self::Value, V::Error>
where V: SeqVisitor,
{
Err(Error::syntax_error())
}
fn visit_map<V>(&mut self, _visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor,
{
Err(Error::syntax_error())
}
fn visit_bytes<E>(&mut self, _v: &[u8]) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
}
fn visit_byte_buf<E>(&mut self, _v: Vec<u8>) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
}
}
///////////////////////////////////////////////////////////////////////////////
pub trait SeqVisitor {
type Error: Error;
fn visit<T>(&mut self) -> Result<Option<T>, Self::Error>
where T: Deserialize;
fn end(&mut self) -> Result<(), Self::Error>;
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
impl<'a, V> SeqVisitor for &'a mut V where V: SeqVisitor {
type Error = V::Error;
#[inline]
fn visit<T>(&mut self) -> Result<Option<T>, V::Error>
where T: Deserialize
{
(**self).visit()
}
#[inline]
fn end(&mut self) -> Result<(), V::Error> {
(**self).end()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(**self).size_hint()
}
}
///////////////////////////////////////////////////////////////////////////////
pub trait MapVisitor {
type Error: Error;
#[inline]
fn visit<K, V>(&mut self) -> Result<Option<(K, V)>, Self::Error>
where K: Deserialize,
V: Deserialize,
{
match try!(self.visit_key()) {
Some(key) => {
let value = try!(self.visit_value());
Ok(Some((key, value)))
}
None => Ok(None)
}
}
fn visit_key<K>(&mut self) -> Result<Option<K>, Self::Error>
where K: Deserialize;
fn visit_value<V>(&mut self) -> Result<V, Self::Error>
where V: Deserialize;
fn end(&mut self) -> Result<(), Self::Error>;
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
fn missing_field<V>(&mut self, field: &'static str) -> Result<V, Self::Error>
where V: Deserialize,
{
Err(Error::missing_field_error(field))
}
}
impl<'a, V_> MapVisitor for &'a mut V_ where V_: MapVisitor {
type Error = V_::Error;
#[inline]
fn visit<K, V>(&mut self) -> Result<Option<(K, V)>, V_::Error>
where K: Deserialize,
V: Deserialize,
{
(**self).visit()
}
#[inline]
fn visit_key<K>(&mut self) -> Result<Option<K>, V_::Error>
where K: Deserialize
{
(**self).visit_key()
}
#[inline]
fn visit_value<V>(&mut self) -> Result<V, V_::Error>
where V: Deserialize
{
(**self).visit_value()
}
#[inline]
fn end(&mut self) -> Result<(), V_::Error> {
(**self).end()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(**self).size_hint()
}
}
///////////////////////////////////////////////////////////////////////////////
/// `EnumVisitor` is a visitor that is created by the `Deserialize` and passed to the
/// `Deserializer` in order to deserialize enums.
pub trait EnumVisitor {
type Value;
fn visit<V>(&mut self, visitor: V) -> Result<Self::Value, V::Error>
where V: VariantVisitor;
}
///////////////////////////////////////////////////////////////////////////////
/// `VariantVisitor` is a visitor that is created by the `Deserializer` and passed to the
/// `Deserialize` in order to deserialize a specific enum variant.
pub trait VariantVisitor {
type Error: Error;
/// `visit_variant` is called to identify which variant to deserialize.
fn visit_variant<V>(&mut self) -> Result<V, Self::Error>
where V: Deserialize;
/// `visit_unit` is called when deserializing a variant with no values.
fn visit_unit(&mut self) -> Result<(), Self::Error> {
Err(Error::syntax_error())
}
/// `visit_seq` is called when deserializing a tuple-like variant.
fn visit_seq<V>(&mut self, _visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
Err(Error::syntax_error())
}
/// `visit_map` is called when deserializing a struct-like variant.
fn visit_map<V>(&mut self, _visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
Err(Error::syntax_error())
}
}
impl<'a, T> VariantVisitor for &'a mut T where T: VariantVisitor {
type Error = T::Error;
fn visit_variant<V>(&mut self) -> Result<V, T::Error>
where V: Deserialize
{
(**self).visit_variant()
}
fn visit_unit(&mut self) -> Result<(), T::Error> {
(**self).visit_unit()
}
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, T::Error>
where V: Visitor,
{
(**self).visit_seq(visitor)
}
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, T::Error>
where V: Visitor,
{
(**self).visit_map(visitor)
}
}
///////////////////////////////////////////////////////////////////////////////
pub trait EnumSeqVisitor {
type Value;
fn visit<V>(&mut self, visitor: V) -> Result<Self::Value, V::Error>
where V: SeqVisitor;
}
///////////////////////////////////////////////////////////////////////////////
pub trait EnumMapVisitor {
type Value;
fn visit<V>(&mut self, visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor;
}
-411
View File
@@ -1,411 +0,0 @@
use std::collections::{
BTreeMap,
BTreeSet,
HashMap,
HashSet,
btree_map,
btree_set,
hash_map,
hash_set,
};
use std::hash::Hash;
use std::vec;
use de;
///////////////////////////////////////////////////////////////////////////////
pub enum Error {
SyntaxError,
EndOfStreamError,
UnknownFieldError(String),
MissingFieldError(&'static str),
}
impl de::Error for Error {
fn syntax_error() -> Self { Error::SyntaxError }
fn end_of_stream_error() -> Self { Error::EndOfStreamError }
fn unknown_field_error(field: &str) -> Self { Error::UnknownFieldError(field.to_string()) }
fn missing_field_error(field: &'static str) -> Self { Error::MissingFieldError(field) }
}
///////////////////////////////////////////////////////////////////////////////
pub trait ValueDeserializer {
type Deserializer: de::Deserializer<Error=Error>;
fn into_deserializer(self) -> Self::Deserializer;
}
///////////////////////////////////////////////////////////////////////////////
impl ValueDeserializer for () {
type Deserializer = UnitDeserializer;
fn into_deserializer(self) -> UnitDeserializer {
UnitDeserializer
}
}
/// A helper deserializer that deserializes a `()`.
pub struct UnitDeserializer;
impl de::Deserializer for UnitDeserializer {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_unit()
}
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_none()
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! primitive_deserializer {
($ty:ty, $name:ident, $method:ident) => {
pub struct $name(Option<$ty>);
impl ValueDeserializer for $ty {
type Deserializer = $name;
fn into_deserializer(self) -> $name {
$name(Some(self))
}
}
impl de::Deserializer for $name {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.0.take() {
Some(v) => visitor.$method(v),
None => Err(de::Error::end_of_stream_error()),
}
}
}
}
}
primitive_deserializer!(bool, BoolDeserializer, visit_bool);
primitive_deserializer!(i8, I8Deserializer, visit_i8);
primitive_deserializer!(i16, I16Deserializer, visit_i16);
primitive_deserializer!(i32, I32Deserializer, visit_i32);
primitive_deserializer!(i64, I64Deserializer, visit_i64);
primitive_deserializer!(isize, IsizeDeserializer, visit_isize);
primitive_deserializer!(u8, U8Deserializer, visit_u8);
primitive_deserializer!(u16, U16Deserializer, visit_u16);
primitive_deserializer!(u32, U32Deserializer, visit_u32);
primitive_deserializer!(u64, U64Deserializer, visit_u64);
primitive_deserializer!(usize, UsizeDeserializer, visit_usize);
primitive_deserializer!(f32, F32Deserializer, visit_f32);
primitive_deserializer!(f64, F64Deserializer, visit_f64);
primitive_deserializer!(char, CharDeserializer, visit_char);
///////////////////////////////////////////////////////////////////////////////
/// A helper deserializer that deserializes a `&str`.
pub struct StrDeserializer<'a>(Option<&'a str>);
impl<'a> ValueDeserializer for &'a str {
type Deserializer = StrDeserializer<'a>;
fn into_deserializer(self) -> StrDeserializer<'a> {
StrDeserializer(Some(self))
}
}
impl<'a> de::Deserializer for StrDeserializer<'a> {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.0.take() {
Some(v) => visitor.visit_str(v),
None => Err(de::Error::end_of_stream_error()),
}
}
fn visit_enum<V>(&mut self, _name: &str, mut visitor: V) -> Result<V::Value, Error>
where V: de::EnumVisitor,
{
visitor.visit(self)
}
}
impl<'a> de::VariantVisitor for StrDeserializer<'a> {
type Error = Error;
fn visit_variant<T>(&mut self) -> Result<T, Error>
where T: de::Deserialize,
{
de::Deserialize::deserialize(self)
}
fn visit_unit(&mut self) -> Result<(), Error> {
Ok(())
}
}
///////////////////////////////////////////////////////////////////////////////
/// A helper deserializer that deserializes a `String`.
pub struct StringDeserializer(Option<String>);
impl ValueDeserializer for String {
type Deserializer = StringDeserializer;
fn into_deserializer(self) -> StringDeserializer {
StringDeserializer(Some(self))
}
}
impl de::Deserializer for StringDeserializer {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.0.take() {
Some(string) => visitor.visit_string(string),
None => Err(de::Error::end_of_stream_error()),
}
}
fn visit_enum<V>(&mut self, _name: &str, mut visitor: V) -> Result<V::Value, Error>
where V: de::EnumVisitor,
{
visitor.visit(self)
}
}
impl<'a> de::VariantVisitor for StringDeserializer {
type Error = Error;
fn visit_variant<T>(&mut self) -> Result<T, Error>
where T: de::Deserialize,
{
de::Deserialize::deserialize(self)
}
fn visit_unit(&mut self) -> Result<(), Error> {
Ok(())
}
}
///////////////////////////////////////////////////////////////////////////////
pub struct SeqDeserializer<I> {
iter: I,
len: usize,
}
impl<I> SeqDeserializer<I> {
pub fn new(iter: I, len: usize) -> Self {
SeqDeserializer {
iter: iter,
len: len,
}
}
}
impl<I, T> de::Deserializer for SeqDeserializer<I>
where I: Iterator<Item=T>,
T: ValueDeserializer,
{
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_seq(self)
}
}
impl<I, T> de::SeqVisitor for SeqDeserializer<I>
where I: Iterator<Item=T>,
T: ValueDeserializer,
{
type Error = Error;
fn visit<V>(&mut self) -> Result<Option<V>, Error>
where V: de::Deserialize
{
match self.iter.next() {
Some(value) => {
self.len -= 1;
let mut de = value.into_deserializer();
Ok(Some(try!(de::Deserialize::deserialize(&mut de))))
}
None => Ok(None),
}
}
fn end(&mut self) -> Result<(), Error> {
if self.len == 0 {
Ok(())
} else {
Err(de::Error::end_of_stream_error())
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
///////////////////////////////////////////////////////////////////////////////
impl<T> ValueDeserializer for Vec<T>
where T: ValueDeserializer,
{
type Deserializer = SeqDeserializer<vec::IntoIter<T>>;
fn into_deserializer(self) -> SeqDeserializer<vec::IntoIter<T>> {
let len = self.len();
SeqDeserializer::new(self.into_iter(), len)
}
}
impl<T> ValueDeserializer for BTreeSet<T>
where T: ValueDeserializer + Eq + Ord,
{
type Deserializer = SeqDeserializer<btree_set::IntoIter<T>>;
fn into_deserializer(self) -> SeqDeserializer<btree_set::IntoIter<T>> {
let len = self.len();
SeqDeserializer::new(self.into_iter(), len)
}
}
impl<T> ValueDeserializer for HashSet<T>
where T: ValueDeserializer + Eq + Hash,
{
type Deserializer = SeqDeserializer<hash_set::IntoIter<T>>;
fn into_deserializer(self) -> SeqDeserializer<hash_set::IntoIter<T>> {
let len = self.len();
SeqDeserializer::new(self.into_iter(), len)
}
}
///////////////////////////////////////////////////////////////////////////////
pub struct MapDeserializer<I, K, V>
where I: Iterator<Item=(K, V)>,
K: ValueDeserializer,
V: ValueDeserializer,
{
iter: I,
value: Option<V>,
len: usize,
}
impl<I, K, V> MapDeserializer<I, K, V>
where I: Iterator<Item=(K, V)>,
K: ValueDeserializer,
V: ValueDeserializer,
{
pub fn new(iter: I, len: usize) -> Self {
MapDeserializer {
iter: iter,
value: None,
len: len,
}
}
}
impl<I, K, V> de::Deserializer for MapDeserializer<I, K, V>
where I: Iterator<Item=(K, V)>,
K: ValueDeserializer,
V: ValueDeserializer,
{
type Error = Error;
fn visit<V_>(&mut self, mut visitor: V_) -> Result<V_::Value, Error>
where V_: de::Visitor,
{
visitor.visit_map(self)
}
}
impl<I, K, V> de::MapVisitor for MapDeserializer<I, K, V>
where I: Iterator<Item=(K, V)>,
K: ValueDeserializer,
V: ValueDeserializer,
{
type Error = Error;
fn visit_key<T>(&mut self) -> Result<Option<T>, Error>
where T: de::Deserialize,
{
match self.iter.next() {
Some((key, value)) => {
self.len -= 1;
self.value = Some(value);
let mut de = key.into_deserializer();
Ok(Some(try!(de::Deserialize::deserialize(&mut de))))
}
None => Ok(None),
}
}
fn visit_value<T>(&mut self) -> Result<T, Error>
where T: de::Deserialize,
{
match self.value.take() {
Some(value) => {
let mut de = value.into_deserializer();
de::Deserialize::deserialize(&mut de)
}
None => Err(de::Error::syntax_error())
}
}
fn end(&mut self) -> Result<(), Error> {
if self.len == 0 {
Ok(())
} else {
Err(de::Error::end_of_stream_error())
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
///////////////////////////////////////////////////////////////////////////////
impl<K, V> ValueDeserializer for BTreeMap<K, V>
where K: ValueDeserializer + Eq + Ord,
V: ValueDeserializer,
{
type Deserializer = MapDeserializer<btree_map::IntoIter<K, V>, K, V>;
fn into_deserializer(self) -> MapDeserializer<btree_map::IntoIter<K, V>, K, V> {
let len = self.len();
MapDeserializer::new(self.into_iter(), len)
}
}
impl<K, V> ValueDeserializer for HashMap<K, V>
where K: ValueDeserializer + Eq + Hash,
V: ValueDeserializer,
{
type Deserializer = MapDeserializer<hash_map::IntoIter<K, V>, K, V>;
fn into_deserializer(self) -> MapDeserializer<hash_map::IntoIter<K, V>, K, V> {
let len = self.len();
MapDeserializer::new(self.into_iter(), len)
}
}
-51
View File
@@ -1,51 +0,0 @@
use std::io;
pub struct LineColIterator<Iter: Iterator<Item=io::Result<u8>>> {
iter: Iter,
line: usize,
col: usize,
}
impl<Iter: Iterator<Item=io::Result<u8>>> LineColIterator<Iter> {
pub fn new(iter: Iter) -> LineColIterator<Iter> {
LineColIterator {
iter: iter,
line: 1,
col: 0,
}
}
/// Report the current line inside the iterator.
pub fn line(&self) -> usize { self.line }
/// Report the current column inside the iterator.
pub fn col(&self) -> usize { self.col }
/// Gets a reference to the underlying iterator.
pub fn get_ref(&self) -> &Iter { &self.iter }
/// Gets a mutable reference to the underlying iterator.
pub fn get_mut(&self) -> &Iter { &self.iter }
/// Unwraps this `LineColIterator`, returning the underlying iterator.
pub fn into_inner(self) -> Iter { self.iter }
}
impl<Iter: Iterator<Item=io::Result<u8>>> Iterator for LineColIterator<Iter> {
type Item = io::Result<u8>;
fn next(&mut self) -> Option<io::Result<u8>> {
match self.iter.next() {
None => None,
Some(Ok(b'\n')) => {
self.line += 1;
self.col = 0;
Some(Ok(b'\n'))
},
Some(Ok(c)) => {
self.col += 1;
Some(Ok(c))
},
Some(Err(e)) => Some(Err(e)),
}
}
}
-84
View File
@@ -1,84 +0,0 @@
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::collections::BTreeMap;
use ser::{self, Serialize};
use json::value::{self, Value};
pub struct ArrayBuilder {
array: Vec<Value>,
}
impl ArrayBuilder {
pub fn new() -> ArrayBuilder {
ArrayBuilder { array: Vec::new() }
}
pub fn unwrap(self) -> Value {
Value::Array(self.array)
}
pub fn push<T: ser::Serialize>(mut self, v: T) -> ArrayBuilder {
self.array.push(value::to_value(&v));
self
}
pub fn push_array<F>(mut self, f: F) -> ArrayBuilder where
F: FnOnce(ArrayBuilder) -> ArrayBuilder
{
let builder = ArrayBuilder::new();
self.array.push(f(builder).unwrap());
self
}
pub fn push_object<F>(mut self, f: F) -> ArrayBuilder where
F: FnOnce(ObjectBuilder) -> ObjectBuilder
{
let builder = ObjectBuilder::new();
self.array.push(f(builder).unwrap());
self
}
}
pub struct ObjectBuilder {
object: BTreeMap<String, Value>,
}
impl ObjectBuilder {
pub fn new() -> ObjectBuilder {
ObjectBuilder { object: BTreeMap::new() }
}
pub fn unwrap(self) -> Value {
Value::Object(self.object)
}
pub fn insert<V: ser::Serialize>(mut self, k: String, v: V) -> ObjectBuilder {
self.object.insert(k, value::to_value(&v));
self
}
pub fn insert_array<F>(mut self, key: String, f: F) -> ObjectBuilder where
F: FnOnce(ArrayBuilder) -> ArrayBuilder
{
let builder = ArrayBuilder::new();
self.object.insert(key, f(builder).unwrap());
self
}
pub fn insert_object<F>(mut self, key: String, f: F) -> ObjectBuilder where
F: FnOnce(ObjectBuilder) -> ObjectBuilder
{
let builder = ObjectBuilder::new();
self.object.insert(key, f(builder).unwrap());
self
}
}
-675
View File
@@ -1,675 +0,0 @@
use std::char;
use std::io;
use std::str;
use de;
use iter::LineColIterator;
use super::error::{Error, ErrorCode};
pub struct Deserializer<Iter: Iterator<Item=io::Result<u8>>> {
rdr: LineColIterator<Iter>,
ch: Option<u8>,
str_buf: Vec<u8>,
}
impl<Iter> Deserializer<Iter>
where Iter: Iterator<Item=io::Result<u8>>,
{
/// Creates the JSON parser from an `std::iter::Iterator`.
#[inline]
pub fn new(rdr: Iter) -> Result<Deserializer<Iter>, Error> {
let mut deserializer = Deserializer {
rdr: LineColIterator::new(rdr),
ch: None,
str_buf: Vec::with_capacity(128),
};
try!(deserializer.bump());
Ok(deserializer)
}
#[inline]
pub fn end(&mut self) -> Result<(), Error> {
try!(self.parse_whitespace());
if self.eof() {
Ok(())
} else {
Err(self.error(ErrorCode::TrailingCharacters))
}
}
fn eof(&self) -> bool { self.ch.is_none() }
fn ch_or_null(&self) -> u8 { self.ch.unwrap_or(b'\x00') }
fn bump(&mut self) -> Result<(), Error> {
self.ch = match self.rdr.next() {
Some(Err(err)) => { return Err(Error::IoError(err)); }
Some(Ok(ch)) => Some(ch),
None => None,
};
Ok(())
}
fn next_char(&mut self) -> Result<Option<u8>, Error> {
try!(self.bump());
Ok(self.ch)
}
fn ch_is(&self, c: u8) -> bool {
self.ch == Some(c)
}
fn error(&mut self, reason: ErrorCode) -> Error {
Error::SyntaxError(reason, self.rdr.line(), self.rdr.col())
}
fn parse_whitespace(&mut self) -> Result<(), Error> {
while self.ch_is(b' ') ||
self.ch_is(b'\n') ||
self.ch_is(b'\t') ||
self.ch_is(b'\r') { try!(self.bump()); }
Ok(())
}
fn parse_value<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
try!(self.parse_whitespace());
if self.eof() {
return Err(self.error(ErrorCode::EOFWhileParsingValue));
}
let value = match self.ch_or_null() {
b'n' => {
try!(self.parse_ident(b"ull"));
visitor.visit_unit()
}
b't' => {
try!(self.parse_ident(b"rue"));
visitor.visit_bool(true)
}
b'f' => {
try!(self.parse_ident(b"alse"));
visitor.visit_bool(false)
}
b'0' ... b'9' | b'-' => self.parse_number(visitor),
b'"' => {
try!(self.parse_string());
let s = str::from_utf8(&self.str_buf).unwrap();
visitor.visit_str(s)
}
b'[' => {
try!(self.bump());
visitor.visit_seq(SeqVisitor::new(self))
}
b'{' => {
try!(self.bump());
visitor.visit_map(MapVisitor::new(self))
}
_ => {
Err(self.error(ErrorCode::ExpectedSomeValue))
}
};
match value {
Ok(value) => Ok(value),
Err(Error::SyntaxError(code, _, _)) => Err(self.error(code)),
Err(err) => Err(err),
}
}
fn parse_ident(&mut self, ident: &[u8]) -> Result<(), Error> {
for c in ident {
if Some(*c) != try!(self.next_char()) {
return Err(self.error(ErrorCode::ExpectedSomeIdent));
}
}
try!(self.bump());
Ok(())
}
fn parse_number<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
let mut neg = false;
if self.ch_is(b'-') {
try!(self.bump());
neg = true;
}
let res = try!(self.parse_integer());
if self.ch_is(b'.') || self.ch_is(b'e') || self.ch_is(b'E') {
let mut res = res as f64;
if self.ch_is(b'.') {
res = try!(self.parse_decimal(res));
}
if self.ch_is(b'e') || self.ch_is(b'E') {
res = try!(self.parse_exponent(res));
}
if neg {
visitor.visit_f64(-res)
} else {
visitor.visit_f64(res)
}
} else {
if neg {
let res = -(res as i64);
// Make sure we didn't underflow.
if res > 0 {
Err(self.error(ErrorCode::InvalidNumber))
} else {
visitor.visit_i64(res)
}
} else {
visitor.visit_u64(res)
}
}
}
fn parse_integer(&mut self) -> Result<u64, Error> {
let mut res = 0;
match self.ch_or_null() {
b'0' => {
try!(self.bump());
// There can be only one leading '0'.
match self.ch_or_null() {
b'0' ... b'9' => {
return Err(self.error(ErrorCode::InvalidNumber));
}
_ => ()
}
},
b'1' ... b'9' => {
while !self.eof() {
match self.ch_or_null() {
c @ b'0' ... b'9' => {
res *= 10;
res += (c as u64) - (b'0' as u64);
try!(self.bump());
}
_ => break,
}
}
}
_ => { return Err(self.error(ErrorCode::InvalidNumber)); }
}
Ok(res)
}
fn parse_decimal(&mut self, res: f64) -> Result<f64, Error> {
try!(self.bump());
// Make sure a digit follows the decimal place.
match self.ch_or_null() {
b'0' ... b'9' => (),
_ => { return Err(self.error(ErrorCode::InvalidNumber)); }
}
let mut res = res;
let mut dec = 1.0;
while !self.eof() {
match self.ch_or_null() {
c @ b'0' ... b'9' => {
dec /= 10.0;
res += (((c as u64) - (b'0' as u64)) as f64) * dec;
try!(self.bump());
}
_ => break,
}
}
Ok(res)
}
fn parse_exponent(&mut self, mut res: f64) -> Result<f64, Error> {
try!(self.bump());
let mut exp = 0;
let mut neg_exp = false;
if self.ch_is(b'+') {
try!(self.bump());
} else if self.ch_is(b'-') {
try!(self.bump());
neg_exp = true;
}
// Make sure a digit follows the exponent place.
match self.ch_or_null() {
b'0' ... b'9' => (),
_ => { return Err(self.error(ErrorCode::InvalidNumber)); }
}
while !self.eof() {
match self.ch_or_null() {
c @ b'0' ... b'9' => {
exp *= 10;
exp += (c as i32) - (b'0' as i32);
try!(self.bump());
}
_ => break
}
}
let exp: f64 = 10_f64.powi(exp);
if neg_exp {
res /= exp;
} else {
res *= exp;
}
Ok(res)
}
fn decode_hex_escape(&mut self) -> Result<u16, Error> {
let mut i = 0;
let mut n = 0u16;
while i < 4 && !self.eof() {
try!(self.bump());
n = match self.ch_or_null() {
c @ b'0' ... b'9' => n * 16_u16 + ((c as u16) - (b'0' as u16)),
b'a' | b'A' => n * 16_u16 + 10_u16,
b'b' | b'B' => n * 16_u16 + 11_u16,
b'c' | b'C' => n * 16_u16 + 12_u16,
b'd' | b'D' => n * 16_u16 + 13_u16,
b'e' | b'E' => n * 16_u16 + 14_u16,
b'f' | b'F' => n * 16_u16 + 15_u16,
_ => { return Err(self.error(ErrorCode::InvalidEscape)); }
};
i += 1;
}
// Error out if we didn't parse 4 digits.
if i != 4 {
return Err(self.error(ErrorCode::InvalidEscape));
}
Ok(n)
}
fn parse_string(&mut self) -> Result<(), Error> {
self.str_buf.clear();
let mut escape = false;
loop {
let ch = match try!(self.next_char()) {
Some(ch) => ch,
None => { return Err(self.error(ErrorCode::EOFWhileParsingString)); }
};
if escape {
match ch {
b'"' => self.str_buf.push(b'"'),
b'\\' => self.str_buf.push(b'\\'),
b'/' => self.str_buf.push(b'/'),
b'b' => self.str_buf.push(b'\x08'),
b'f' => self.str_buf.push(b'\x0c'),
b'n' => self.str_buf.push(b'\n'),
b'r' => self.str_buf.push(b'\r'),
b't' => self.str_buf.push(b'\t'),
b'u' => {
let c = match try!(self.decode_hex_escape()) {
0xDC00 ... 0xDFFF => {
return Err(self.error(ErrorCode::LoneLeadingSurrogateInHexEscape));
}
// Non-BMP characters are encoded as a sequence of
// two hex escapes, representing UTF-16 surrogates.
n1 @ 0xD800 ... 0xDBFF => {
match (try!(self.next_char()), try!(self.next_char())) {
(Some(b'\\'), Some(b'u')) => (),
_ => {
return Err(self.error(ErrorCode::UnexpectedEndOfHexEscape));
}
}
let n2 = try!(self.decode_hex_escape());
if n2 < 0xDC00 || n2 > 0xDFFF {
return Err(self.error(ErrorCode::LoneLeadingSurrogateInHexEscape));
}
let n = (((n1 - 0xD800) as u32) << 10 |
(n2 - 0xDC00) as u32) + 0x1_0000;
match char::from_u32(n as u32) {
Some(c) => c,
None => {
return Err(self.error(ErrorCode::InvalidUnicodeCodePoint));
}
}
}
n => {
match char::from_u32(n as u32) {
Some(c) => c,
None => {
return Err(self.error(ErrorCode::InvalidUnicodeCodePoint));
}
}
}
};
// FIXME: this allocation is required in order to be compatible with stable
// rust, which doesn't support encoding a `char` into a stack buffer.
let buf = c.to_string();
self.str_buf.extend(buf.bytes());
}
_ => {
return Err(self.error(ErrorCode::InvalidEscape));
}
}
escape = false;
} else {
match ch {
b'"' => {
try!(self.bump());
return Ok(());
}
b'\\' => {
escape = true;
}
ch => {
self.str_buf.push(ch);
}
}
}
}
}
fn parse_object_colon(&mut self) -> Result<(), Error> {
try!(self.parse_whitespace());
if self.ch_is(b':') {
try!(self.bump());
Ok(())
} else if self.eof() {
Err(self.error(ErrorCode::EOFWhileParsingObject))
} else {
Err(self.error(ErrorCode::ExpectedColon))
}
}
}
impl<Iter> de::Deserializer for Deserializer<Iter>
where Iter: Iterator<Item=io::Result<u8>>,
{
type Error = Error;
#[inline]
fn visit<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
self.parse_value(visitor)
}
#[inline]
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
try!(self.parse_whitespace());
if self.eof() {
return Err(self.error(ErrorCode::EOFWhileParsingValue));
}
if self.ch_is(b'n') {
try!(self.parse_ident(b"ull"));
visitor.visit_none()
} else {
visitor.visit_some(self)
}
}
#[inline]
fn visit_enum<V>(&mut self, _name: &str, mut visitor: V) -> Result<V::Value, Error>
where V: de::EnumVisitor,
{
try!(self.parse_whitespace());
if self.ch_is(b'{') {
try!(self.bump());
try!(self.parse_whitespace());
let value = {
try!(visitor.visit(&mut *self))
};
try!(self.parse_whitespace());
if self.ch_is(b'}') {
try!(self.bump());
Ok(value)
} else {
Err(self.error(ErrorCode::ExpectedSomeValue))
}
} else {
Err(self.error(ErrorCode::ExpectedSomeValue))
}
}
}
struct SeqVisitor<'a, Iter: 'a + Iterator<Item=io::Result<u8>>> {
de: &'a mut Deserializer<Iter>,
first: bool,
}
impl<'a, Iter: Iterator<Item=io::Result<u8>>> SeqVisitor<'a, Iter> {
fn new(de: &'a mut Deserializer<Iter>) -> Self {
SeqVisitor {
de: de,
first: true,
}
}
}
impl<'a, Iter> de::SeqVisitor for SeqVisitor<'a, Iter>
where Iter: Iterator<Item=io::Result<u8>>,
{
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: de::Deserialize,
{
try!(self.de.parse_whitespace());
if self.de.ch_is(b']') {
return Ok(None);
}
if self.first {
self.first = false;
} else {
if self.de.ch_is(b',') {
try!(self.de.bump());
} else if self.de.eof() {
return Err(self.de.error(ErrorCode::EOFWhileParsingList));
} else {
return Err(self.de.error(ErrorCode::ExpectedListCommaOrEnd));
}
}
let value = try!(de::Deserialize::deserialize(self.de));
Ok(Some(value))
}
fn end(&mut self) -> Result<(), Error> {
try!(self.de.parse_whitespace());
if self.de.ch_is(b']') {
self.de.bump()
} else if self.de.eof() {
Err(self.de.error(ErrorCode::EOFWhileParsingList))
} else {
Err(self.de.error(ErrorCode::TrailingCharacters))
}
}
}
struct MapVisitor<'a, Iter: 'a + Iterator<Item=io::Result<u8>>> {
de: &'a mut Deserializer<Iter>,
first: bool,
}
impl<'a, Iter: Iterator<Item=io::Result<u8>>> MapVisitor<'a, Iter> {
fn new(de: &'a mut Deserializer<Iter>) -> Self {
MapVisitor {
de: de,
first: true,
}
}
}
impl<'a, Iter> de::MapVisitor for MapVisitor<'a, Iter>
where Iter: Iterator<Item=io::Result<u8>>
{
type Error = Error;
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
where K: de::Deserialize,
{
try!(self.de.parse_whitespace());
if self.de.ch_is(b'}') {
return Ok(None);
}
if self.first {
self.first = false;
} else {
if self.de.ch_is(b',') {
try!(self.de.bump());
try!(self.de.parse_whitespace());
} else if self.de.eof() {
return Err(self.de.error(ErrorCode::EOFWhileParsingObject));
} else {
return Err(self.de.error(ErrorCode::ExpectedObjectCommaOrEnd));
}
}
if self.de.eof() {
return Err(self.de.error(ErrorCode::EOFWhileParsingValue));
}
if !self.de.ch_is(b'"') {
return Err(self.de.error(ErrorCode::KeyMustBeAString));
}
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
fn visit_value<V>(&mut self) -> Result<V, Error>
where V: de::Deserialize,
{
try!(self.de.parse_object_colon());
Ok(try!(de::Deserialize::deserialize(self.de)))
}
fn end(&mut self) -> Result<(), Error> {
try!(self.de.parse_whitespace());
if self.de.ch_is(b'}') {
try!(self.de.bump());
Ok(())
} else if self.de.eof() {
Err(self.de.error(ErrorCode::EOFWhileParsingObject))
} else {
Err(self.de.error(ErrorCode::TrailingCharacters))
}
}
fn missing_field<V>(&mut self, _field: &'static str) -> Result<V, Error>
where V: de::Deserialize,
{
let mut de = de::value::ValueDeserializer::into_deserializer(());
Ok(try!(de::Deserialize::deserialize(&mut de)))
}
}
impl<Iter> de::VariantVisitor for Deserializer<Iter>
where Iter: Iterator<Item=io::Result<u8>>,
{
type Error = Error;
fn visit_variant<V>(&mut self) -> Result<V, Error>
where V: de::Deserialize
{
de::Deserialize::deserialize(self)
}
fn visit_unit(&mut self) -> Result<(), Error> {
try!(self.parse_object_colon());
de::Deserialize::deserialize(self)
}
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
try!(self.parse_object_colon());
de::Deserializer::visit(self, visitor)
}
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
try!(self.parse_object_colon());
de::Deserializer::visit(self, visitor)
}
}
/// Decodes a json value from a `std::io::Read`.
pub fn from_iter<I, T>(iter: I) -> Result<T, Error>
where I: Iterator<Item=io::Result<u8>>,
T: de::Deserialize,
{
let mut de = try!(Deserializer::new(iter));
let value = try!(de::Deserialize::deserialize(&mut de));
// Make sure the whole stream has been consumed.
try!(de.end());
Ok(value)
}
/// Decodes a json value from a `std::io::Read`.
pub fn from_reader<R, T>(rdr: R) -> Result<T, Error>
where R: io::Read,
T: de::Deserialize,
{
from_iter(rdr.bytes())
}
/// Decodes a json value from a `&str`.
pub fn from_slice<T>(v: &[u8]) -> Result<T, Error>
where T: de::Deserialize
{
from_iter(v.iter().map(|byte| Ok(*byte)))
}
/// Decodes a json value from a `&str`.
pub fn from_str<T>(s: &str) -> Result<T, Error>
where T: de::Deserialize
{
from_slice(s.as_bytes())
}
-185
View File
@@ -1,185 +0,0 @@
use std::error;
use std::fmt;
use std::io;
use de;
/// The errors that can arise while parsing a JSON stream.
#[derive(Clone, PartialEq)]
pub enum ErrorCode {
EOFWhileParsingList,
EOFWhileParsingObject,
EOFWhileParsingString,
EOFWhileParsingValue,
ExpectedColon,
ExpectedConversion,
ExpectedEnumEnd,
ExpectedEnumEndToken,
ExpectedEnumMapStart,
ExpectedEnumToken,
ExpectedEnumVariantString,
ExpectedListCommaOrEnd,
ExpectedName,
ExpectedObjectCommaOrEnd,
ExpectedSomeIdent,
ExpectedSomeValue,
InvalidEscape,
InvalidNumber,
InvalidUnicodeCodePoint,
KeyMustBeAString,
LoneLeadingSurrogateInHexEscape,
UnknownField(String),
MissingField(&'static str),
NotFourDigit,
NotUtf8,
TrailingCharacters,
UnexpectedEndOfHexEscape,
UnknownVariant,
UnrecognizedHex,
}
impl fmt::Debug for ErrorCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use std::fmt::Debug;
match *self {
//ErrorCode::ConversionError(ref token) => write!(f, "failed to convert {}", token),
ErrorCode::EOFWhileParsingList => "EOF While parsing list".fmt(f),
ErrorCode::EOFWhileParsingObject => "EOF While parsing object".fmt(f),
ErrorCode::EOFWhileParsingString => "EOF While parsing string".fmt(f),
ErrorCode::EOFWhileParsingValue => "EOF While parsing value".fmt(f),
ErrorCode::ExpectedColon => "expected `:`".fmt(f),
ErrorCode::ExpectedConversion => "expected conversion".fmt(f),
ErrorCode::ExpectedEnumEnd => "expected enum end".fmt(f),
ErrorCode::ExpectedEnumEndToken => "expected enum map end".fmt(f),
ErrorCode::ExpectedEnumMapStart => "expected enum map start".fmt(f),
ErrorCode::ExpectedEnumToken => "expected enum token".fmt(f),
ErrorCode::ExpectedEnumVariantString => "expected variant".fmt(f),
ErrorCode::ExpectedListCommaOrEnd => "expected `,` or `]`".fmt(f),
ErrorCode::ExpectedName => "expected name".fmt(f),
ErrorCode::ExpectedObjectCommaOrEnd => "expected `,` or `}`".fmt(f),
ErrorCode::ExpectedSomeIdent => "expected ident".fmt(f),
ErrorCode::ExpectedSomeValue => "expected value".fmt(f),
//ErrorCode::ExpectedTokens(ref token, tokens) => write!(f, "expected {}, found {}", tokens, token),
ErrorCode::InvalidEscape => "invalid escape".fmt(f),
ErrorCode::InvalidNumber => "invalid number".fmt(f),
ErrorCode::InvalidUnicodeCodePoint => "invalid unicode code point".fmt(f),
ErrorCode::KeyMustBeAString => "key must be a string".fmt(f),
ErrorCode::LoneLeadingSurrogateInHexEscape => "lone leading surrogate in hex escape".fmt(f),
ErrorCode::UnknownField(ref field) => write!(f, "unknown field \"{}\"", field),
ErrorCode::MissingField(ref field) => write!(f, "missing field \"{}\"", field),
ErrorCode::NotFourDigit => "invalid \\u escape (not four digits)".fmt(f),
ErrorCode::NotUtf8 => "contents not utf-8".fmt(f),
ErrorCode::TrailingCharacters => "trailing characters".fmt(f),
ErrorCode::UnexpectedEndOfHexEscape => "unexpected end of hex escape".fmt(f),
//ErrorCode::UnexpectedName(ref name) => write!(f, "unexpected name {}", name),
ErrorCode::UnknownVariant => "unknown variant".fmt(f),
ErrorCode::UnrecognizedHex => "invalid \\u escape (unrecognized hex)".fmt(f),
}
}
}
#[derive(Debug)]
pub enum Error {
/// msg, line, col
SyntaxError(ErrorCode, usize, usize),
IoError(io::Error),
/*
ExpectedError(String, String),
*/
MissingFieldError(&'static str),
/*
UnknownVariantError(String),
*/
}
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::SyntaxError(..) => "syntax error",
Error::IoError(ref error) => error::Error::description(error),
/*
Error::ExpectedError(ref expected, _) => &expected,
*/
Error::MissingFieldError(_) => "missing field",
/*
Error::UnknownVariantError(_) => "unknown variant",
*/
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
Error::IoError(ref error) => Some(error),
_ => None,
}
}
}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::SyntaxError(ref code, line, col) => {
write!(fmt, "{:?} at line {} column {}", code, line, col)
}
Error::IoError(ref error) => fmt::Display::fmt(error, fmt),
/*
Error::ExpectedError(ref expected, ref found) => {
Some(format!("expected {}, found {}", expected, found))
}
*/
Error::MissingFieldError(ref field) => {
write!(fmt, "missing field {}", field)
}
/*
Error::UnknownVariantError(ref variant) => {
Some(format!("unknown variant {}", variant))
}
*/
}
}
}
impl From<io::Error> for Error {
fn from(error: io::Error) -> Error {
Error::IoError(error)
}
}
impl From<de::value::Error> for Error {
fn from(error: de::value::Error) -> Error {
match error {
de::value::Error::SyntaxError => {
de::Error::syntax_error()
}
de::value::Error::EndOfStreamError => {
de::Error::end_of_stream_error()
}
de::value::Error::UnknownFieldError(field) => {
Error::SyntaxError(ErrorCode::UnknownField(field), 0, 0)
}
de::value::Error::MissingFieldError(field) => {
de::Error::missing_field_error(field)
}
}
}
}
impl de::Error for Error {
fn syntax_error() -> Error {
Error::SyntaxError(ErrorCode::ExpectedSomeValue, 0, 0)
}
fn end_of_stream_error() -> Error {
Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 0, 0)
}
fn unknown_field_error(field: &str) -> Error {
Error::SyntaxError(ErrorCode::UnknownField(field.to_string()), 0, 0)
}
fn missing_field_error(field: &'static str) -> Error {
Error::MissingFieldError(field)
}
}
-113
View File
@@ -1,113 +0,0 @@
//! JSON and serialization
//!
//! # What is JSON?
//!
//! JSON (JavaScript Object Notation) is a way to write data in JavaScript. Like XML, it allows to
//! encode structured data in a text format that can be easily read by humans. Its simple syntax
//! and native compatibility with JavaScript have made it a widely used format.
//!
//! Data types that can be encoded are JavaScript types (see the `serde::json:Value` enum for more
//! details):
//!
//! * `Boolean`: equivalent to rust's `bool`
//! * `I64`: equivalent to rust's `i64`
//! * `U64`: equivalent to rust's `u64`
//! * `F64`: equivalent to rust's `i64`
//! * `String`: equivalent to rust's `String`
//! * `Array`: equivalent to rust's `Vec<T>`, but also allowing objects of different types in the
//! same array
//! * `Object`: equivalent to rust's `BTreeMap<String, serde::json::Value>`
//! * `Null`
//!
//! An object is a series of string keys mapping to values, in `"key": value` format. Arrays are
//! enclosed in square brackets ([ ... ]) and objects in curly brackets ({ ... }). A simple JSON
//! document encoding a person, his/her age, address and phone numbers could look like
//!
//! ```ignore
//! {
//! "FirstName": "John",
//! "LastName": "Doe",
//! "Age": 43,
//! "Address": {
//! "Street": "Downing Street 10",
//! "City": "London",
//! "Country": "Great Britain"
//! },
//! "PhoneNumbers": [
//! "+44 1234567",
//! "+44 2345678"
//! ]
//! }
//! ```
//!
//! # Type-based Serialization and Deserialization
//!
//! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
//! from JSON via the serialization API. To be able to serialize a piece of data, it must implement
//! the `serde::Serialize` trait. To be able to deserialize a piece of data, it must implement the
//! `serde::Deserialize` trait. Serde provides provides an annotation to automatically generate
//! the code for these traits: `#[derive(Serialize, Deserialize)]`.
//!
//! The JSON API also provides an enum `serde::json::Value` and a method `to_value` to serialize
//! objects. A `serde::json::Value` value can be serialized as a string or buffer using the
//! functions described above. You can also use the `json::Serializer` object, which implements the
//! `Serializer` trait.
//!
//! # Examples of use
//!
//! ## Parsing a `str` to `Value` and reading the result
//!
//! ```rust
//! //#![feature(custom_derive, plugin)]
//! //#![plugin(serde_macros)]
//!
//! extern crate serde;
//!
//! use serde::json::{self, Value};
//!
//! fn main() {
//! let data: Value = json::from_str("{\"foo\": 13, \"bar\": \"baz\"}").unwrap();
//! println!("data: {:?}", data);
//! // data: {"bar":"baz","foo":13}
//! println!("object? {}", data.is_object());
//! // object? true
//!
//! let obj = data.as_object().unwrap();
//! let foo = obj.get("foo").unwrap();
//!
//! println!("array? {:?}", foo.as_array());
//! // array? None
//! println!("u64? {:?}", foo.as_u64());
//! // u64? Some(13u64)
//!
//! for (key, value) in obj.iter() {
//! println!("{}: {}", key, match *value {
//! Value::U64(v) => format!("{} (u64)", v),
//! Value::String(ref v) => format!("{} (string)", v),
//! _ => format!("other")
//! });
//! }
//! // bar: baz (string)
//! // foo: 13 (u64)
//! }
//! ```
pub use self::de::{Deserializer, from_str};
pub use self::error::{Error, ErrorCode};
pub use self::ser::{
Serializer,
to_writer,
to_writer_pretty,
to_vec,
to_vec_pretty,
to_string,
to_string_pretty,
escape_str,
};
pub use self::value::{Value, to_value, from_value};
pub mod builder;
pub mod de;
pub mod error;
pub mod ser;
pub mod value;
-519
View File
@@ -1,519 +0,0 @@
use std::io;
use std::num::FpCategory;
use std::string::FromUtf8Error;
use ser;
/// A structure for implementing serialization to JSON.
pub struct Serializer<W, F=CompactFormatter> {
writer: W,
formatter: F,
/// `first` is used to signify if we should print a comma when we are walking through a
/// sequence.
first: bool,
}
impl<W> Serializer<W>
where W: io::Write,
{
/// Creates a new JSON serializer.
#[inline]
pub fn new(writer: W) -> Self {
Serializer::with_formatter(writer, CompactFormatter)
}
}
impl<'a, W> Serializer<W, PrettyFormatter<'a>>
where W: io::Write,
{
/// Creates a new JSON pretty print serializer.
#[inline]
pub fn pretty(writer: W) -> Self {
Serializer::with_formatter(writer, PrettyFormatter::new())
}
}
impl<W, F> Serializer<W, F>
where W: io::Write,
F: Formatter,
{
/// Creates a new JSON visitor whose output will be written to the writer
/// specified.
#[inline]
pub fn with_formatter(writer: W, formatter: F) -> Self {
Serializer {
writer: writer,
formatter: formatter,
first: false,
}
}
/// Unwrap the `Writer` from the `Serializer`.
#[inline]
pub fn into_inner(self) -> W {
self.writer
}
}
impl<W, F> ser::Serializer for Serializer<W, F>
where W: io::Write,
F: Formatter,
{
type Error = io::Error;
#[inline]
fn visit_bool(&mut self, value: bool) -> io::Result<()> {
if value {
self.writer.write_all(b"true")
} else {
self.writer.write_all(b"false")
}
}
#[inline]
fn visit_isize(&mut self, value: isize) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_i8(&mut self, value: i8) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_i16(&mut self, value: i16) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_i32(&mut self, value: i32) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_i64(&mut self, value: i64) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_usize(&mut self, value: usize) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_u8(&mut self, value: u8) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_u16(&mut self, value: u16) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_u32(&mut self, value: u32) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_u64(&mut self, value: u64) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_f32(&mut self, value: f32) -> io::Result<()> {
fmt_f32_or_null(&mut self.writer, value)
}
#[inline]
fn visit_f64(&mut self, value: f64) -> io::Result<()> {
fmt_f64_or_null(&mut self.writer, value)
}
#[inline]
fn visit_char(&mut self, value: char) -> io::Result<()> {
escape_char(&mut self.writer, value)
}
#[inline]
fn visit_str(&mut self, value: &str) -> io::Result<()> {
escape_str(&mut self.writer, value)
}
#[inline]
fn visit_none(&mut self) -> io::Result<()> {
self.visit_unit()
}
#[inline]
fn visit_some<V>(&mut self, value: V) -> io::Result<()>
where V: ser::Serialize
{
value.serialize(self)
}
#[inline]
fn visit_unit(&mut self) -> io::Result<()> {
self.writer.write_all(b"null")
}
#[inline]
fn visit_enum_unit(&mut self, _name: &str, variant: &str) -> io::Result<()> {
try!(self.formatter.open(&mut self.writer, b'{'));
try!(self.formatter.comma(&mut self.writer, true));
try!(self.visit_str(variant));
try!(self.formatter.colon(&mut self.writer));
try!(self.writer.write_all(b"[]"));
self.formatter.close(&mut self.writer, b'}')
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> io::Result<()>
where V: ser::SeqVisitor,
{
match visitor.len() {
Some(len) if len == 0 => {
self.writer.write_all(b"[]")
}
_ => {
try!(self.formatter.open(&mut self.writer, b'['));
self.first = true;
while let Some(()) = try!(visitor.visit(self)) { }
self.formatter.close(&mut self.writer, b']')
}
}
}
#[inline]
fn visit_enum_seq<V>(&mut self, _name: &str, variant: &str, visitor: V) -> io::Result<()>
where V: ser::SeqVisitor,
{
try!(self.formatter.open(&mut self.writer, b'{'));
try!(self.formatter.comma(&mut self.writer, true));
try!(self.visit_str(variant));
try!(self.formatter.colon(&mut self.writer));
try!(self.visit_seq(visitor));
self.formatter.close(&mut self.writer, b'}')
}
#[inline]
fn visit_seq_elt<T>(&mut self, value: T) -> io::Result<()>
where T: ser::Serialize,
{
try!(self.formatter.comma(&mut self.writer, self.first));
self.first = false;
value.serialize(self)
}
#[inline]
fn visit_map<V>(&mut self, mut visitor: V) -> io::Result<()>
where V: ser::MapVisitor,
{
match visitor.len() {
Some(len) if len == 0 => {
self.writer.write_all(b"{}")
}
_ => {
try!(self.formatter.open(&mut self.writer, b'{'));
self.first = true;
while let Some(()) = try!(visitor.visit(self)) { }
self.formatter.close(&mut self.writer, b'}')
}
}
}
#[inline]
fn visit_enum_map<V>(&mut self, _name: &str, variant: &str, visitor: V) -> io::Result<()>
where V: ser::MapVisitor,
{
try!(self.formatter.open(&mut self.writer, b'{'));
try!(self.formatter.comma(&mut self.writer, true));
try!(self.visit_str(variant));
try!(self.formatter.colon(&mut self.writer));
try!(self.visit_map(visitor));
self.formatter.close(&mut self.writer, b'}')
}
#[inline]
fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> io::Result<()>
where K: ser::Serialize,
V: ser::Serialize,
{
try!(self.formatter.comma(&mut self.writer, self.first));
self.first = false;
try!(key.serialize(self));
try!(self.formatter.colon(&mut self.writer));
value.serialize(self)
}
}
pub trait Formatter {
fn open<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
where W: io::Write;
fn comma<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
where W: io::Write;
fn colon<W>(&mut self, writer: &mut W) -> io::Result<()>
where W: io::Write;
fn close<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
where W: io::Write;
}
pub struct CompactFormatter;
impl Formatter for CompactFormatter {
fn open<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
where W: io::Write,
{
writer.write_all(&[ch])
}
fn comma<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
where W: io::Write,
{
if first {
Ok(())
} else {
writer.write_all(b",")
}
}
fn colon<W>(&mut self, writer: &mut W) -> io::Result<()>
where W: io::Write,
{
writer.write_all(b":")
}
fn close<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
where W: io::Write,
{
writer.write_all(&[ch])
}
}
pub struct PrettyFormatter<'a> {
current_indent: usize,
indent: &'a [u8],
}
impl<'a> PrettyFormatter<'a> {
fn new() -> Self {
PrettyFormatter::with_indent(b" ")
}
fn with_indent(indent: &'a [u8]) -> Self {
PrettyFormatter {
current_indent: 0,
indent: indent,
}
}
}
impl<'a> Formatter for PrettyFormatter<'a> {
fn open<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
where W: io::Write,
{
self.current_indent += 1;
writer.write_all(&[ch])
}
fn comma<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
where W: io::Write,
{
if first {
try!(writer.write_all(b"\n"));
} else {
try!(writer.write_all(b",\n"));
}
indent(writer, self.current_indent, self.indent)
}
fn colon<W>(&mut self, writer: &mut W) -> io::Result<()>
where W: io::Write,
{
writer.write_all(b": ")
}
fn close<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
where W: io::Write,
{
self.current_indent -= 1;
try!(writer.write(b"\n"));
try!(indent(writer, self.current_indent, self.indent));
writer.write_all(&[ch])
}
}
#[inline]
pub fn escape_bytes<W>(wr: &mut W, bytes: &[u8]) -> io::Result<()>
where W: io::Write
{
try!(wr.write_all(b"\""));
let mut start = 0;
for (i, byte) in bytes.iter().enumerate() {
let escaped = match *byte {
b'"' => b"\\\"",
b'\\' => b"\\\\",
b'\x08' => b"\\b",
b'\x0c' => b"\\f",
b'\n' => b"\\n",
b'\r' => b"\\r",
b'\t' => b"\\t",
_ => { continue; }
};
if start < i {
try!(wr.write_all(&bytes[start..i]));
}
try!(wr.write_all(escaped));
start = i + 1;
}
if start != bytes.len() {
try!(wr.write_all(&bytes[start..]));
}
try!(wr.write_all(b"\""));
Ok(())
}
#[inline]
pub fn escape_str<W>(wr: &mut W, value: &str) -> io::Result<()>
where W: io::Write
{
escape_bytes(wr, value.as_bytes())
}
#[inline]
fn escape_char<W>(wr: &mut W, value: char) -> io::Result<()>
where W: io::Write
{
// FIXME: this allocation is required in order to be compatible with stable
// rust, which doesn't support encoding a `char` into a stack buffer.
escape_bytes(wr, value.to_string().as_bytes())
}
fn fmt_f32_or_null<W>(wr: &mut W, value: f32) -> io::Result<()>
where W: io::Write
{
match value.classify() {
FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"),
_ => {
let s = format!("{:?}", value);
try!(wr.write_all(s.as_bytes()));
if !s.contains('.') {
try!(wr.write_all(b".0"))
}
Ok(())
}
}
}
fn fmt_f64_or_null<W>(wr: &mut W, value: f64) -> io::Result<()>
where W: io::Write
{
match value.classify() {
FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"),
_ => {
let s = format!("{:?}", value);
try!(wr.write_all(s.as_bytes()));
if !s.contains('.') {
try!(wr.write_all(b".0"))
}
Ok(())
}
}
}
/// Encode the specified struct into a json `[u8]` writer.
#[inline]
pub fn to_writer<W, T>(writer: &mut W, value: &T) -> io::Result<()>
where W: io::Write,
T: ser::Serialize,
{
let mut ser = Serializer::new(writer);
try!(value.serialize(&mut ser));
Ok(())
}
/// Encode the specified struct into a json `[u8]` writer.
#[inline]
pub fn to_writer_pretty<W, T>(writer: &mut W, value: &T) -> io::Result<()>
where W: io::Write,
T: ser::Serialize,
{
let mut ser = Serializer::pretty(writer);
try!(value.serialize(&mut ser));
Ok(())
}
/// Encode the specified struct into a json `[u8]` buffer.
#[inline]
pub fn to_vec<T>(value: &T) -> Vec<u8>
where T: ser::Serialize,
{
// We are writing to a Vec, which doesn't fail. So we can ignore
// the error.
let mut writer = Vec::with_capacity(128);
to_writer(&mut writer, value).unwrap();
writer
}
/// Encode the specified struct into a json `[u8]` buffer.
#[inline]
pub fn to_vec_pretty<T>(value: &T) -> Vec<u8>
where T: ser::Serialize,
{
// We are writing to a Vec, which doesn't fail. So we can ignore
// the error.
let mut writer = Vec::with_capacity(128);
to_writer_pretty(&mut writer, value).unwrap();
writer
}
/// Encode the specified struct into a json `String` buffer.
#[inline]
pub fn to_string<T>(value: &T) -> Result<String, FromUtf8Error>
where T: ser::Serialize
{
let vec = to_vec(value);
String::from_utf8(vec)
}
/// Encode the specified struct into a json `String` buffer.
#[inline]
pub fn to_string_pretty<T>(value: &T) -> Result<String, FromUtf8Error>
where T: ser::Serialize
{
let vec = to_vec_pretty(value);
String::from_utf8(vec)
}
fn indent<W>(wr: &mut W, n: usize, s: &[u8]) -> io::Result<()>
where W: io::Write,
{
for _ in 0 .. n {
try!(wr.write_all(s));
}
Ok(())
}
-883
View File
@@ -1,883 +0,0 @@
use std::collections::{BTreeMap, btree_map};
use std::fmt;
use std::io;
use std::str;
use std::vec;
use num::NumCast;
use de;
use ser;
use super::error::Error;
#[derive(Clone, PartialEq)]
pub enum Value {
Null,
Bool(bool),
I64(i64),
U64(u64),
F64(f64),
String(String),
Array(Vec<Value>),
Object(BTreeMap<String, Value>),
}
impl Value {
/// If the `Value` is an Object, returns the value associated with the provided key.
/// Otherwise, returns None.
pub fn find<'a>(&'a self, key: &str) -> Option<&'a Value>{
match self {
&Value::Object(ref map) => map.get(key),
_ => None
}
}
/// Attempts to get a nested Value Object for each key in `keys`.
/// If any key is found not to exist, find_path will return None.
/// Otherwise, it will return the `Value` associated with the final key.
pub fn find_path<'a>(&'a self, keys: &[&str]) -> Option<&'a Value>{
let mut target = self;
for key in keys.iter() {
match target.find(*key) {
Some(t) => { target = t; },
None => return None
}
}
Some(target)
}
/// If the `Value` is an Object, performs a depth-first search until
/// a value associated with the provided key is found. If no value is found
/// or the `Value` is not an Object, returns None.
pub fn search<'a>(&'a self, key: &str) -> Option<&'a Value> {
match self {
&Value::Object(ref map) => {
match map.get(key) {
Some(json_value) => Some(json_value),
None => {
for (_, v) in map.iter() {
match v.search(key) {
x if x.is_some() => return x,
_ => ()
}
}
None
}
}
},
_ => None
}
}
/// Returns true if the `Value` is an Object. Returns false otherwise.
pub fn is_object<'a>(&'a self) -> bool {
self.as_object().is_some()
}
/// If the `Value` is an Object, returns the associated BTreeMap.
/// Returns None otherwise.
pub fn as_object<'a>(&'a self) -> Option<&'a BTreeMap<String, Value>> {
match self {
&Value::Object(ref map) => Some(map),
_ => None
}
}
/// If the `Value` is an Object, returns the associated mutable BTreeMap.
/// Returns None otherwise.
pub fn as_object_mut<'a>(&'a mut self) -> Option<&'a mut BTreeMap<String, Value>> {
match self {
&mut Value::Object(ref mut map) => Some(map),
_ => None
}
}
/// Returns true if the `Value` is an Array. Returns false otherwise.
pub fn is_array<'a>(&'a self) -> bool {
self.as_array().is_some()
}
/// If the `Value` is an Array, returns the associated vector.
/// Returns None otherwise.
pub fn as_array<'a>(&'a self) -> Option<&'a Vec<Value>> {
match self {
&Value::Array(ref array) => Some(&*array),
_ => None
}
}
/// If the `Value` is an Array, returns the associated mutable vector.
/// Returns None otherwise.
pub fn as_array_mut<'a>(&'a mut self) -> Option<&'a mut Vec<Value>> {
match self {
&mut Value::Array(ref mut list) => Some(list),
_ => None
}
}
/// Returns true if the `Value` is a String. Returns false otherwise.
pub fn is_string<'a>(&'a self) -> bool {
self.as_string().is_some()
}
/// If the `Value` is a String, returns the associated str.
/// Returns None otherwise.
pub fn as_string<'a>(&'a self) -> Option<&'a str> {
match *self {
Value::String(ref s) => Some(&s),
_ => None
}
}
/// Returns true if the `Value` is a Number. Returns false otherwise.
pub fn is_number(&self) -> bool {
match *self {
Value::I64(_) | Value::U64(_) | Value::F64(_) => true,
_ => false,
}
}
/// Returns true if the `Value` is a i64. Returns false otherwise.
pub fn is_i64(&self) -> bool {
match *self {
Value::I64(_) => true,
_ => false,
}
}
/// Returns true if the `Value` is a u64. Returns false otherwise.
pub fn is_u64(&self) -> bool {
match *self {
Value::U64(_) => true,
_ => false,
}
}
/// Returns true if the `Value` is a f64. Returns false otherwise.
pub fn is_f64(&self) -> bool {
match *self {
Value::F64(_) => true,
_ => false,
}
}
/// If the `Value` is a number, return or cast it to a i64.
/// Returns None otherwise.
pub fn as_i64(&self) -> Option<i64> {
match *self {
Value::I64(n) => Some(n),
Value::U64(n) => NumCast::from(n),
_ => None
}
}
/// If the `Value` is a number, return or cast it to a u64.
/// Returns None otherwise.
pub fn as_u64(&self) -> Option<u64> {
match *self {
Value::I64(n) => NumCast::from(n),
Value::U64(n) => Some(n),
_ => None
}
}
/// If the `Value` is a number, return or cast it to a f64.
/// Returns None otherwise.
pub fn as_f64(&self) -> Option<f64> {
match *self {
Value::I64(n) => NumCast::from(n),
Value::U64(n) => NumCast::from(n),
Value::F64(n) => Some(n),
_ => None
}
}
/// Returns true if the `Value` is a Boolean. Returns false otherwise.
pub fn is_boolean(&self) -> bool {
self.as_boolean().is_some()
}
/// If the `Value` is a Boolean, returns the associated bool.
/// Returns None otherwise.
pub fn as_boolean(&self) -> Option<bool> {
match self {
&Value::Bool(b) => Some(b),
_ => None
}
}
/// Returns true if the `Value` is a Null. Returns false otherwise.
pub fn is_null(&self) -> bool {
self.as_null().is_some()
}
/// If the `Value` is a Null, returns ().
/// Returns None otherwise.
pub fn as_null(&self) -> Option<()> {
match self {
&Value::Null => Some(()),
_ => None
}
}
}
impl ser::Serialize for Value {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: ser::Serializer,
{
match *self {
Value::Null => serializer.visit_unit(),
Value::Bool(v) => serializer.visit_bool(v),
Value::I64(v) => serializer.visit_i64(v),
Value::U64(v) => serializer.visit_u64(v),
Value::F64(v) => serializer.visit_f64(v),
Value::String(ref v) => serializer.visit_str(&v),
Value::Array(ref v) => v.serialize(serializer),
Value::Object(ref v) => v.serialize(serializer),
}
}
}
impl de::Deserialize for Value {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<Value, D::Error>
where D: de::Deserializer,
{
struct ValueVisitor;
impl de::Visitor for ValueVisitor {
type Value = Value;
#[inline]
fn visit_bool<E>(&mut self, value: bool) -> Result<Value, E> {
Ok(Value::Bool(value))
}
#[inline]
fn visit_i64<E>(&mut self, value: i64) -> Result<Value, E> {
if value < 0 {
Ok(Value::I64(value))
} else {
Ok(Value::U64(value as u64))
}
}
#[inline]
fn visit_u64<E>(&mut self, value: u64) -> Result<Value, E> {
Ok(Value::U64(value))
}
#[inline]
fn visit_f64<E>(&mut self, value: f64) -> Result<Value, E> {
Ok(Value::F64(value))
}
#[inline]
fn visit_str<E>(&mut self, value: &str) -> Result<Value, E>
where E: de::Error,
{
self.visit_string(value.to_string())
}
#[inline]
fn visit_string<E>(&mut self, value: String) -> Result<Value, E> {
Ok(Value::String(value))
}
#[inline]
fn visit_none<E>(&mut self) -> Result<Value, E> {
Ok(Value::Null)
}
#[inline]
fn visit_some<D>(&mut self, deserializer: &mut D) -> Result<Value, D::Error>
where D: de::Deserializer,
{
de::Deserialize::deserialize(deserializer)
}
#[inline]
fn visit_unit<E>(&mut self) -> Result<Value, E> {
Ok(Value::Null)
}
#[inline]
fn visit_seq<V>(&mut self, visitor: V) -> Result<Value, V::Error>
where V: de::SeqVisitor,
{
let values = try!(de::impls::VecVisitor::new().visit_seq(visitor));
Ok(Value::Array(values))
}
#[inline]
fn visit_map<V>(&mut self, visitor: V) -> Result<Value, V::Error>
where V: de::MapVisitor,
{
let values = try!(de::impls::BTreeMapVisitor::new().visit_map(visitor));
Ok(Value::Object(values))
}
}
deserializer.visit(ValueVisitor)
}
}
struct WriterFormatter<'a, 'b: 'a> {
inner: &'a mut fmt::Formatter<'b>,
}
impl<'a, 'b> io::Write for WriterFormatter<'a, 'b> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match self.inner.write_str(str::from_utf8(buf).unwrap()) {
Ok(_) => Ok(buf.len()),
Err(_) => Err(io::Error::last_os_error()),
}
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl fmt::Debug for Value {
/// Serializes a json value into a string
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut wr = WriterFormatter { inner: f };
super::ser::to_writer(&mut wr, self).map_err(|_| fmt::Error)
}
}
#[derive(Debug)]
enum State {
Value(Value),
Array(Vec<Value>),
Object(BTreeMap<String, Value>),
}
pub struct Serializer {
state: Vec<State>,
}
impl Serializer {
pub fn new() -> Serializer {
Serializer {
state: Vec::with_capacity(4),
}
}
pub fn unwrap(mut self) -> Value {
match self.state.pop().unwrap() {
State::Value(value) => value,
state => panic!("expected value, found {:?}", state),
}
}
}
impl ser::Serializer for Serializer {
type Error = ();
#[inline]
fn visit_bool(&mut self, value: bool) -> Result<(), ()> {
self.state.push(State::Value(Value::Bool(value)));
Ok(())
}
#[inline]
fn visit_i64(&mut self, value: i64) -> Result<(), ()> {
if value < 0 {
self.state.push(State::Value(Value::I64(value)));
} else {
self.state.push(State::Value(Value::U64(value as u64)));
}
Ok(())
}
#[inline]
fn visit_u64(&mut self, value: u64) -> Result<(), ()> {
self.state.push(State::Value(Value::U64(value)));
Ok(())
}
#[inline]
fn visit_f64(&mut self, value: f64) -> Result<(), ()> {
self.state.push(State::Value(Value::F64(value as f64)));
Ok(())
}
#[inline]
fn visit_char(&mut self, value: char) -> Result<(), ()> {
self.state.push(State::Value(Value::String(value.to_string())));
Ok(())
}
#[inline]
fn visit_str(&mut self, value: &str) -> Result<(), ()> {
self.state.push(State::Value(Value::String(value.to_string())));
Ok(())
}
#[inline]
fn visit_none(&mut self) -> Result<(), ()> {
self.visit_unit()
}
#[inline]
fn visit_some<V>(&mut self, value: V) -> Result<(), ()>
where V: ser::Serialize,
{
value.serialize(self)
}
#[inline]
fn visit_unit(&mut self) -> Result<(), ()> {
self.state.push(State::Value(Value::Null));
Ok(())
}
#[inline]
fn visit_enum_unit(&mut self, _name: &str, variant: &str) -> Result<(), ()> {
let mut values = BTreeMap::new();
values.insert(variant.to_string(), Value::Array(vec![]));
self.state.push(State::Value(Value::Object(values)));
Ok(())
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<(), ()>
where V: ser::SeqVisitor,
{
let len = visitor.len().unwrap_or(0);
let values = Vec::with_capacity(len);
self.state.push(State::Array(values));
while let Some(()) = try!(visitor.visit(self)) { }
let values = match self.state.pop().unwrap() {
State::Array(values) => values,
state => panic!("Expected array, found {:?}", state),
};
self.state.push(State::Value(Value::Array(values)));
Ok(())
}
#[inline]
fn visit_enum_seq<V>(&mut self, _name: &str, variant: &str, visitor: V) -> Result<(), ()>
where V: ser::SeqVisitor,
{
try!(self.visit_seq(visitor));
let value = match self.state.pop().unwrap() {
State::Value(value) => value,
state => panic!("expected value, found {:?}", state),
};
let mut object = BTreeMap::new();
object.insert(variant.to_string(), value);
self.state.push(State::Value(Value::Object(object)));
Ok(())
}
#[inline]
fn visit_seq_elt<T>(&mut self, value: T) -> Result<(), ()>
where T: ser::Serialize,
{
try!(value.serialize(self));
let value = match self.state.pop().unwrap() {
State::Value(value) => value,
state => panic!("expected value, found {:?}", state),
};
match *self.state.last_mut().unwrap() {
State::Array(ref mut values) => { values.push(value); }
ref state => panic!("expected array, found {:?}", state),
}
Ok(())
}
#[inline]
fn visit_map<V>(&mut self, mut visitor: V) -> Result<(), ()>
where V: ser::MapVisitor,
{
let values = BTreeMap::new();
self.state.push(State::Object(values));
while let Some(()) = try!(visitor.visit(self)) { }
let values = match self.state.pop().unwrap() {
State::Object(values) => values,
state => panic!("expected object, found {:?}", state),
};
self.state.push(State::Value(Value::Object(values)));
Ok(())
}
#[inline]
fn visit_enum_map<V>(&mut self, _name: &str, variant: &str, visitor: V) -> Result<(), ()>
where V: ser::MapVisitor,
{
try!(self.visit_map(visitor));
let value = match self.state.pop().unwrap() {
State::Value(value) => value,
state => panic!("expected value, found {:?}", state),
};
let mut object = BTreeMap::new();
object.insert(variant.to_string(), value);
self.state.push(State::Value(Value::Object(object)));
Ok(())
}
#[inline]
fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), ()>
where K: ser::Serialize,
V: ser::Serialize,
{
try!(key.serialize(self));
let key = match self.state.pop().unwrap() {
State::Value(Value::String(value)) => value,
state => panic!("expected key, found {:?}", state),
};
try!(value.serialize(self));
let value = match self.state.pop().unwrap() {
State::Value(value) => value,
state => panic!("expected value, found {:?}", state),
};
match *self.state.last_mut().unwrap() {
State::Object(ref mut values) => { values.insert(key, value); }
ref state => panic!("expected object, found {:?}", state),
}
Ok(())
}
}
pub struct Deserializer {
value: Option<Value>,
}
impl Deserializer {
/// Creates a new deserializer instance for deserializing the specified JSON value.
pub fn new(value: Value) -> Deserializer {
Deserializer {
value: Some(value),
}
}
}
impl de::Deserializer for Deserializer {
type Error = Error;
#[inline]
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
let value = match self.value.take() {
Some(value) => value,
None => { return Err(de::Error::end_of_stream_error()); }
};
match value {
Value::Null => visitor.visit_unit(),
Value::Bool(v) => visitor.visit_bool(v),
Value::I64(v) => visitor.visit_i64(v),
Value::U64(v) => visitor.visit_u64(v),
Value::F64(v) => visitor.visit_f64(v),
Value::String(v) => visitor.visit_string(v),
Value::Array(v) => {
let len = v.len();
visitor.visit_seq(SeqDeserializer {
de: self,
iter: v.into_iter(),
len: len,
})
}
Value::Object(v) => {
let len = v.len();
visitor.visit_map(MapDeserializer {
de: self,
iter: v.into_iter(),
value: None,
len: len,
})
}
}
}
#[inline]
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.value {
Some(Value::Null) => visitor.visit_none(),
Some(_) => visitor.visit_some(self),
None => Err(de::Error::end_of_stream_error()),
}
}
#[inline]
fn visit_enum<V>(&mut self, _name: &str, mut visitor: V) -> Result<V::Value, Error>
where V: de::EnumVisitor,
{
let value = match self.value.take() {
Some(Value::Object(value)) => value,
Some(_) => { return Err(de::Error::syntax_error()); }
None => { return Err(de::Error::end_of_stream_error()); }
};
let mut iter = value.into_iter();
let value = match iter.next() {
Some((variant, Value::Array(fields))) => {
self.value = Some(Value::String(variant));
let len = fields.len();
try!(visitor.visit(SeqDeserializer {
de: self,
iter: fields.into_iter(),
len: len,
}))
}
Some((variant, Value::Object(fields))) => {
let len = fields.len();
try!(visitor.visit(MapDeserializer {
de: self,
iter: fields.into_iter(),
value: Some(Value::String(variant)),
len: len,
}))
}
Some(_) => { return Err(de::Error::syntax_error()); }
None => { return Err(de::Error::syntax_error()); }
};
match iter.next() {
Some(_) => Err(de::Error::syntax_error()),
None => Ok(value)
}
}
}
struct SeqDeserializer<'a> {
de: &'a mut Deserializer,
iter: vec::IntoIter<Value>,
len: usize,
}
impl<'a> de::Deserializer for SeqDeserializer<'a> {
type Error = Error;
#[inline]
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
if self.len == 0 {
visitor.visit_unit()
} else {
visitor.visit_seq(self)
}
}
}
impl<'a> de::SeqVisitor for SeqDeserializer<'a> {
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: de::Deserialize
{
match self.iter.next() {
Some(value) => {
self.len -= 1;
self.de.value = Some(value);
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
None => Ok(None),
}
}
fn end(&mut self) -> Result<(), Error> {
if self.len == 0 {
Ok(())
} else {
Err(de::Error::end_of_stream_error())
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl<'a> de::VariantVisitor for SeqDeserializer<'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)
}
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
de::Deserializer::visit(self, visitor)
}
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
de::Deserializer::visit(self, visitor)
}
}
struct MapDeserializer<'a> {
de: &'a mut Deserializer,
iter: btree_map::IntoIter<String, Value>,
value: Option<Value>,
len: usize,
}
impl<'a> de::MapVisitor for MapDeserializer<'a> {
type Error = Error;
fn visit_key<T>(&mut self) -> Result<Option<T>, Error>
where T: de::Deserialize
{
match self.iter.next() {
Some((key, value)) => {
self.len -= 1;
self.value = Some(value);
self.de.value = Some(Value::String(key));
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
None => Ok(None),
}
}
fn visit_value<T>(&mut self) -> Result<T, Error>
where T: de::Deserialize
{
let value = self.value.take().unwrap();
self.de.value = Some(value);
Ok(try!(de::Deserialize::deserialize(self.de)))
}
fn end(&mut self) -> Result<(), Error> {
if self.len == 0 {
Ok(())
} else {
Err(de::Error::end_of_stream_error())
}
}
fn missing_field<V>(&mut self, _field: &'static str) -> Result<V, Error>
where V: de::Deserialize,
{
// See if the type can deserialize from a unit.
struct UnitDeserializer;
impl de::Deserializer for UnitDeserializer {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_unit()
}
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_none()
}
}
Ok(try!(de::Deserialize::deserialize(&mut UnitDeserializer)))
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl<'a> de::Deserializer for MapDeserializer<'a> {
type Error = Error;
#[inline]
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
println!("MapDeserializer!");
visitor.visit_map(self)
}
}
impl<'a> de::VariantVisitor for MapDeserializer<'a> {
type Error = Error;
fn visit_variant<V>(&mut self) -> Result<V, Error>
where V: de::Deserialize,
{
self.de.value = self.value.take();
de::Deserialize::deserialize(self.de)
}
fn visit_unit(&mut self) -> Result<(), Error> {
de::Deserialize::deserialize(self)
}
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
de::Deserializer::visit(self, visitor)
}
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
de::Deserializer::visit(self, visitor)
}
}
/// Shortcut function to encode a `T` into a JSON `Value`
pub fn to_value<T>(value: &T) -> Value
where T: ser::Serialize
{
let mut ser = Serializer::new();
value.serialize(&mut ser).ok().unwrap();
ser.unwrap()
}
/// Shortcut function to decode a JSON `Value` into a `T`
pub fn from_value<T>(value: Value) -> Result<T, Error>
where T: de::Deserialize
{
let mut de = Deserializer::new(value);
de::Deserialize::deserialize(&mut de)
}
-19
View File
@@ -1,19 +0,0 @@
//! Serde Serialization Framework
//!
//! 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.
#![doc(html_root_url="http://erickt.github.io/rust-serde")]
extern crate num;
pub use ser::{Serialize, Serializer};
pub use de::{Deserialize, Deserializer, Error};
pub mod bytes;
pub mod de;
pub mod iter;
pub mod json;
pub mod ser;
-490
View File
@@ -1,490 +0,0 @@
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::hash::Hash;
use std::path;
use std::rc::Rc;
use std::sync::Arc;
use super::{
Serialize,
Serializer,
SeqVisitor,
MapVisitor,
};
///////////////////////////////////////////////////////////////////////////////
macro_rules! impl_visit {
($ty:ty, $method:ident) => {
impl Serialize for $ty {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.$method(*self)
}
}
}
}
impl_visit!(bool, visit_bool);
impl_visit!(isize, visit_isize);
impl_visit!(i8, visit_i8);
impl_visit!(i16, visit_i16);
impl_visit!(i32, visit_i32);
impl_visit!(i64, visit_i64);
impl_visit!(usize, visit_usize);
impl_visit!(u8, visit_u8);
impl_visit!(u16, visit_u16);
impl_visit!(u32, visit_u32);
impl_visit!(u64, visit_u64);
impl_visit!(f32, visit_f32);
impl_visit!(f64, visit_f64);
impl_visit!(char, visit_char);
///////////////////////////////////////////////////////////////////////////////
impl Serialize for str {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_str(self)
}
}
impl Serialize for String {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
(&self[..]).serialize(serializer)
}
}
///////////////////////////////////////////////////////////////////////////////
impl<T> Serialize for Option<T> where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
match *self {
Some(ref value) => serializer.visit_some(value),
None => serializer.visit_none(),
}
}
}
///////////////////////////////////////////////////////////////////////////////
pub struct SeqIteratorVisitor<Iter> {
iter: Iter,
len: Option<usize>,
}
impl<T, Iter> SeqIteratorVisitor<Iter>
where Iter: Iterator<Item=T>
{
#[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) => {
let value = try!(serializer.visit_seq_elt(value));
Ok(Some(value))
}
None => Ok(None),
}
}
#[inline]
fn len(&self) -> Option<usize> {
self.len
}
}
///////////////////////////////////////////////////////////////////////////////
impl<'a, T> Serialize for &'a [T]
where T: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
impl<T> Serialize for Vec<T> where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
(&self[..]).serialize(serializer)
}
}
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.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
impl<T> Serialize for HashSet<T>
where T: Serialize + Eq + Hash,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
///////////////////////////////////////////////////////////////////////////////
impl Serialize for () {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_unit()
}
}
///////////////////////////////////////////////////////////////////////////////
// FIXME(rust #19630) Remove this work-around
macro_rules! e {
($e:expr) => { $e }
}
macro_rules! tuple_impls {
($(
$TupleVisitor:ident ($len:expr, $($T:ident),+) {
$($state:pat => $idx:tt,)+
}
)+) => {
$(
pub struct $TupleVisitor<'a, $($T: 'a),+> {
tuple: &'a ($($T,)+),
state: u8,
}
impl<'a, $($T: 'a),+> $TupleVisitor<'a, $($T),+> {
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.visit_seq_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.visit_seq($TupleVisitor::new(self))
}
}
)+
}
}
tuple_impls! {
TupleVisitor1 (1, T0) {
0 => 0,
}
TupleVisitor2 (2, T0, T1) {
0 => 0,
1 => 1,
}
TupleVisitor3 (3, T0, T1, T2) {
0 => 0,
1 => 1,
2 => 2,
}
TupleVisitor4 (4, T0, T1, T2, T3) {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
}
TupleVisitor5 (5, T0, T1, T2, T3, T4) {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
}
TupleVisitor6 (6, T0, T1, T2, T3, T4, T5) {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
}
TupleVisitor7 (7, T0, T1, T2, T3, T4, T5, T6) {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
}
TupleVisitor8 (8, T0, T1, T2, T3, T4, T5, T6, T7) {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
7 => 7,
}
TupleVisitor9 (9, T0, T1, T2, T3, T4, T5, T6, T7, T8) {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
7 => 7,
8 => 8,
}
TupleVisitor10 (10, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
7 => 7,
8 => 8,
9 => 9,
}
TupleVisitor11 (11, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
7 => 7,
8 => 8,
9 => 9,
10 => 10,
}
TupleVisitor12 (12, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
7 => 7,
8 => 8,
9 => 9,
10 => 10,
11 => 11,
}
}
///////////////////////////////////////////////////////////////////////////////
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.visit_map_elt(key, value));
Ok(Some(value))
}
None => Ok(None)
}
}
#[inline]
fn len(&self) -> Option<usize> {
self.len
}
}
///////////////////////////////////////////////////////////////////////////////
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.visit_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
impl<K, V> Serialize for HashMap<K, V>
where K: Serialize + Eq + Hash,
V: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
// FIXME: `VecMap` is unstable.
/*
impl<V> Serialize for VecMap<V>
where V: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
*/
///////////////////////////////////////////////////////////////////////////////
impl<'a, T: ?Sized> Serialize for &'a T where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
(**self).serialize(serializer)
}
}
impl<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
(**self).serialize(serializer)
}
}
impl<T: ?Sized> Serialize for Box<T> where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
(**self).serialize(serializer)
}
}
impl<T> Serialize for Rc<T> where T: Serialize, {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
(**self).serialize(serializer)
}
}
impl<T> Serialize for Arc<T> where T: Serialize, {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
(**self).serialize(serializer)
}
}
///////////////////////////////////////////////////////////////////////////////
impl Serialize for path::Path {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
self.to_str().unwrap().serialize(serializer)
}
}
impl Serialize for path::PathBuf {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
self.to_str().unwrap().serialize(serializer)
}
}
-204
View File
@@ -1,204 +0,0 @@
//! Generic serialization framework.
pub mod impls;
///////////////////////////////////////////////////////////////////////////////
pub trait Serialize {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer;
}
///////////////////////////////////////////////////////////////////////////////
pub trait Serializer {
type Error;
/// `visit_bool` serializes a `bool` value.
fn visit_bool(&mut self, v: bool) -> Result<(), Self::Error>;
/// `visit_isize` serializes a `isize` value. By default it casts the value to a `i64` and
/// passes it to the `visit_i64` method.
#[inline]
fn visit_isize(&mut self, v: isize) -> Result<(), Self::Error> {
self.visit_i64(v as i64)
}
/// `visit_i8` serializes a `i8` value. By default it casts the value to a `i64` and
/// passes it to the `visit_i64` method.
#[inline]
fn visit_i8(&mut self, v: i8) -> Result<(), Self::Error> {
self.visit_i64(v as i64)
}
/// `visit_i16` serializes a `i16` value. By default it casts the value to a `i64` and
/// passes it to the `visit_i64` method.
#[inline]
fn visit_i16(&mut self, v: i16) -> Result<(), Self::Error> {
self.visit_i64(v as i64)
}
/// `visit_i32` serializes a `i32` value. By default it casts the value to a `i64` and
/// passes it to the `visit_i64` method.
#[inline]
fn visit_i32(&mut self, v: i32) -> Result<(), Self::Error> {
self.visit_i64(v as i64)
}
/// `visit_i64` serializes a `i64` value.
#[inline]
fn visit_i64(&mut self, v: i64) -> Result<(), Self::Error>;
/// `visit_usize` serializes a `usize` value. By default it casts the value to a `u64` and
/// passes it to the `visit_u64` method.
#[inline]
fn visit_usize(&mut self, v: usize) -> Result<(), Self::Error> {
self.visit_u64(v as u64)
}
/// `visit_u8` serializes a `u8` value. By default it casts the value to a `u64` and passes
/// it to the `visit_u64` method.
#[inline]
fn visit_u8(&mut self, v: u8) -> Result<(), Self::Error> {
self.visit_u64(v as u64)
}
/// `visit_u32` serializes a `u32` value. By default it casts the value to a `u64` and passes
/// it to the `visit_u64` method.
#[inline]
fn visit_u16(&mut self, v: u16) -> Result<(), Self::Error> {
self.visit_u64(v as u64)
}
/// `visit_u32` serializes a `u32` value. By default it casts the value to a `u64` and passes
/// it to the `visit_u64` method.
#[inline]
fn visit_u32(&mut self, v: u32) -> Result<(), Self::Error> {
self.visit_u64(v as u64)
}
/// `visit_u64` serializes a `u64` value.
#[inline]
fn visit_u64(&mut self, v: u64) -> Result<(), Self::Error>;
/// `visit_f32` serializes a `f32` value. By default it casts the value to a `f64` and passes
/// it to the `visit_f64` method.
#[inline]
fn visit_f32(&mut self, v: f32) -> Result<(), Self::Error> {
self.visit_f64(v as f64)
}
/// `visit_f64` serializes a `f64` value.
fn visit_f64(&mut self, v: f64) -> Result<(), Self::Error>;
/// `visit_char` serializes a character. By default it serializes it as a `&str` containing a
/// single character.
#[inline]
fn visit_char(&mut self, v: char) -> Result<(), Self::Error> {
// FIXME: this allocation is required in order to be compatible with stable rust, which
// doesn't support encoding a `char` into a stack buffer.
self.visit_str(&v.to_string())
}
/// `visit_str` serializes a `&str`.
fn visit_str(&mut self, value: &str) -> Result<(), Self::Error>;
/// `visit_bytes` is a hook that enables those serialization formats that support serializing
/// byte slices separately from generic arrays. By default it serializes as a regular array.
#[inline]
fn visit_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error> {
self.visit_seq(impls::SeqIteratorVisitor::new(value.iter(), Some(value.len())))
}
fn visit_unit(&mut self) -> Result<(), Self::Error>;
#[inline]
fn visit_named_unit(&mut self, _name: &str) -> Result<(), Self::Error> {
self.visit_unit()
}
#[inline]
fn visit_enum_unit(&mut self,
_name: &str,
_variant: &str) -> Result<(), Self::Error> {
self.visit_unit()
}
fn visit_none(&mut self) -> Result<(), Self::Error>;
fn visit_some<V>(&mut self, value: V) -> Result<(), Self::Error>
where V: Serialize;
fn visit_seq<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor;
#[inline]
fn visit_named_seq<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.visit_seq(visitor)
}
#[inline]
fn visit_enum_seq<V>(&mut self,
_name: &'static str,
_variant: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.visit_seq(visitor)
}
fn visit_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize;
fn visit_map<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: MapVisitor;
#[inline]
fn visit_named_map<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: MapVisitor,
{
self.visit_map(visitor)
}
#[inline]
fn visit_enum_map<V>(&mut self,
_name: &'static str,
_variant: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: MapVisitor,
{
self.visit_map(visitor)
}
fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
where K: Serialize,
V: Serialize;
}
pub trait SeqVisitor {
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer;
/// Return the length of the sequence if known.
#[inline]
fn len(&self) -> Option<usize> {
None
}
}
pub trait MapVisitor {
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer;
/// Return the length of the map if known.
#[inline]
fn len(&self) -> Option<usize> {
None
}
}
+18
View File
@@ -0,0 +1,18 @@
[package]
name = "serde_test_suite"
version = "0.0.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
publish = false
[features]
unstable = ["serde/unstable", "compiletest_rs"]
[dev-dependencies]
fnv = "1.0"
rustc-serialize = "0.3.16"
serde = { path = "../serde" }
serde_derive = { path = "../serde_derive" }
serde_test = { path = "../serde_test" }
[dependencies]
compiletest_rs = { version = "0.2", optional = true }
+11
View File
@@ -0,0 +1,11 @@
[package]
name = "serde_test_suite_deps"
version = "0.0.0"
authors = ["David Tolnay <dtolnay@gmail.com>"]
publish = false
[workspace]
[dependencies]
serde = { path = "../../serde" }
serde_derive = { path = "../../serde_derive" }
View File
+8
View File
@@ -0,0 +1,8 @@
[package]
name = "serde_derive_tests_no_std"
version = "0.0.0"
publish = false
[dependencies]
serde = { path = "../../serde", default-features = false }
serde_derive = { path = "../../serde_derive" }
+53
View File
@@ -0,0 +1,53 @@
#![feature(lang_items, start, libc, compiler_builtins_lib)]
#![no_std]
extern crate libc;
extern crate compiler_builtins;
#[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) -> ! {
unsafe {
libc::abort()
}
}
//////////////////////////////////////////////////////////////////////////////
#[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 },
}
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test<'a> {
#[serde(borrow = "zzz")] //~^^ HELP: failed to parse borrowed lifetimes: "zzz"
s: &'a str,
}
fn main() {}
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test<'a> {
#[serde(borrow = "'a + 'a")] //~^^ HELP: duplicate borrowed lifetime `'a`
s: &'a str,
}
fn main() {}
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test<'a> {
#[serde(borrow = "")] //~^^ HELP: at least one lifetime must be borrowed
s: &'a str,
}
fn main() {}
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test {
#[serde(borrow)] //~^^ HELP: field `s` has no lifetimes to borrow
s: String,
}
fn main() {}
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test<'a> {
#[serde(borrow = "'b")] //~^^ HELP: field `s` does not have lifetime 'b
s: &'a str,
}
fn main() {}
@@ -0,0 +1,16 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(default)] //~^ HELP: #[serde(default)] can only be used on structs
enum E {
S { f: u8 },
}
@@ -0,0 +1,16 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(default)] //~^ HELP: #[serde(default)] can only be used on structs
struct T(u8, u8);
fn main() { }
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S {
#[serde(rename="x", serialize="y")] //~^^ HELP: unknown serde field attribute `serialize`
x: (),
}
fn main() {}
@@ -0,0 +1,19 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S {
#[serde(rename="x")]
#[serde(rename(deserialize="y"))] //~^^^ HELP: duplicate serde attribute `rename`
x: (),
}
fn main() {}
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S {
#[serde(rename(serialize="x"), rename(serialize="y"))] //~^^ HELP: duplicate serde attribute `rename`
x: (),
}
fn main() {}
@@ -0,0 +1,19 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S {
#[serde(rename(serialize="x"))]
#[serde(rename="y")] //~^^^ HELP: duplicate serde attribute `rename`
x: (),
}
fn main() {}
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S {
#[serde(rename(serialize="x", serialize="y"))] //~^^ HELP: duplicate serde attribute `rename`
x: (),
}
fn main() {}

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