Compare commits

...

1284 Commits

Author SHA1 Message Date
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 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 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 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 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
Erick Tryzelaar 206e19edb4 Fix unquoting arms with latest quasi 2015-05-02 10:44:57 -07:00
Erick Tryzelaar f0c87fbd4c Format flats with Debug to properly print "-0.0". 2015-05-01 07:43:48 -07:00
Erick Tryzelaar c3fe6c9c67 Update the README to point at https://github.com/serde-rs 2015-04-26 18:37:18 -07:00
Erick Tryzelaar e5df4b6653 Simplify PrettyFormatter::new 2015-04-26 12:05:38 -07:00
Erick Tryzelaar 12cf2f0b0b Simplify the return types 2015-04-26 11:01:55 -07:00
Erick Tryzelaar 8d4de2b3db Rename Serializer::new_with_formatter to with_formatter 2015-04-26 10:29:28 -07:00
Erick Tryzelaar e509adcac5 Allow the pretty printer character to be changed
This unfortunately loses the simd-ish whitespace printer, but since
pretty printing shouldn't be on a hot path, this shouldn't really
matter.

Partially addresses #65.
2015-04-26 09:29:06 -07:00
Erick Tryzelaar eb9c860cb4 Rename iterator.rs to iter.rs and expose it. 2015-04-26 09:23:08 -07:00
Erick Tryzelaar cf38b8dae5 Add some docs to LineColIterator, expose the underlying iterator 2015-04-26 09:22:56 -07:00
Erick Tryzelaar 75af81234f LineColIterator doesn't need to be peekable. 2015-04-26 09:21:52 -07:00
Erick Tryzelaar 7cc319acca Bump version to 0.3.2. 2015-04-26 09:21:26 -07:00
Erick Tryzelaar 3b44792ff3 Merge pull request #64 from oli-obk/missing_renamed_field
missing field errors displayed original field name instead of renamed
2015-04-26 08:09:00 -07:00
Erick Tryzelaar 678bad241e Merge pull request #66 from daniellandau/fix/compilation
Fix compilation for latest nightly
2015-04-25 08:13:39 -07:00
Daniel Landau 5b1225cc87 Fix compilation for latest nightly 2015-04-24 22:35:56 +03:00
Oliver Schneider 1748831152 missing field errors displayed original field name instead of renamed
closes #63
2015-04-23 17:28:42 +02:00
Erick Tryzelaar ed1b476a22 Merge pull request #58 from oli-obk/separate_line_col
separate out the line/column counting from character iteration
2015-04-22 11:02:55 -07:00
Erick Tryzelaar 79c59ebae1 Merge pull request #62 from hugoduncan/add-ser-de-rename
Add serialize, deserialize specific rename
2015-04-22 11:01:38 -07:00
Hugo Duncan fd6462f8d1 Add serialize, deserialize specific rename
Adds the rename_serialize and rename_deserialize field attributes to
specify serialisation and deserialisation specific renames.
2015-04-21 17:58:18 -04:00
Oliver Schneider c37f67b0a1 separate out the line/column counting from character iteration 2015-04-16 16:31:56 +02:00
Erick Tryzelaar 195f7380b5 Merge pull request #56 from derhaskell/patch-1
fixes struct serialization example for rust 1.0.0-beta
2015-04-13 06:21:37 -07:00
derhaskell becb8c48e8 fixes typo in deserialization example 2015-04-13 13:37:06 +02:00
derhaskell aa16ecf4d3 Update README.md 2015-04-13 13:28:47 +02:00
derhaskell ddda360fec Update README.md
fixes struct serialization example for rust 1.0.0-beta
2015-04-13 13:27:15 +02:00
Erick Tryzelaar cca72f2dbc Merge pull request #55 from sfackler/master
Add doc link to Cargo.toml and doc attr
2015-04-12 22:22:25 -07:00
Steven Fackler 5013b37c09 Add doc link to Cargo.toml and doc attr
The attribute allows cross-crate rustdoc links.
2015-04-12 22:21:00 -07:00
Erick Tryzelaar c90dc9f48f bump version to 0.3.1 2015-04-12 11:43:35 -07:00
Erick Tryzelaar 67e8ca354c Remove core feature 2015-04-12 11:36:09 -07:00
Erick Tryzelaar 9a4ba047c4 Remove collections feature flag and disable VecMap, which is unstable 2015-04-12 10:48:32 -07:00
Erick Tryzelaar 7622255d6f Remove the std_misc feature flag 2015-04-12 10:43:29 -07:00
Erick Tryzelaar 8ba1e7aceb Remove the need for the unicode feature flag 2015-04-12 10:42:57 -07:00
Erick Tryzelaar 5f6838130d Update to Rust HEAD 2015-04-12 10:32:54 -07:00
Erick Tryzelaar e0eff942b1 Add Error::unknown_field_error 2015-04-12 10:32:54 -07:00
Erick Tryzelaar 1da47c0870 Change de::VariantVisitor to let deserializers know the variant kind
This allows formats like cbor that encode a unit variant as just a
string to work.

[breaking-change]
2015-04-12 10:32:54 -07:00
Erick Tryzelaar d36879f5ee Merge pull request #54 from apoelstra/no-impl-bytebuf
Remove `impl Into<Vec<u8>> for ByteBuf` since it causes a compile error
2015-04-12 10:32:36 -07:00
Andrew Poelstra f363cb435a Remove impl Into<Vec<u8>> for ByteBuf since it causes a compile error
As BurntSushi observes, there is an `impl<T, U> Into<U> for T where U: From<T>`
in libcore. We have `From<Vec<u8>>` for `ByteBuf` since we have implemented
`From<T> for ByteBuf where T: Into<Vec<u8>>`, so this is redundant anyway.
2015-04-11 17:51:31 -05:00
Erick Tryzelaar d8506e9a6d Update to rust HEAD 2015-04-05 13:20:33 -04:00
Erick Tryzelaar 87503d11e9 Merge pull request #49 from alexcrichton/tweak-some-impls
Tweak some Deserialize/Serialize impls
2015-04-03 12:04:50 -04:00
Erick Tryzelaar d0b49d9b89 Finish updating to rust HEAD 2015-04-02 19:13:25 -07:00
Erick Tryzelaar b30965ede4 Get serde to build, but tests are still failing 2015-04-02 13:27:57 -07:00
Alex Crichton ace6d9e442 Generalize some serialization impls
* Impl Serialize for bare `str`
* Expand `&T` and `&mut T` blanket impls to include `T: ?Sized`
* Expand `Box<T>` blanket impl to include `T: ?Sized`
2015-04-02 12:54:21 -07:00
Alex Crichton e150553d58 Add deserialize impls for smart pointers
This allows deserializing into a Box/Arc/Rc pointer
2015-04-02 12:53:51 -07:00
Erick Tryzelaar ed569bd3f6 Update to latest rust nightly 2015-04-01 22:51:02 -07:00
Erick Tryzelaar d00c1ad6d0 Remove the use of serde_macros from the doctests
This has been disabled in the upcoming beta.
2015-04-01 22:19:14 -07:00
Erick Tryzelaar 2cd49060fa Rename #[serde(alias)] to #[serde(rename)] and add tests
Closes #9 and #47.
2015-04-01 22:14:28 -07:00
Erick Tryzelaar 54a970e694 Remove an unnecessary import 2015-04-01 22:13:34 -07:00
Erick Tryzelaar d57f02884f Work on the README, add a json example 2015-04-01 21:59:37 -07:00
Erick Tryzelaar dcf7037792 Add some basic docs 2015-03-31 22:33:18 -07:00
Erick Tryzelaar 55eb390778 Update the readme 2015-03-31 22:16:15 -07:00
Erick Tryzelaar 99b9524201 Change the name of ValueDeserializer::{,into_}deserializer 2015-03-31 20:45:59 -07:00
Erick Tryzelaar 45bd239202 Release 0.3.0 2015-03-31 13:01:17 -07:00
Erick Tryzelaar 54009e0991 Factor out value deserializers 2015-03-31 12:56:17 -07:00
Erick Tryzelaar bfe7a04c4d Update the location of json errors coming from "Deserialize" 2015-03-30 19:50:41 -07:00
Erick Tryzelaar 3167da72d8 Minor whitespace cleanup 2015-03-28 15:40:56 -07:00
Erick Tryzelaar 0d725a63b0 Add some serialization docs 2015-03-26 08:11:43 -07:00
Erick Tryzelaar ee0cd4aba9 Pull the serialization impls into their own file 2015-03-26 08:05:29 -07:00
Erick Tryzelaar 1b1c605102 Pull deserialization impls into their own file 2015-03-26 07:58:26 -07:00
Erick Tryzelaar 44edfa5974 Add {,de}serializer for VecMap 2015-03-26 07:45:22 -07:00
Erick Tryzelaar aa8d13456a Add bytes type to enable {,de}serializing to a byte array 2015-03-25 23:03:01 -07:00
Erick Tryzelaar 4beb86ab7e Update to rust HEAD 2015-03-25 10:43:25 -07:00
Erick Tryzelaar c369010d3d Allow json::de to work with io::Read 2015-03-24 08:55:20 -07:00
Erick Tryzelaar 1618faed63 Add deserialization impls for {BTree,Hash}{Map,Set} 2015-03-23 19:02:20 -07:00
Erick Tryzelaar 9059b734aa Merge pull request #46 from oli-obk/no_rustc_serialize_propagation
require rustc-serialize only in tests and benchmarks
2015-03-23 17:59:55 -07:00
Erick Tryzelaar 89f463111e Merge pull request #42 from Byron/master
fix(macros): fully qualified usage of `Result`
2015-03-23 09:59:55 -07:00
Sebastian Thiel 2962287703 fix(macros): fully qualified usage of Result
Otherwise it was possible for the expanded macro to pickup a
user-defined `Result` type, which didn't fulfill the required type
bounds and cause compilation failure.
2015-03-23 17:04:23 +01:00
Oliver 'ker' Schneider aa3c55fd98 require rustc-serialize only in tests and benchmarks 2015-03-22 14:16:58 +01:00
Erick Tryzelaar 17c295680e Remove an unused variable 2015-03-20 08:47:48 -07:00
Erick Tryzelaar 09de237033 Allow Vecs, BTreeMaps, and HashMaps to be deserialized from a unit
Closes #36
2015-03-20 08:47:33 -07:00
Erick Tryzelaar d17846eff1 Add deserializer type hinting hooks
Formats like xml have trouble knowing if they should deserialize
tags into a sequence from the stream they are deserializing from.
This PR adds hooks so the deserializee can inform the deserializer
to provide them a sequence if possible.

Closes #38.
2015-03-20 08:32:33 -07:00
Erick Tryzelaar 5378d22708 Switch to the new custom_deserialize syntax 2015-03-19 20:19:49 -07:00
Erick Tryzelaar c8b2ad01b5 Update to rust HEAD 2015-03-19 20:19:49 -07:00
Erick Tryzelaar e778c7e25c Update to rust HEAD 2015-03-19 20:19:48 -07:00
Erick Tryzelaar f0d0dd2982 Merge pull request #41 from hugoduncan/feature/mark-field-attributes-used
Mark serde field attributes as used
2015-03-19 20:08:50 -07:00
Hugo Duncan 3e63d34c00 Mark serde field attributes as used
Prevents unused attribute warnings in code that marks fields with
field level #[serde] attributes.
2015-03-19 11:04:08 -04:00
Erick Tryzelaar 8821421357 Docs, json::Value::U64, and bring many of the rust-serialize fns to Value 2015-03-18 20:51:48 -07:00
Erick Tryzelaar eb4af09456 Simplify the variant deserializer visitor 2015-03-18 07:35:05 -07:00
Erick Tryzelaar 78137ee3a4 Rewrite enum deserialization to not require allocations 2015-03-16 22:42:04 -07:00
Erick Tryzelaar b40d8f7bac Remove the first argument from visit_{seq,map}_elt 2015-03-16 22:30:02 -07:00
Erick Tryzelaar a6ba251ef9 Enable a missing field test 2015-03-16 21:23:20 -07:00
Erick Tryzelaar c6cc2340c8 Rename a variable 2015-03-16 21:11:30 -07:00
Erick Tryzelaar a212ef11a9 Fix compiling bench_struct 2015-03-16 21:10:16 -07:00
Erick Tryzelaar 7bd4c6963b Merge pull request #37 from oli-obk/fix_seq_map_end
MapVisitor::end and SeqVisitor::end were mostly never called
2015-03-16 20:54:35 -07:00
Oliver Schneider f21cbb71e2 MapVisitor::end and SeqVisitor::end were mostly never called 2015-03-16 13:27:00 +01:00
Erick Tryzelaar f4f8194f46 More cleanup 2015-03-15 18:38:52 -07:00
Erick Tryzelaar 90e02206fe Cleanup, and move default::Default #[derive_deserialize] support to get called when missing 2015-03-15 18:37:26 -07:00
Erick Tryzelaar 9fc9d1b33a Get rid of syntax::ext::generic from #[derive_deserialize] 2015-03-15 17:47:25 -07:00
Erick Tryzelaar b9f5d22630 Spring cleaning 2015-03-15 15:31:31 -07:00
Erick Tryzelaar cbafc83af4 Cleanup palooza 2015-03-15 15:14:57 -07:00
Erick Tryzelaar b628446768 Cleanup train 2015-03-15 15:04:11 -07:00
Erick Tryzelaar aacc14ad7b More cleanup 2015-03-15 14:50:00 -07:00
Erick Tryzelaar 35eb234c41 More aster driven cleanup 2015-03-15 14:31:05 -07:00
Erick Tryzelaar 989c8ff809 Include running the benchmarks in travis 2015-03-15 13:12:21 -07:00
Erick Tryzelaar 49c2585a20 Try to fix travis 2015-03-15 13:08:08 -07:00
Erick Tryzelaar 9972478066 Fix #35 by not relying on the crate being import in the current module 2015-03-15 13:02:34 -07:00
Erick Tryzelaar 00287bd055 Cleanup 2015-03-14 21:47:23 -07:00
Erick Tryzelaar 11f47bd51f Minor cleanup 2015-03-14 15:20:00 -07:00
Erick Tryzelaar 5e98a83717 Remove redundant bounds 2015-03-14 15:03:41 -07:00
Erick Tryzelaar ec8b7c9b89 Update to rust HEAD 2015-03-14 14:57:13 -07:00
Erick Tryzelaar 008ce75ae5 Replace #[derive_serialize] syntax::ext::deriving::generic with aster 2015-03-14 14:57:05 -07:00
Erick Tryzelaar 5c62b7ed06 Split serde_macros into multiple files 2015-03-14 13:09:37 -07:00
Erick Tryzelaar 99f4efd313 Merge #[derive_serialize] for structs and struct variants 2015-03-14 12:53:53 -07:00
Erick Tryzelaar 87ff636c10 Fix some warnings 2015-03-14 12:03:53 -07:00
Erick Tryzelaar d2bd361d9c Merge #[derive_serialize] backend for serializing tuple structs and variants 2015-03-14 12:02:21 -07:00
Erick Tryzelaar 5a32d420cd More cleanup 2015-03-14 00:47:10 -07:00
Erick Tryzelaar a3b2f00c92 More cleanup 2015-03-14 00:08:23 -07:00
Erick Tryzelaar 13fcf1ad5b More cleanup 2015-03-14 00:04:25 -07:00
Erick Tryzelaar 8cb2ff6e2e Fix multiple unnamed enum seq/map variants
Closes #32.
2015-03-13 23:44:18 -07:00
Erick Tryzelaar c917941ec3 More cleanup 2015-03-13 23:43:21 -07:00
Erick Tryzelaar f699d29fb3 More cleanup 2015-03-13 23:38:12 -07:00
Erick Tryzelaar 6723097a3f More cleanup 2015-03-13 23:26:38 -07:00
Erick Tryzelaar 80e27344f1 More cleanup 2015-03-13 23:17:44 -07:00
Erick Tryzelaar f244e0f522 More cleanup 2015-03-13 23:11:05 -07:00
Erick Tryzelaar 61317f5935 Replace some aster with quasi in serde_macros 2015-03-13 22:46:21 -07:00
Erick Tryzelaar 9ca1e2a8f7 Bump aster and quasi 2015-03-13 19:37:01 -07:00
Erick Tryzelaar aedd5f57cf Split json compact and pretty serializer. Recover 20MB/s 2015-03-12 21:15:47 -07:00
Erick Tryzelaar dc87288f48 Allow json missing fields to be treated as a null
Closes #34.
2015-03-12 20:44:16 -07:00
Erick Tryzelaar 5dd53e7ea3 Change ser::{Seq,Map}Visitor to return an optional exact length
This is necessary for formats that serialize the length in the
format stream. Those formats need the exact length, so the
iterator-style size_hint has the wrong semantics.
2015-03-12 19:40:46 -07:00
Erick Tryzelaar 9e454a243a Rename Serialize::visit to Serialize::serialize 2015-03-12 07:33:34 -07:00
Erick Tryzelaar 3f62b6d2bf Merge ser::Serializer and ser::Visitor 2015-03-11 11:05:46 -07:00
Erick Tryzelaar fbd6d1974a Remove the unused Serializer::Value associated type 2015-03-11 10:15:27 -07:00
Erick Tryzelaar 5d22be26d8 Fixed the description 2015-03-08 23:12:33 -07:00
114 changed files with 19709 additions and 10845 deletions
+3 -2
View File
@@ -1,2 +1,3 @@
/target/
/Cargo.lock
Cargo.lock
target
*.sw[po]
+12 -8
View File
@@ -1,13 +1,17 @@
sudo: false
language: rust
cache: cargo
# run builds for all the trains (and more)
rust:
- 1.13.0
- stable
- beta
- nightly
script:
- cargo build --verbose
- cargo test --verbose
- cargo bench --verbose
- cd serde2
- cargo build --verbose
- cargo test --verbose
- cargo bench --verbose
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 -16
View File
@@ -1,16 +1,9 @@
[package]
name = "serde"
version = "0.2.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A quasi-quoting macro system"
repository = "https://github.com/erickt/rust-quasi"
[lib]
name = "serde"
[dependencies]
rustc-serialize = "*"
[dev-dependencies]
serde_macros = "0.2.0"
[workspace]
members = [
"serde",
"serde_codegen_internals",
"serde_derive",
"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.
+67 -30
View File
@@ -1,34 +1,71 @@
Experimental Rust Serialization Library.
# Serde &emsp; [![Build Status](https://api.travis-ci.org/serde-rs/serde.svg?branch=master)](https://travis-ci.org/serde-rs/serde) [![Latest Version](https://img.shields.io/crates/v/serde.svg)](https://crates.io/crates/serde)
[![Build Status](https://travis-ci.org/erickt/rust-serde.png?branch=master)](https://travis-ci.org/erickt/rust-serde)
This is an experiment to modernize rust's `libserialize` library. It is designed to implement https://github.com/rust-lang/rfcs/pull/22. `rust-serde` is an attempt to address a major shortcoming in `libserialize`. For normal structures, when you say you want to deserialize into:
```rust
struct Foo {
x: int,
y: int,
}
```
`libserialize`'s deserializer essentially asks for:
* Is the next value a struct named "Foo"? If not, error.
* Is the next field named "x"? If not, error.
* Is the next value an "int"? If not, error.
* Is the next field named "y"? If not, error.
* Is the next value an "int"? If not, error.
* Is the struct finished? If not, error.
While this works for user defined structures, it cannot support deserializing into a value like `json::Json`, which is an enum that can represent every JSON value. In order to support that, it needs to be able to do some lookahead:
* What is the next value type?
* If a struct, parse a struct.
* If an integer, parse an integer.
* ...
More formally, `libserialize` implements a LL(0) grammar, whereas `json::Json` requires a LL(1) grammar. `rust-serde` provides this by implementing a serializer and deserializer that produces a tagged token stream of values. This enables a `Deserializable` for `json::Json` to look at the next token before deciding on how to parse the value.
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
---
There is now also a new library variation called `serde2`. This removes the need for tagged values and replaces them with a `Visitor` pattern. This pattern is very similar to the `Iterator` pattern, but it threads some custom state through visiting each type. This gets many of the benefits of the `serde` library without needing to always pay for tagging the variants.
You may be looking for:
- [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
```rust
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
// Convert the Point to a JSON string.
let serialized = serde_json::to_string(&point).unwrap();
// 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);
}
```
## Getting help
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.
## License
Serde is licensed under either of
* 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)
at your option.
### Contribution
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'
-417
View File
@@ -1,417 +0,0 @@
#![feature(custom_derive, plugin, test)]
#![plugin(serde_macros)]
extern crate serde;
extern crate "rustc-serialize" as 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)]
#[derive_deserialize]
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 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;
enum State {
AnimalState(Animal),
IsizeState(isize),
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::AnimalState(Animal::Dog)) => {
self.stack.push(State::UnitState);
visitor.visit_enum("Animal", "Dog", DogVisitor {
de: self,
})
}
Some(State::AnimalState(Animal::Frog(x0, x1))) => {
self.stack.push(State::IsizeState(x1));
self.stack.push(State::StringState(x0));
visitor.visit_enum("Animal", "Frog", FrogVisitor {
de: self,
state: 0,
})
}
Some(State::IsizeState(value)) => {
visitor.visit_isize(value)
}
Some(State::StringState(value)) => {
visitor.visit_string(value)
}
Some(State::UnitState) => {
visitor.visit_unit()
}
None => {
Err(Error::EndOfStreamError)
}
}
}
}
struct DogVisitor<'a> {
de: &'a mut AnimalDeserializer,
}
impl<'a> de::EnumVisitor for DogVisitor<'a> {
type Error = Error;
fn visit_unit(&mut self) -> Result<(), Error> {
de::Deserialize::deserialize(self.de)
}
}
struct FrogVisitor<'a> {
de: &'a mut AnimalDeserializer,
state: usize,
}
impl<'a> de::EnumVisitor for FrogVisitor<'a> {
type Error = Error;
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::EnumSeqVisitor,
{
visitor.visit(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);
})
}
-1212
View File
File diff suppressed because it is too large Load Diff
-462
View File
@@ -1,462 +0,0 @@
#![feature(custom_derive, core, plugin, test)]
#![plugin(serde_macros)]
extern crate serde;
extern crate "rustc-serialize" as 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 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 range(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 range(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 range(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 range(0, 100) {
m.insert(i.to_string(), i);
}
run_deserializer(deserializer::IsizeDeserializer::new(m.clone()), m)
})
}
-726
View File
@@ -1,726 +0,0 @@
#![feature(custom_derive, plugin, test)]
#![plugin(serde_macros)]
extern crate serde;
extern crate "rustc-serialize" as 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)]
#[derive_deserialize]
struct Inner {
a: (),
b: usize,
c: HashMap<String, Option<char>>,
}
//////////////////////////////////////////////////////////////////////////////
#[derive(Clone, PartialEq, Debug, RustcDecodable)]
#[derive_deserialize]
struct Outer {
inner: Vec<Inner>,
}
//////////////////////////////////////////////////////////////////////////////
#[derive(Debug)]
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 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::OuterState(Outer { inner })) => {
self.stack.push(State::VecState(inner));
self.stack.push(State::StrState("inner"));
visitor.visit_named_map("Outer", OuterMapVisitor {
de: self,
state: 0,
})
}
Some(State::InnerState(Inner { a: (), b, c })) => {
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_named_map("Inner", InnerMapVisitor {
de: self,
state: 0,
})
}
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)
}
None => Err(Error::EndOfStream),
}
}
}
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 == 1 {
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: Outer = Decodable::decode(&mut d).unwrap();
assert_eq!(value, 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: Outer = Decodable::decode(&mut d).unwrap();
assert_eq!(value, 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: Outer = Decodable::decode(&mut d).unwrap();
assert_eq!(value, 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: Outer = Deserialize::deserialize(&mut d).unwrap();
assert_eq!(value, 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: Outer = Deserialize::deserialize(&mut d).unwrap();
assert_eq!(value, 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: Outer = Deserialize::deserialize(&mut d).unwrap();
assert_eq!(value, outer);
})
}
-615
View File
@@ -1,615 +0,0 @@
#![feature(core, plugin, test)]
#![plugin(serde_macros)]
extern crate serde;
extern crate "rustc-serialize" as 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 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> = range(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> = range(0u8, 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> = range(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> = range(0u8, 100).collect();
run_deserializer(deserializer::Deserializer::new(v.clone()), v)
})
}
+35
View File
@@ -0,0 +1,35 @@
[package]
name = "serde"
version = "0.9.13"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://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" }
[features]
default = ["std"]
derive = ["serde_derive"]
std = []
unstable = []
alloc = ["unstable"]
collections = ["alloc"]
unstable-testing = ["unstable", "std"]
# to get serde_derive picked up by play.integer32.com
playground = ["serde_derive"]
[dependencies]
serde_derive = { version = "0.9", optional = true, path = "../serde_derive" }
[dev-dependencies]
serde_derive = { version = "0.9", path = "../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
+315
View File
@@ -0,0 +1,315 @@
//! Wrapper types to enable optimized handling of `&[u8]` and `Vec<u8>`.
//!
//! Without specialization, Rust forces us to treat `&[u8]` just like any other
//! slice and `Vec<u8>` just like any other vector. In reality this particular
//! slice and vector can often be serialized and deserialized in a more
//! efficient, compact representation in many formats.
//!
//! When working with such a format, you can opt into specialized handling of
//! `&[u8]` by wrapping it in `bytes::Bytes` and `Vec<u8>` by wrapping it in
//! `bytes::ByteBuf`.
//!
//! Rust support for specialization is being tracked in
//! [rust-lang/rust#31844][specialization]. Once it lands in the stable compiler
//! we will be deprecating these wrapper types in favor of optimizing `&[u8]`
//! and `Vec<u8>` out of the box.
//!
//! [specialization]: https://github.com/rust-lang/rust/issues/31844
use core::{ops, fmt, char, iter, slice};
use core::fmt::Write;
use ser;
#[cfg(any(feature = "std", feature = "collections"))]
pub use self::bytebuf::ByteBuf;
#[cfg(any(feature = "std", feature = "collections"))]
#[doc(hidden)] // does anybody need this?
pub use self::bytebuf::ByteBufVisitor;
#[cfg(feature = "collections")]
use collections::Vec;
///////////////////////////////////////////////////////////////////////////////
/// Wraps a `&[u8]` in order to serialize in an efficient way. Does not support
/// deserialization.
///
/// ```rust
/// # #[macro_use] extern crate serde_derive;
/// # extern crate serde;
/// # use std::net::IpAddr;
/// #
/// use serde::bytes::Bytes;
///
/// # #[allow(dead_code)]
/// #[derive(Serialize)]
/// struct Packet<'a> {
/// destination: IpAddr,
/// payload: Bytes<'a>,
/// }
/// #
/// # fn main() {}
/// ```
#[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct Bytes<'a> {
bytes: &'a [u8],
}
impl<'a> Bytes<'a> {
/// Wrap an existing `&[u8]`.
pub fn new(bytes: &'a [u8]) -> Self {
Bytes { bytes: bytes }
}
}
impl<'a> fmt::Debug for Bytes<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(f.write_str("b\""));
for c in escape_bytestring(self.bytes) {
try!(f.write_char(c));
}
f.write_char('"')
}
}
impl<'a> From<&'a [u8]> for Bytes<'a> {
fn from(bytes: &'a [u8]) -> Self {
Bytes::new(bytes)
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a> From<&'a Vec<u8>> for Bytes<'a> {
fn from(bytes: &'a Vec<u8>) -> Self {
Bytes::new(bytes)
}
}
impl<'a> Into<&'a [u8]> for Bytes<'a> {
fn into(self) -> &'a [u8] {
self.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: S) -> Result<S::Ok, S::Error>
where S: ser::Serializer
{
serializer.serialize_bytes(self.bytes)
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))]
mod bytebuf {
use core::cmp;
use core::ops;
use core::fmt;
use core::fmt::Write;
use ser;
use de;
#[cfg(feature = "collections")]
use collections::{String, Vec};
/// Wraps a `Vec<u8>` in order to serialize and deserialize in an efficient
/// way.
///
/// ```rust
/// # #[macro_use] extern crate serde_derive;
/// # extern crate serde;
/// # use std::net::IpAddr;
/// #
/// use serde::bytes::ByteBuf;
///
/// # #[allow(dead_code)]
/// #[derive(Serialize, Deserialize)]
/// struct Packet {
/// destination: IpAddr,
/// payload: ByteBuf,
/// }
/// #
/// # fn main() {}
/// ```
#[derive(Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct ByteBuf {
bytes: Vec<u8>,
}
impl ByteBuf {
/// Construct a new, empty `ByteBuf`.
pub fn new() -> Self {
ByteBuf::from(Vec::new())
}
/// Construct a new, empty `ByteBuf` with the specified capacity.
pub fn with_capacity(cap: usize) -> Self {
ByteBuf::from(Vec::with_capacity(cap))
}
/// Wrap existing bytes in a `ByteBuf`.
pub fn from<T: Into<Vec<u8>>>(bytes: T) -> Self {
ByteBuf { bytes: bytes.into() }
}
}
impl fmt::Debug for ByteBuf {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(f.write_str("b\""));
for c in super::escape_bytestring(self.bytes.as_ref()) {
try!(f.write_char(c));
}
f.write_char('"')
}
}
impl Into<Vec<u8>> for ByteBuf {
fn into(self) -> Vec<u8> {
self.bytes
}
}
impl From<Vec<u8>> for ByteBuf {
fn from(bytes: Vec<u8>) -> Self {
ByteBuf::from(bytes)
}
}
impl AsRef<Vec<u8>> for ByteBuf {
fn as_ref(&self) -> &Vec<u8> {
&self.bytes
}
}
impl AsRef<[u8]> for ByteBuf {
fn as_ref(&self) -> &[u8] {
&self.bytes
}
}
impl AsMut<Vec<u8>> for ByteBuf {
fn as_mut(&mut self) -> &mut Vec<u8> {
&mut self.bytes
}
}
impl AsMut<[u8]> for ByteBuf {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.bytes
}
}
impl ops::Deref for ByteBuf {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.bytes[..]
}
}
impl ops::DerefMut for ByteBuf {
fn deref_mut(&mut self) -> &mut [u8] {
&mut self.bytes[..]
}
}
impl ser::Serialize for ByteBuf {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: ser::Serializer
{
serializer.serialize_bytes(self)
}
}
/// This type implements the `serde::de::Visitor` trait for a `ByteBuf`.
pub struct ByteBufVisitor;
impl de::Visitor for ByteBufVisitor {
type Value = ByteBuf;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("byte array")
}
#[inline]
fn visit_unit<E>(self) -> Result<ByteBuf, E>
where E: de::Error
{
Ok(ByteBuf::new())
}
#[inline]
fn visit_seq<V>(self, mut visitor: V) -> Result<ByteBuf, V::Error>
where V: de::SeqVisitor
{
let len = cmp::min(visitor.size_hint().0, 4096);
let mut values = Vec::with_capacity(len);
while let Some(value) = try!(visitor.visit()) {
values.push(value);
}
Ok(ByteBuf::from(values))
}
#[inline]
fn visit_bytes<E>(self, v: &[u8]) -> Result<ByteBuf, E>
where E: de::Error
{
Ok(ByteBuf::from(v))
}
#[inline]
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<ByteBuf, E>
where E: de::Error
{
Ok(ByteBuf::from(v))
}
fn visit_str<E>(self, v: &str) -> Result<ByteBuf, E>
where E: de::Error
{
Ok(ByteBuf::from(v))
}
fn visit_string<E>(self, v: String) -> Result<ByteBuf, E>
where E: de::Error
{
Ok(ByteBuf::from(v))
}
}
impl de::Deserialize for ByteBuf {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<ByteBuf, D::Error>
where D: de::Deserializer
{
deserializer.deserialize_byte_buf(ByteBufVisitor)
}
}
}
///////////////////////////////////////////////////////////////////////////////
#[inline]
fn escape_bytestring<'a>
(bytes: &'a [u8])
-> iter::FlatMap<slice::Iter<'a, u8>, char::EscapeDefault, fn(&u8) -> char::EscapeDefault> {
fn f(b: &u8) -> char::EscapeDefault {
char::from_u32(*b as u32).unwrap().escape_default()
}
bytes.iter().flat_map(f as fn(&u8) -> char::EscapeDefault)
}
File diff suppressed because it is too large Load Diff
+409
View File
@@ -0,0 +1,409 @@
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Extracted from https://github.com/rust-num/num.
// Rust 1.5 is unhappy that this private module is undocumented.
#![allow(missing_docs)]
use core::{usize, u8, u16, u32, u64};
use core::{isize, i8, i16, i32, i64};
use core::{f32, f64};
use core::mem::size_of;
/// Numbers which have upper and lower bounds
pub trait Bounded {
// FIXME (#5527): These should be associated constants
/// returns the smallest finite number this type can represent
fn min_value() -> Self;
/// returns the largest finite number this type can represent
fn max_value() -> Self;
}
macro_rules! bounded_impl {
($t:ty, $min:expr, $max:expr) => {
impl Bounded for $t {
#[inline]
fn min_value() -> $t { $min }
#[inline]
fn max_value() -> $t { $max }
}
}
}
bounded_impl!(usize, usize::MIN, usize::MAX);
bounded_impl!(u8, u8::MIN, u8::MAX);
bounded_impl!(u16, u16::MIN, u16::MAX);
bounded_impl!(u32, u32::MIN, u32::MAX);
bounded_impl!(u64, u64::MIN, u64::MAX);
bounded_impl!(isize, isize::MIN, isize::MAX);
bounded_impl!(i8, i8::MIN, i8::MAX);
bounded_impl!(i16, i16::MIN, i16::MAX);
bounded_impl!(i32, i32::MIN, i32::MAX);
bounded_impl!(i64, i64::MIN, i64::MAX);
bounded_impl!(f32, f32::MIN, f32::MAX);
bounded_impl!(f64, f64::MIN, f64::MAX);
/// A generic trait for converting a value to a number.
pub trait ToPrimitive {
/// Converts the value of `self` to an `isize`.
#[inline]
fn to_isize(&self) -> Option<isize> {
self.to_i64().and_then(|x| x.to_isize())
}
/// Converts the value of `self` to an `i8`.
#[inline]
fn to_i8(&self) -> Option<i8> {
self.to_i64().and_then(|x| x.to_i8())
}
/// Converts the value of `self` to an `i16`.
#[inline]
fn to_i16(&self) -> Option<i16> {
self.to_i64().and_then(|x| x.to_i16())
}
/// Converts the value of `self` to an `i32`.
#[inline]
fn to_i32(&self) -> Option<i32> {
self.to_i64().and_then(|x| x.to_i32())
}
/// Converts the value of `self` to an `i64`.
fn to_i64(&self) -> Option<i64>;
/// Converts the value of `self` to a `usize`.
#[inline]
fn to_usize(&self) -> Option<usize> {
self.to_u64().and_then(|x| x.to_usize())
}
/// Converts the value of `self` to an `u8`.
#[inline]
fn to_u8(&self) -> Option<u8> {
self.to_u64().and_then(|x| x.to_u8())
}
/// Converts the value of `self` to an `u16`.
#[inline]
fn to_u16(&self) -> Option<u16> {
self.to_u64().and_then(|x| x.to_u16())
}
/// Converts the value of `self` to an `u32`.
#[inline]
fn to_u32(&self) -> Option<u32> {
self.to_u64().and_then(|x| x.to_u32())
}
/// Converts the value of `self` to an `u64`.
#[inline]
fn to_u64(&self) -> Option<u64>;
/// Converts the value of `self` to an `f32`.
#[inline]
fn to_f32(&self) -> Option<f32> {
self.to_f64().and_then(|x| x.to_f32())
}
/// Converts the value of `self` to an `f64`.
#[inline]
fn to_f64(&self) -> Option<f64> {
self.to_i64().and_then(|x| x.to_f64())
}
}
macro_rules! impl_to_primitive_int_to_int {
($SrcT:ty, $DstT:ty, $slf:expr) => (
{
if size_of::<$SrcT>() <= size_of::<$DstT>() {
Some($slf as $DstT)
} else {
let n = $slf as i64;
let min_value: $DstT = Bounded::min_value();
let max_value: $DstT = Bounded::max_value();
if min_value as i64 <= n && n <= max_value as i64 {
Some($slf as $DstT)
} else {
None
}
}
}
)
}
macro_rules! impl_to_primitive_int_to_uint {
($SrcT:ty, $DstT:ty, $slf:expr) => (
{
let zero: $SrcT = 0;
let max_value: $DstT = Bounded::max_value();
if zero <= $slf && $slf as u64 <= max_value as u64 {
Some($slf as $DstT)
} else {
None
}
}
)
}
macro_rules! impl_to_primitive_int {
($T:ty) => (
impl ToPrimitive for $T {
#[inline]
fn to_isize(&self) -> Option<isize> { impl_to_primitive_int_to_int!($T, isize, *self) }
#[inline]
fn to_i8(&self) -> Option<i8> { impl_to_primitive_int_to_int!($T, i8, *self) }
#[inline]
fn to_i16(&self) -> Option<i16> { impl_to_primitive_int_to_int!($T, i16, *self) }
#[inline]
fn to_i32(&self) -> Option<i32> { impl_to_primitive_int_to_int!($T, i32, *self) }
#[inline]
fn to_i64(&self) -> Option<i64> { impl_to_primitive_int_to_int!($T, i64, *self) }
#[inline]
fn to_usize(&self) -> Option<usize> { impl_to_primitive_int_to_uint!($T, usize, *self) }
#[inline]
fn to_u8(&self) -> Option<u8> { impl_to_primitive_int_to_uint!($T, u8, *self) }
#[inline]
fn to_u16(&self) -> Option<u16> { impl_to_primitive_int_to_uint!($T, u16, *self) }
#[inline]
fn to_u32(&self) -> Option<u32> { impl_to_primitive_int_to_uint!($T, u32, *self) }
#[inline]
fn to_u64(&self) -> Option<u64> { impl_to_primitive_int_to_uint!($T, u64, *self) }
#[inline]
fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
#[inline]
fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
}
)
}
impl_to_primitive_int! { isize }
impl_to_primitive_int! { i8 }
impl_to_primitive_int! { i16 }
impl_to_primitive_int! { i32 }
impl_to_primitive_int! { i64 }
macro_rules! impl_to_primitive_uint_to_int {
($DstT:ty, $slf:expr) => (
{
let max_value: $DstT = Bounded::max_value();
if $slf as u64 <= max_value as u64 {
Some($slf as $DstT)
} else {
None
}
}
)
}
macro_rules! impl_to_primitive_uint_to_uint {
($SrcT:ty, $DstT:ty, $slf:expr) => (
{
if size_of::<$SrcT>() <= size_of::<$DstT>() {
Some($slf as $DstT)
} else {
let zero: $SrcT = 0;
let max_value: $DstT = Bounded::max_value();
if zero <= $slf && $slf as u64 <= max_value as u64 {
Some($slf as $DstT)
} else {
None
}
}
}
)
}
macro_rules! impl_to_primitive_uint {
($T:ty) => (
impl ToPrimitive for $T {
#[inline]
fn to_isize(&self) -> Option<isize> { impl_to_primitive_uint_to_int!(isize, *self) }
#[inline]
fn to_i8(&self) -> Option<i8> { impl_to_primitive_uint_to_int!(i8, *self) }
#[inline]
fn to_i16(&self) -> Option<i16> { impl_to_primitive_uint_to_int!(i16, *self) }
#[inline]
fn to_i32(&self) -> Option<i32> { impl_to_primitive_uint_to_int!(i32, *self) }
#[inline]
fn to_i64(&self) -> Option<i64> { impl_to_primitive_uint_to_int!(i64, *self) }
#[inline]
fn to_usize(&self) -> Option<usize> {
impl_to_primitive_uint_to_uint!($T, usize, *self)
}
#[inline]
fn to_u8(&self) -> Option<u8> { impl_to_primitive_uint_to_uint!($T, u8, *self) }
#[inline]
fn to_u16(&self) -> Option<u16> { impl_to_primitive_uint_to_uint!($T, u16, *self) }
#[inline]
fn to_u32(&self) -> Option<u32> { impl_to_primitive_uint_to_uint!($T, u32, *self) }
#[inline]
fn to_u64(&self) -> Option<u64> { impl_to_primitive_uint_to_uint!($T, u64, *self) }
#[inline]
fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
#[inline]
fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
}
)
}
impl_to_primitive_uint! { usize }
impl_to_primitive_uint! { u8 }
impl_to_primitive_uint! { u16 }
impl_to_primitive_uint! { u32 }
impl_to_primitive_uint! { u64 }
macro_rules! impl_to_primitive_float_to_float {
($SrcT:ident, $DstT:ident, $slf:expr) => (
if size_of::<$SrcT>() <= size_of::<$DstT>() {
Some($slf as $DstT)
} else {
let n = $slf as f64;
let max_value: $SrcT = ::core::$SrcT::MAX;
if -max_value as f64 <= n && n <= max_value as f64 {
Some($slf as $DstT)
} else {
None
}
}
)
}
macro_rules! impl_to_primitive_float {
($T:ident) => (
impl ToPrimitive for $T {
#[inline]
fn to_isize(&self) -> Option<isize> { Some(*self as isize) }
#[inline]
fn to_i8(&self) -> Option<i8> { Some(*self as i8) }
#[inline]
fn to_i16(&self) -> Option<i16> { Some(*self as i16) }
#[inline]
fn to_i32(&self) -> Option<i32> { Some(*self as i32) }
#[inline]
fn to_i64(&self) -> Option<i64> { Some(*self as i64) }
#[inline]
fn to_usize(&self) -> Option<usize> { Some(*self as usize) }
#[inline]
fn to_u8(&self) -> Option<u8> { Some(*self as u8) }
#[inline]
fn to_u16(&self) -> Option<u16> { Some(*self as u16) }
#[inline]
fn to_u32(&self) -> Option<u32> { Some(*self as u32) }
#[inline]
fn to_u64(&self) -> Option<u64> { Some(*self as u64) }
#[inline]
fn to_f32(&self) -> Option<f32> { impl_to_primitive_float_to_float!($T, f32, *self) }
#[inline]
fn to_f64(&self) -> Option<f64> { impl_to_primitive_float_to_float!($T, f64, *self) }
}
)
}
impl_to_primitive_float! { f32 }
impl_to_primitive_float! { f64 }
pub trait FromPrimitive: Sized {
#[inline]
fn from_isize(n: isize) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
#[inline]
fn from_i8(n: i8) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
fn from_i64(n: i64) -> Option<Self>;
#[inline]
fn from_usize(n: usize) -> Option<Self> {
FromPrimitive::from_u64(n as u64)
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
FromPrimitive::from_u64(n as u64)
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
FromPrimitive::from_u64(n as u64)
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
FromPrimitive::from_u64(n as u64)
}
fn from_u64(n: u64) -> Option<Self>;
#[inline]
fn from_f32(n: f32) -> Option<Self> {
FromPrimitive::from_f64(n as f64)
}
#[inline]
fn from_f64(n: f64) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
}
macro_rules! impl_from_primitive {
($T:ty, $to_ty:ident) => (
impl FromPrimitive for $T {
#[inline] fn from_i8(n: i8) -> Option<$T> { n.$to_ty() }
#[inline] fn from_i16(n: i16) -> Option<$T> { n.$to_ty() }
#[inline] fn from_i32(n: i32) -> Option<$T> { n.$to_ty() }
#[inline] fn from_i64(n: i64) -> Option<$T> { n.$to_ty() }
#[inline] fn from_u8(n: u8) -> Option<$T> { n.$to_ty() }
#[inline] fn from_u16(n: u16) -> Option<$T> { n.$to_ty() }
#[inline] fn from_u32(n: u32) -> Option<$T> { n.$to_ty() }
#[inline] fn from_u64(n: u64) -> Option<$T> { n.$to_ty() }
#[inline] fn from_f32(n: f32) -> Option<$T> { n.$to_ty() }
#[inline] fn from_f64(n: f64) -> Option<$T> { n.$to_ty() }
}
)
}
impl_from_primitive! { isize, to_isize }
impl_from_primitive! { i8, to_i8 }
impl_from_primitive! { i16, to_i16 }
impl_from_primitive! { i32, to_i32 }
impl_from_primitive! { i64, to_i64 }
impl_from_primitive! { usize, to_usize }
impl_from_primitive! { u8, to_u8 }
impl_from_primitive! { u16, to_u16 }
impl_from_primitive! { u32, to_u32 }
impl_from_primitive! { u64, to_u64 }
impl_from_primitive! { f32, to_f32 }
impl_from_primitive! { f64, to_f64 }
File diff suppressed because it is too large Load Diff
+1531
View File
File diff suppressed because it is too large Load Diff
+44
View File
@@ -0,0 +1,44 @@
use core::marker::PhantomData;
use de::{Deserialize, Deserializer, Error, Visitor};
#[cfg(any(feature = "std", feature = "collections"))]
pub use de::content::{Content, ContentRefDeserializer, ContentDeserializer, TaggedContentVisitor,
TagOrContentField, TagOrContentFieldVisitor, InternallyTaggedUnitVisitor,
UntaggedUnitVisitor};
/// If the missing field is of type `Option<T>` then treat is as `None`,
/// otherwise it is an error.
pub fn missing_field<V, E>(field: &'static str) -> Result<V, E>
where V: Deserialize,
E: Error
{
struct MissingFieldDeserializer<E>(&'static str, PhantomData<E>);
impl<E> Deserializer for MissingFieldDeserializer<E>
where E: Error
{
type Error = E;
fn deserialize<V>(self, _visitor: V) -> Result<V::Value, E>
where V: Visitor
{
Err(Error::missing_field(self.0))
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, E>
where V: Visitor
{
visitor.visit_none()
}
forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
seq_fixed_size bytes byte_buf map unit_struct newtype_struct
tuple_struct struct struct_field tuple enum ignored_any
}
}
let deserializer = MissingFieldDeserializer(field, PhantomData);
Deserialize::deserialize(deserializer)
}
File diff suppressed because it is too large Load Diff
+17
View File
@@ -0,0 +1,17 @@
//! A stand-in for `std::error`
use core::fmt::{Debug, Display};
/// A stand-in for `std::error::Error`, which requires no allocation.
pub trait Error: Debug + Display {
/// A short description of the error.
///
/// The description should not contain newlines or sentence-ending
/// punctuation, to facilitate embedding in larger user-facing
/// strings.
fn description(&self) -> &str;
/// The lower-level cause of this error, if any.
fn cause(&self) -> Option<&Error> {
None
}
}
+36
View File
@@ -0,0 +1,36 @@
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::String;
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::borrow::Cow;
pub use core::clone::Clone;
pub use core::convert::{From, Into};
pub use core::default::Default;
pub use core::fmt;
pub use core::marker::PhantomData;
pub use core::option::Option::{self, None, Some};
pub use core::result::Result::{self, Ok, Err};
#[cfg(any(feature = "collections", feature = "std"))]
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
String::from_utf8_lossy(bytes)
}
// The generated code calls this like:
//
// let value = &_serde::export::from_utf8_lossy(bytes);
// Err(_serde::de::Error::unknown_variant(value, VARIANTS))
//
// so it is okay for the return type to be different from the std case as long
// as the above works.
#[cfg(not(any(feature = "collections", feature = "std")))]
pub fn from_utf8_lossy(bytes: &[u8]) -> &str {
use core::str;
// Three unicode replacement characters if it fails. They look like a
// white-on-black question mark. The user will recognize it as invalid
// UTF-8.
str::from_utf8(bytes).unwrap_or("\u{fffd}\u{fffd}\u{fffd}")
}
+73
View File
@@ -0,0 +1,73 @@
//! Module that contains helper iterators.
use std::io;
use std::iter::Peekable;
/// Iterator over a byte stream that tracks the current position's line and column.
pub struct LineColIterator<Iter: Iterator<Item = io::Result<u8>>> {
iter: Iter,
line: usize,
col: usize,
}
impl<Iter: Iterator<Item = io::Result<u8>>> LineColIterator<Iter> {
/// Construct a new `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(&mut self) -> &mut Iter {
&mut self.iter
}
/// Unwraps this `LineColIterator`, returning the underlying iterator.
pub fn into_inner(self) -> Iter {
self.iter
}
}
impl<Iter: Iterator<Item = io::Result<u8>>> LineColIterator<Peekable<Iter>> {
/// peeks at the next value
pub fn peek(&mut self) -> Option<&io::Result<u8>> {
self.iter.peek()
}
}
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)),
}
}
}
+155
View File
@@ -0,0 +1,155 @@
//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website https://serde.rs/ for additional documentation and
//! usage examples.
//!
//! ### Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's code
//! generation to automatically derive implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform roughly the same speed as a handwritten serializer
//! for the specific selection of data structure and data format.
//!
//! ### Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON](https://github.com/serde-rs/json), the ubiquitous JavaScript Object
//! Notation used by many HTTP APIs.
//! - [Bincode](https://github.com/TyOverby/bincode), a compact binary format
//! used for IPC within the Servo rendering engine.
//! - [CBOR](https://github.com/pyfisch/cbor), a Concise Binary Object
//! Representation designed for small message size without the need for
//! version negotiation.
//! - [YAML](https://github.com/dtolnay/serde-yaml), a popular human-friendly
//! configuration language that ain't markup language.
//! - [MessagePack](https://github.com/3Hren/msgpack-rust), an efficient binary
//! format that resembles a compact JSON.
//! - [TOML](https://github.com/alexcrichton/toml-rs), a minimal configuration
//! format used by [Cargo](http://doc.crates.io/manifest.html).
//! - [Pickle](https://github.com/birkenfeld/serde-pickle), a format common in
//! the Python world.
//! - [Hjson](https://github.com/laktak/hjson-rust), a variant of JSON designed
//! to be readable and writable by humans.
//! - [BSON](https://github.com/zonyitoo/bson-rs), the data storage and network
//! transfer format used by MongoDB.
//! - [URL](https://github.com/nox/serde_urlencoded), the x-www-form-urlencoded
//! format.
//! - [XML](https://github.com/serde-rs/xml), the flexible machine-friendly W3C
//! standard. *(deserialization only)*
//! - [Envy](https://github.com/softprops/envy), a way to deserialize
//! environment variables into Rust structs. *(deserialization only)*
//! - [Redis](https://github.com/OneSignal/serde-redis), deserialize values from
//! Redis when using [redis-rs](https://crates.io/crates/redis).
//! *(deserialization only)*
#![doc(html_root_url="https://docs.serde.rs")]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "unstable", feature(nonzero, specialization, zero_one, into_boxed_c_str))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "collections", feature(collections))]
#![cfg_attr(feature = "cargo-clippy", allow(linkedlist, type_complexity, doc_markdown))]
#![deny(missing_docs)]
#[cfg(feature = "collections")]
extern crate collections;
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "unstable")]
extern crate core as actual_core;
#[cfg(feature = "std")]
mod core {
pub use std::{ops, hash, fmt, cmp, marker, mem, i8, i16, i32, i64, u8, u16, u32, u64, isize,
usize, f32, f64, char, str, num, slice, iter, cell, default, result, option,
clone, convert};
#[cfg(feature = "unstable")]
pub use actual_core::nonzero;
}
#[doc(inline)]
pub use ser::{Serialize, Serializer};
#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[macro_use]
mod macros;
pub mod bytes;
pub mod de;
#[cfg(feature = "std")]
#[doc(hidden)]
pub mod iter;
pub mod ser;
#[cfg_attr(feature = "std", doc(hidden))]
pub mod error;
mod utils;
// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;
// 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::*;
+207
View File
@@ -0,0 +1,207 @@
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_method {
($func:ident($($arg:ty),*)) => {
#[inline]
fn $func<__V>(self, $(_: $arg,)* visitor: __V) -> $crate::export::Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor
{
self.deserialize(visitor)
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_helper {
(bool) => {
forward_to_deserialize_method!{deserialize_bool()}
};
(u8) => {
forward_to_deserialize_method!{deserialize_u8()}
};
(u16) => {
forward_to_deserialize_method!{deserialize_u16()}
};
(u32) => {
forward_to_deserialize_method!{deserialize_u32()}
};
(u64) => {
forward_to_deserialize_method!{deserialize_u64()}
};
(i8) => {
forward_to_deserialize_method!{deserialize_i8()}
};
(i16) => {
forward_to_deserialize_method!{deserialize_i16()}
};
(i32) => {
forward_to_deserialize_method!{deserialize_i32()}
};
(i64) => {
forward_to_deserialize_method!{deserialize_i64()}
};
(f32) => {
forward_to_deserialize_method!{deserialize_f32()}
};
(f64) => {
forward_to_deserialize_method!{deserialize_f64()}
};
(char) => {
forward_to_deserialize_method!{deserialize_char()}
};
(str) => {
forward_to_deserialize_method!{deserialize_str()}
};
(string) => {
forward_to_deserialize_method!{deserialize_string()}
};
(unit) => {
forward_to_deserialize_method!{deserialize_unit()}
};
(option) => {
forward_to_deserialize_method!{deserialize_option()}
};
(seq) => {
forward_to_deserialize_method!{deserialize_seq()}
};
(seq_fixed_size) => {
forward_to_deserialize_method!{deserialize_seq_fixed_size(usize)}
};
(bytes) => {
forward_to_deserialize_method!{deserialize_bytes()}
};
(byte_buf) => {
forward_to_deserialize_method!{deserialize_byte_buf()}
};
(map) => {
forward_to_deserialize_method!{deserialize_map()}
};
(unit_struct) => {
forward_to_deserialize_method!{deserialize_unit_struct(&'static str)}
};
(newtype_struct) => {
forward_to_deserialize_method!{deserialize_newtype_struct(&'static str)}
};
(tuple_struct) => {
forward_to_deserialize_method!{deserialize_tuple_struct(&'static str, usize)}
};
(struct) => {
forward_to_deserialize_method!{deserialize_struct(&'static str, &'static [&'static str])}
};
(struct_field) => {
forward_to_deserialize_method!{deserialize_struct_field()}
};
(tuple) => {
forward_to_deserialize_method!{deserialize_tuple(usize)}
};
(enum) => {
forward_to_deserialize_method!{deserialize_enum(&'static str, &'static [&'static str])}
};
(ignored_any) => {
forward_to_deserialize_method!{deserialize_ignored_any()}
};
}
// Super explicit first paragraph because this shows up at the top level and
// trips up people who are just looking for basic Serialize / Deserialize
// documentation.
//
/// Helper macro when implementing the `Deserializer` part of a new data format
/// for Serde.
///
/// Some `Deserializer` implementations for self-describing formats do not care
/// what hint the `Visitor` gives them, they just want to blindly call the
/// `Visitor` method corresponding to the data they can tell is in the input.
/// This requires repetitive implementations of all the `Deserializer` trait
/// methods.
///
/// ```rust
/// # #[macro_use] extern crate serde;
/// # use serde::de::{value, Deserializer, Visitor};
/// # pub struct MyDeserializer;
/// # impl Deserializer for MyDeserializer {
/// # type Error = value::Error;
/// # fn deserialize<V>(self, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor
/// # { unimplemented!() }
/// #
/// #[inline]
/// fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor
/// {
/// self.deserialize(visitor)
/// }
/// # forward_to_deserialize! {
/// # u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
/// # seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
/// # tuple_struct struct struct_field tuple enum ignored_any
/// # }
/// # }
/// # fn main() {}
/// ```
///
/// The `forward_to_deserialize!` macro implements these simple forwarding
/// methods so that they forward directly to `Deserializer::deserialize`. You
/// can choose which methods to forward.
///
/// ```rust
/// # #[macro_use] extern crate serde;
/// # use serde::de::{value, Deserializer, Visitor};
/// # pub struct MyDeserializer;
/// impl Deserializer for MyDeserializer {
/// # type Error = value::Error;
/// fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor
/// {
/// /* ... */
/// # let _ = visitor;
/// # unimplemented!()
/// }
///
/// forward_to_deserialize! {
/// bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
/// seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
/// tuple_struct struct struct_field tuple enum ignored_any
/// }
/// }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! forward_to_deserialize {
($($func:ident)*) => {
$(forward_to_deserialize_helper!{$func})*
};
}
/// Seralize the `$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")]
// Not exported
macro_rules! serialize_display_bounded_length {
($value: expr, $MAX_LEN: expr, $serializer: expr) => {
{
use std::io::Write;
let mut buffer: [u8; $MAX_LEN] = unsafe { ::std::mem::uninitialized() };
let remaining_len;
{
let mut remaining = &mut buffer[..];
write!(remaining, "{}", $value).unwrap();
remaining_len = remaining.len()
}
let written_len = buffer.len() - remaining_len;
let written = &buffer[..written_len];
// write! only provides std::fmt::Formatter to Display implementations,
// which has methods write_str and write_char but no method to write arbitrary bytes.
// Therefore, `written` is well-formed in UTF-8.
let written_str = unsafe {
::std::str::from_utf8_unchecked(written)
};
$serializer.serialize_str(written_str)
}
}
}
+607
View File
@@ -0,0 +1,607 @@
use core::marker::PhantomData;
#[cfg(all(not(feature = "std"), feature = "collections"))]
use collections::{String, Vec};
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::boxed::Box;
#[cfg(feature = "collections")]
use collections::borrow::ToOwned;
use ser::{self, Serialize, Serializer};
pub struct SerializeTupleVariantAsMapValue<M> {
map: M,
name: &'static str,
fields: Vec<Content>,
}
impl<M> SerializeTupleVariantAsMapValue<M> {
pub fn new(map: M, name: &'static str, len: usize) -> Self {
SerializeTupleVariantAsMapValue {
map: map,
name: name,
fields: Vec::with_capacity(len),
}
}
}
impl<M> ser::SerializeTupleVariant for SerializeTupleVariantAsMapValue<M>
where M: ser::SerializeMap
{
type Ok = M::Ok;
type Error = M::Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), M::Error> {
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push(value);
Ok(())
}
fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self.map.serialize_value(&Content::TupleStruct(self.name, self.fields)));
self.map.end()
}
}
pub struct SerializeStructVariantAsMapValue<M> {
map: M,
name: &'static str,
fields: Vec<(&'static str, Content)>,
}
impl<M> SerializeStructVariantAsMapValue<M> {
pub fn new(map: M, name: &'static str, len: usize) -> Self {
SerializeStructVariantAsMapValue {
map: map,
name: name,
fields: Vec::with_capacity(len),
}
}
}
impl<M> ser::SerializeStructVariant for SerializeStructVariantAsMapValue<M>
where M: ser::SerializeMap
{
type Ok = M::Ok;
type Error = M::Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
key: &'static str,
value: &T)
-> Result<(), M::Error> {
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push((key, value));
Ok(())
}
fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self.map.serialize_value(&Content::Struct(self.name, self.fields)));
self.map.end()
}
}
#[derive(Debug)]
enum Content {
Bool(bool),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
F32(f32),
F64(f64),
Char(char),
String(String),
Bytes(Vec<u8>),
None,
Some(Box<Content>),
Unit,
UnitStruct(&'static str),
UnitVariant(&'static str, usize, &'static str),
NewtypeStruct(&'static str, Box<Content>),
NewtypeVariant(&'static str, usize, &'static str, Box<Content>),
Seq(Vec<Content>),
SeqFixedSize(Vec<Content>),
Tuple(Vec<Content>),
TupleStruct(&'static str, Vec<Content>),
TupleVariant(&'static str, usize, &'static str, Vec<Content>),
Map(Vec<(Content, Content)>),
Struct(&'static str, Vec<(&'static str, Content)>),
StructVariant(&'static str, usize, &'static str, Vec<(&'static str, Content)>),
}
impl Serialize for Content {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
match *self {
Content::Bool(b) => serializer.serialize_bool(b),
Content::U8(u) => serializer.serialize_u8(u),
Content::U16(u) => serializer.serialize_u16(u),
Content::U32(u) => serializer.serialize_u32(u),
Content::U64(u) => serializer.serialize_u64(u),
Content::I8(i) => serializer.serialize_i8(i),
Content::I16(i) => serializer.serialize_i16(i),
Content::I32(i) => serializer.serialize_i32(i),
Content::I64(i) => serializer.serialize_i64(i),
Content::F32(f) => serializer.serialize_f32(f),
Content::F64(f) => serializer.serialize_f64(f),
Content::Char(c) => serializer.serialize_char(c),
Content::String(ref s) => serializer.serialize_str(s),
Content::Bytes(ref b) => serializer.serialize_bytes(b),
Content::None => serializer.serialize_none(),
Content::Some(ref c) => serializer.serialize_some(&**c),
Content::Unit => serializer.serialize_unit(),
Content::UnitStruct(n) => serializer.serialize_unit_struct(n),
Content::UnitVariant(n, i, v) => serializer.serialize_unit_variant(n, i, v),
Content::NewtypeStruct(n, ref c) => serializer.serialize_newtype_struct(n, &**c),
Content::NewtypeVariant(n, i, v, ref c) => {
serializer.serialize_newtype_variant(n, i, v, &**c)
}
Content::Seq(ref elements) => elements.serialize(serializer),
Content::SeqFixedSize(ref elements) => {
use ser::SerializeSeq;
let mut seq = try!(serializer.serialize_seq_fixed_size(elements.len()));
for e in elements {
try!(seq.serialize_element(e));
}
seq.end()
}
Content::Tuple(ref elements) => {
use ser::SerializeTuple;
let mut tuple = try!(serializer.serialize_tuple(elements.len()));
for e in elements {
try!(tuple.serialize_element(e));
}
tuple.end()
}
Content::TupleStruct(n, ref fields) => {
use ser::SerializeTupleStruct;
let mut ts = try!(serializer.serialize_tuple_struct(n, fields.len()));
for f in fields {
try!(ts.serialize_field(f));
}
ts.end()
}
Content::TupleVariant(n, i, v, ref fields) => {
use ser::SerializeTupleVariant;
let mut tv = try!(serializer.serialize_tuple_variant(n, i, v, fields.len()));
for f in fields {
try!(tv.serialize_field(f));
}
tv.end()
}
Content::Map(ref entries) => {
use ser::SerializeMap;
let mut map = try!(serializer.serialize_map(Some(entries.len())));
for &(ref k, ref v) in entries {
try!(map.serialize_entry(k, v));
}
map.end()
}
Content::Struct(n, ref fields) => {
use ser::SerializeStruct;
let mut s = try!(serializer.serialize_struct(n, fields.len()));
for &(k, ref v) in fields {
try!(s.serialize_field(k, v));
}
s.end()
}
Content::StructVariant(n, i, v, ref fields) => {
use ser::SerializeStructVariant;
let mut sv = try!(serializer.serialize_struct_variant(n, i, v, fields.len()));
for &(k, ref v) in fields {
try!(sv.serialize_field(k, v));
}
sv.end()
}
}
}
}
struct ContentSerializer<E> {
error: PhantomData<E>,
}
impl<E> ContentSerializer<E> {
fn new() -> Self {
ContentSerializer { error: PhantomData }
}
}
impl<E> Serializer for ContentSerializer<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
type SerializeSeq = SerializeSeq<E>;
type SerializeTuple = SerializeTuple<E>;
type SerializeTupleStruct = SerializeTupleStruct<E>;
type SerializeTupleVariant = SerializeTupleVariant<E>;
type SerializeMap = SerializeMap<E>;
type SerializeStruct = SerializeStruct<E>;
type SerializeStructVariant = SerializeStructVariant<E>;
fn serialize_bool(self, v: bool) -> Result<Content, E> {
Ok(Content::Bool(v))
}
fn serialize_i8(self, v: i8) -> Result<Content, E> {
Ok(Content::I8(v))
}
fn serialize_i16(self, v: i16) -> Result<Content, E> {
Ok(Content::I16(v))
}
fn serialize_i32(self, v: i32) -> Result<Content, E> {
Ok(Content::I32(v))
}
fn serialize_i64(self, v: i64) -> Result<Content, E> {
Ok(Content::I64(v))
}
fn serialize_u8(self, v: u8) -> Result<Content, E> {
Ok(Content::U8(v))
}
fn serialize_u16(self, v: u16) -> Result<Content, E> {
Ok(Content::U16(v))
}
fn serialize_u32(self, v: u32) -> Result<Content, E> {
Ok(Content::U32(v))
}
fn serialize_u64(self, v: u64) -> Result<Content, E> {
Ok(Content::U64(v))
}
fn serialize_f32(self, v: f32) -> Result<Content, E> {
Ok(Content::F32(v))
}
fn serialize_f64(self, v: f64) -> Result<Content, E> {
Ok(Content::F64(v))
}
fn serialize_char(self, v: char) -> Result<Content, E> {
Ok(Content::Char(v))
}
fn serialize_str(self, value: &str) -> Result<Content, E> {
Ok(Content::String(value.to_owned()))
}
fn serialize_bytes(self, value: &[u8]) -> Result<Content, E> {
Ok(Content::Bytes(value.to_owned()))
}
fn serialize_none(self) -> Result<Content, E> {
Ok(Content::None)
}
fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Content, E> {
Ok(Content::Some(Box::new(try!(value.serialize(self)))))
}
fn serialize_unit(self) -> Result<Content, E> {
Ok(Content::Unit)
}
fn serialize_unit_struct(self, name: &'static str) -> Result<Content, E> {
Ok(Content::UnitStruct(name))
}
fn serialize_unit_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str)
-> Result<Content, E> {
Ok(Content::UnitVariant(name, variant_index, variant))
}
fn serialize_newtype_struct<T: ?Sized + Serialize>(self,
name: &'static str,
value: &T)
-> Result<Content, E> {
Ok(Content::NewtypeStruct(name, Box::new(try!(value.serialize(self)))))
}
fn serialize_newtype_variant<T: ?Sized + Serialize>(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
value: &T)
-> Result<Content, E> {
Ok(Content::NewtypeVariant(name,
variant_index,
variant,
Box::new(try!(value.serialize(self)))))
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, E> {
Ok(SerializeSeq {
fixed_size: false,
elements: Vec::with_capacity(len.unwrap_or(0)),
error: PhantomData,
})
}
fn serialize_seq_fixed_size(self, size: usize) -> Result<Self::SerializeSeq, E> {
Ok(SerializeSeq {
fixed_size: true,
elements: Vec::with_capacity(size),
error: PhantomData,
})
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, E> {
Ok(SerializeTuple {
elements: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_tuple_struct(self,
name: &'static str,
len: usize)
-> Result<Self::SerializeTupleStruct, E> {
Ok(SerializeTupleStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_tuple_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize)
-> Result<Self::SerializeTupleVariant, E> {
Ok(SerializeTupleVariant {
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, E> {
Ok(SerializeMap {
entries: Vec::with_capacity(len.unwrap_or(0)),
key: None,
error: PhantomData,
})
}
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct, E> {
Ok(SerializeStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_struct_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize)
-> Result<Self::SerializeStructVariant, E> {
Ok(SerializeStructVariant {
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
}
struct SerializeSeq<E> {
fixed_size: bool,
elements: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeSeq for SerializeSeq<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.elements.push(value);
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(if self.fixed_size {
Content::SeqFixedSize(self.elements)
} else {
Content::Seq(self.elements)
})
}
}
struct SerializeTuple<E> {
elements: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeTuple for SerializeTuple<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.elements.push(value);
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::Tuple(self.elements))
}
}
struct SerializeTupleStruct<E> {
name: &'static str,
fields: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeTupleStruct for SerializeTupleStruct<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push(value);
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::TupleStruct(self.name, self.fields))
}
}
struct SerializeTupleVariant<E> {
name: &'static str,
variant_index: usize,
variant: &'static str,
fields: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeTupleVariant for SerializeTupleVariant<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push(value);
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::TupleVariant(self.name, self.variant_index, self.variant, self.fields))
}
}
struct SerializeMap<E> {
entries: Vec<(Content, Content)>,
key: Option<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeMap for SerializeMap<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<(), E> {
let key = try!(key.serialize(ContentSerializer::<E>::new()));
self.key = Some(key);
Ok(())
}
fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), E> {
let key = self.key.take().expect("serialize_value called before serialize_key");
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.entries.push((key, value));
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::Map(self.entries))
}
fn serialize_entry<K: ?Sized + Serialize, V: ?Sized + Serialize>(&mut self,
key: &K,
value: &V)
-> Result<(), E> {
let key = try!(key.serialize(ContentSerializer::<E>::new()));
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.entries.push((key, value));
Ok(())
}
}
struct SerializeStruct<E> {
name: &'static str,
fields: Vec<(&'static str, Content)>,
error: PhantomData<E>,
}
impl<E> ser::SerializeStruct for SerializeStruct<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
key: &'static str,
value: &T)
-> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push((key, value));
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::Struct(self.name, self.fields))
}
}
struct SerializeStructVariant<E> {
name: &'static str,
variant_index: usize,
variant: &'static str,
fields: Vec<(&'static str, Content)>,
error: PhantomData<E>,
}
impl<E> ser::SerializeStructVariant for SerializeStructVariant<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
key: &'static str,
value: &T)
-> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push((key, value));
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::StructVariant(self.name, self.variant_index, self.variant, self.fields))
}
}
+761
View File
@@ -0,0 +1,761 @@
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::borrow::Cow;
#[cfg(feature = "std")]
use std::collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, HashMap, HashSet, VecDeque};
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque, String, Vec};
#[cfg(feature = "collections")]
use collections::borrow::ToOwned;
#[cfg(feature = "std")]
use core::hash::{Hash, BuildHasher};
#[cfg(feature = "std")]
use std::net;
#[cfg(any(feature = "std", feature = "unstable"))]
use core::ops;
#[cfg(feature = "std")]
use std::path;
#[cfg(feature = "std")]
use std::ffi::{CString, CStr, OsString, OsStr};
#[cfg(feature = "std")]
use std::rc::Rc;
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::rc::Rc;
#[cfg(feature = "std")]
use std::time::Duration;
#[cfg(feature = "std")]
use std::sync::Arc;
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::arc::Arc;
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::boxed::Box;
use core::marker::PhantomData;
#[cfg(feature = "unstable")]
use core::nonzero::{NonZero, Zeroable};
use super::{Serialize, SerializeSeq, SerializeTuple, Serializer};
#[cfg(feature = "std")]
use super::Error;
///////////////////////////////////////////////////////////////////////////////
macro_rules! impl_visit {
($ty:ty, $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)*)
}
}
}
}
impl_visit!(bool, serialize_bool);
impl_visit!(isize, serialize_i64 as i64);
impl_visit!(i8, serialize_i8);
impl_visit!(i16, serialize_i16);
impl_visit!(i32, serialize_i32);
impl_visit!(i64, serialize_i64);
impl_visit!(usize, serialize_u64 as u64);
impl_visit!(u8, serialize_u8);
impl_visit!(u16, serialize_u16);
impl_visit!(u32, serialize_u32);
impl_visit!(u64, serialize_u64);
impl_visit!(f32, serialize_f32);
impl_visit!(f64, serialize_f64);
impl_visit!(char, serialize_char);
///////////////////////////////////////////////////////////////////////////////
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
{
(&self[..]).serialize(serializer)
}
}
///////////////////////////////////////////////////////////////////////////////
#[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")
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! array_impls {
($len:expr) => {
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_seq_fixed_size($len));
for e in self {
try!(seq.serialize_element(e));
}
seq.end()
}
}
}
}
array_impls!(0);
array_impls!(1);
array_impls!(2);
array_impls!(3);
array_impls!(4);
array_impls!(5);
array_impls!(6);
array_impls!(7);
array_impls!(8);
array_impls!(9);
array_impls!(10);
array_impls!(11);
array_impls!(12);
array_impls!(13);
array_impls!(14);
array_impls!(15);
array_impls!(16);
array_impls!(17);
array_impls!(18);
array_impls!(19);
array_impls!(20);
array_impls!(21);
array_impls!(22);
array_impls!(23);
array_impls!(24);
array_impls!(25);
array_impls!(26);
array_impls!(27);
array_impls!(28);
array_impls!(29);
array_impls!(30);
array_impls!(31);
array_impls!(32);
///////////////////////////////////////////////////////////////////////////////
macro_rules! serialize_seq {
() => {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
serializer.collect_seq(self)
}
}
}
impl<T> Serialize for [T]
where T: Serialize
{
serialize_seq!();
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for BinaryHeap<T>
where T: Serialize + Ord
{
serialize_seq!();
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for BTreeSet<T>
where T: Serialize + Ord
{
serialize_seq!();
}
#[cfg(feature = "std")]
impl<T, H> Serialize for HashSet<T, H>
where T: Serialize + Eq + Hash,
H: BuildHasher
{
serialize_seq!();
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for LinkedList<T>
where T: Serialize
{
serialize_seq!();
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for Vec<T>
where T: Serialize
{
serialize_seq!();
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for VecDeque<T>
where T: Serialize
{
serialize_seq!();
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl<Idx: Serialize> Serialize for ops::Range<Idx> {
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 {
($(
$TupleVisitor:ident ($len:expr, $($T:ident),+) {
$($state:pat => $idx:tt,)+
}
)+) => {
$(
impl<$($T),+> Serialize for ($($T,)+)
where $($T: 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.$idx));
)+
tuple.end()
}
}
)+
}
}
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,
}
TupleVisitor13 (13, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
7 => 7,
8 => 8,
9 => 9,
10 => 10,
11 => 11,
12 => 12,
}
TupleVisitor14 (14, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
7 => 7,
8 => 8,
9 => 9,
10 => 10,
11 => 11,
12 => 12,
13 => 13,
}
TupleVisitor15 (15, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
7 => 7,
8 => 8,
9 => 9,
10 => 10,
11 => 11,
12 => 12,
13 => 13,
14 => 14,
}
TupleVisitor16 (16, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
7 => 7,
8 => 8,
9 => 9,
10 => 10,
11 => 11,
12 => 12,
13 => 13,
14 => 14,
15 => 15,
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! serialize_map {
() => {
#[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"))]
impl<K, V> Serialize for BTreeMap<K, V>
where K: Serialize + Ord,
V: Serialize
{
serialize_map!();
}
#[cfg(feature = "std")]
impl<K, V, H> Serialize for HashMap<K, V, H>
where K: Serialize + Eq + Hash,
V: Serialize,
H: BuildHasher
{
serialize_map!();
}
///////////////////////////////////////////////////////////////////////////////
impl<'a, T: ?Sized> Serialize for &'a T
where T: Serialize
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, 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: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
(**self).serialize(serializer)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: ?Sized> Serialize for Box<T>
where T: Serialize
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
(**self).serialize(serializer)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T> Serialize for Rc<T>
where T: Serialize
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
(**self).serialize(serializer)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T> Serialize for Arc<T>
where T: Serialize
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
(**self).serialize(serializer)
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a, T: ?Sized> Serialize for Cow<'a, T>
where T: Serialize + ToOwned
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
(**self).serialize(serializer)
}
}
///////////////////////////////////////////////////////////////////////////////
impl<T, E> Serialize for Result<T, E>
where T: Serialize,
E: Serialize
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
match *self {
Result::Ok(ref value) => serializer.serialize_newtype_variant("Result", 0, "Ok", value),
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()
}
}
///////////////////////////////////////////////////////////////////////////////
#[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::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 path::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)))]
#[cfg(feature = "std")]
impl Serialize for OsString {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
self.as_os_str().serialize(serializer)
}
}
#[cfg(feature = "unstable")]
impl<T> Serialize for NonZero<T>
where T: Serialize + Zeroable
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
(**self).serialize(serializer)
}
}
+156
View File
@@ -0,0 +1,156 @@
//! This module contains `Impossible` serializer and its implementations.
use core::marker::PhantomData;
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,ignore
/// 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.
/// Err(...)
/// }
///
/// /* other Serializer methods */
/// }
/// ```
pub struct Impossible<Ok, E> {
void: Void,
_marker: PhantomData<(Ok, E)>,
}
enum Void {}
impl<Ok, E> SerializeSeq for Impossible<Ok, E>
where E: ser::Error
{
type Ok = Ok;
type Error = E;
fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeTuple for Impossible<Ok, E>
where E: ser::Error
{
type Ok = Ok;
type Error = E;
fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeTupleStruct for Impossible<Ok, E>
where E: ser::Error
{
type Ok = Ok;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeTupleVariant for Impossible<Ok, E>
where E: ser::Error
{
type Ok = Ok;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeMap for Impossible<Ok, E>
where E: ser::Error
{
type Ok = Ok;
type Error = E;
fn serialize_key<T: ?Sized + Serialize>(&mut self, _key: &T) -> Result<(), E> {
match self.void {}
}
fn serialize_value<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeStruct for Impossible<Ok, E>
where E: ser::Error
{
type Ok = Ok;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
_key: &'static str,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeStructVariant for Impossible<Ok, E>
where E: ser::Error
{
type Ok = Ok;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
_key: &'static str,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
+915
View File
@@ -0,0 +1,915 @@
//! Generic data structure serialization framework.
//!
//! The two most important traits in this module are `Serialize` and
//! `Serializer`.
//!
//! - **A type that implements `Serialize` is a data structure** that can be
//! serialized to any data format supported by Serde, and conversely
//! - **A type that implements `Serializer` is a data format** that can
//! serialize any data structure supported by Serde.
//!
//! # The Serialize trait
//!
//! Serde provides `Serialize` implementations for many Rust primitive and
//! standard library types. The complete list is below. All of these can be
//! serialized using Serde out of the box.
//!
//! Additionally, Serde provides a procedural macro called `serde_derive` to
//! automatically generate `Serialize` implementations for structs and enums in
//! your program. See the [codegen section of the manual][codegen] for how to
//! use this.
//!
//! In rare cases it may be necessary to implement `Serialize` manually for some
//! type in your program. See the [Implementing `Serialize`][impl-serialize]
//! section of the manual for more about this.
//!
//! Third-party crates may provide `Serialize` implementations for types that
//! they expose. For example the `linked-hash-map` crate provides a
//! `LinkedHashMap<K, V>` type that is serializable by Serde because the crate
//! provides an implementation of `Serialize` for it.
//!
//! # The Serializer trait
//!
//! `Serializer` implementations are provided by third-party crates, for example
//! [`serde_json`][serde_json], [`serde_yaml`][serde_yaml] and
//! [`bincode`][bincode].
//!
//! A partial list of well-maintained formats is given on the [Serde
//! website][data-formats].
//!
//! # Implementations of Serialize provided by Serde
//!
//! - **Primitive types**:
//! - bool
//! - isize, i8, i16, i32, i64
//! - usize, u8, u16, u32, u64
//! - f32, f64
//! - char
//! - str
//! - &T and &mut T
//! - **Compound types**:
//! - [T]
//! - [T; 0] through [T; 32]
//! - tuples up to size 16
//! - **Common standard library types**:
//! - String
//! - Option\<T\>
//! - Result\<T, E\>
//! - PhantomData\<T\>
//! - **Wrapper types**:
//! - Box\<T\>
//! - Rc\<T\>
//! - Arc\<T\>
//! - Cow\<'a, T\>
//! - **Collection types**:
//! - BTreeMap\<K, V\>
//! - BTreeSet\<T\>
//! - BinaryHeap\<T\>
//! - HashMap\<K, V, H\>
//! - HashSet\<T, H\>
//! - LinkedList\<T\>
//! - VecDeque\<T\>
//! - Vec\<T\>
//! - EnumSet\<T\> (unstable)
//! - **Miscellaneous standard library types**:
//! - Duration
//! - Path
//! - PathBuf
//! - Range\<T\>
//! - NonZero\<T\> (unstable)
//! - **Net types**:
//! - IpAddr
//! - Ipv4Addr
//! - Ipv6Addr
//! - SocketAddr
//! - SocketAddrV4
//! - SocketAddrV6
//!
//! [codegen]: https://serde.rs/codegen.html
//! [impl-serialize]: https://serde.rs/impl-serialize.html
//! [serde_json]: https://github.com/serde-rs/json
//! [serde_yaml]: https://github.com/dtolnay/serde-yaml
//! [bincode]: https://github.com/TyOverby/bincode
//! [data-formats]: https://serde.rs/#data-formats
#[cfg(feature = "std")]
use std::error;
#[cfg(not(feature = "std"))]
use error;
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::string::String;
use core::fmt::Display;
#[cfg(any(feature = "std", feature = "collections"))]
use core::fmt::Write;
use core::iter::IntoIterator;
mod impls;
mod impossible;
// Helpers used by generated code. Not public API.
#[doc(hidden)]
pub mod private;
#[cfg(any(feature = "std", feature = "collections"))]
mod content;
pub use self::impossible::Impossible;
///////////////////////////////////////////////////////////////////////////////
/// Trait used by `Serialize` implementations to generically construct errors
/// belonging to the `Serializer` against which they are currently running.
pub trait Error: Sized + error::Error {
/// Raised when a `Serialize` implementation encounters a general error
/// while serializing a type.
///
/// The message should not be capitalized and should not end with a period.
///
/// For example, a filesystem `Path` may refuse to serialize itself if it
/// contains invalid UTF-8 data.
///
/// ```rust
/// # use serde::ser::{Serialize, Serializer, Error};
/// # struct Path;
/// # impl Path { fn to_str(&self) -> Option<&str> { unimplemented!() } }
/// 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")),
/// }
/// }
/// }
/// ```
fn custom<T: Display>(msg: T) -> Self;
}
///////////////////////////////////////////////////////////////////////////////
/// A **data structure** that can be serialized into any data format supported
/// by Serde.
///
/// Serde provides `Serialize` implementations for many Rust primitive and
/// standard library types. The complete list is [here][ser]. All of these can
/// be serialized using Serde out of the box.
///
/// Additionally, Serde provides a procedural macro called `serde_derive` to
/// automatically generate `Serialize` implementations for structs and enums in
/// your program. See the [codegen section of the manual][codegen] for how to
/// use this.
///
/// In rare cases it may be necessary to implement `Serialize` manually for some
/// type in your program. See the [Implementing `Serialize`][impl-serialize]
/// section of the manual for more about this.
///
/// Third-party crates may provide `Serialize` implementations for types that
/// they expose. For example the `linked-hash-map` crate provides a
/// `LinkedHashMap<K, V>` type that is serializable by Serde because the crate
/// provides an implementation of `Serialize` for it.
///
/// [ser]: https://docs.serde.rs/serde/ser/index.html
/// [codegen]: https://serde.rs/codegen.html
/// [impl-serialize]: https://serde.rs/impl-serialize.html
pub trait Serialize {
/// Serialize this value into the given Serde serializer.
///
/// See the [Implementing `Serialize`][impl-serialize] section of the manual
/// for more information about how to implement this method.
///
/// [impl-serialize]: https://serde.rs/impl-serialize.html
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer;
}
///////////////////////////////////////////////////////////////////////////////
/// A **data format** that can serialize any data structure supported by Serde.
///
/// The role of this trait is to define the serialization half of the Serde data
/// model, which is a way to categorize every Rust data structure into one of 28
/// possible types. Each method of the `Serializer` trait corresponds to one of
/// the types of the data model.
///
/// Implementations of `Serialize` map themselves into this data model by
/// invoking exactly one of the `Serializer` methods.
///
/// The types that make up the Serde data model are:
///
/// - 12 primitive types:
/// - bool
/// - i8, i16, i32, i64
/// - u8, u16, u32, u64
/// - f32, f64
/// - char
/// - string
/// - byte array - [u8]
/// - option
/// - either none or some value
/// - unit
/// - unit is the type of () in Rust
/// - unit_struct
/// - for example `struct Unit` or `PhantomData<T>`
/// - unit_variant
/// - the `E::A` and `E::B` in `enum E { A, B }`
/// - newtype_struct
/// - for example `struct Millimeters(u8)`
/// - newtype_variant
/// - the `E::N` in `enum E { N(u8) }`
/// - seq
/// - a dynamically sized sequence of values, for example `Vec<T>` or
/// `HashSet<T>`
/// - seq_fixed_size
/// - a statically sized sequence of values for which the size will be known
/// at deserialization time without looking at the serialized data, for
/// example `[u64; 10]`
/// - tuple
/// - for example `(u8,)` or `(String, u64, Vec<T>)`
/// - tuple_struct
/// - for example `struct Rgb(u8, u8, u8)`
/// - tuple_variant
/// - the `E::T` in `enum E { T(u8, u8) }`
/// - map
/// - for example `BTreeMap<K, V>`
/// - struct
/// - a key-value pairing in which the keys will be known at deserialization
/// time without looking at the serialized data, for example `struct S { r:
/// u8, g: u8, b: u8 }`
/// - struct_variant
/// - the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }`
///
/// Many Serde serializers produce text or binary data as output, for example
/// JSON or Bincode. This is not a requirement of the `Serializer` trait, and
/// there are serializers that do not produce text or binary output. One example
/// is the `serde_json::value::Serializer` (distinct from the main `serde_json`
/// serializer) that produces a `serde_json::Value` data structure in memory as
/// output.
pub trait Serializer: Sized {
/// The output type produced by this `Serializer` during successful
/// serialization. Most serializers that produce text or binary output
/// should set `Ok = ()` and serialize into an `io::Write` or buffer
/// contained within the `Serializer` instance. Serializers that build
/// in-memory data structures may be simplified by using `Ok` to propagate
/// the data structure around.
type Ok;
/// The error type when some error occurs during serialization.
type Error: Error;
/// Type returned from `serialize_seq` and `serialize_seq_fixed_size` for
/// serializing the content of the sequence.
type SerializeSeq: SerializeSeq<Ok = Self::Ok, Error = Self::Error>;
/// Type returned from `serialize_tuple` for serializing the content of the
/// tuple.
type SerializeTuple: SerializeTuple<Ok = Self::Ok, Error = Self::Error>;
/// Type returned from `serialize_tuple_struct` for serializing the content
/// of the tuple struct.
type SerializeTupleStruct: SerializeTupleStruct<Ok = Self::Ok, Error = Self::Error>;
/// Type returned from `serialize_tuple_variant` for serializing the content
/// of the tuple variant.
type SerializeTupleVariant: SerializeTupleVariant<Ok = Self::Ok, Error = Self::Error>;
/// Type returned from `serialize_map` for serializing the content of the
/// map.
type SerializeMap: SerializeMap<Ok = Self::Ok, Error = Self::Error>;
/// Type returned from `serialize_struct` for serializing the content of the
/// struct.
type SerializeStruct: SerializeStruct<Ok = Self::Ok, Error = Self::Error>;
/// Type returned from `serialize_struct_variant` for serializing the
/// content of the struct variant.
type SerializeStructVariant: SerializeStructVariant<Ok = Self::Ok, Error = Self::Error>;
/// Serialize a `bool` value.
fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error>;
/// Serialize an `i8` value.
///
/// If the format does not differentiate between `i8` and `i64`, a
/// reasonable implementation would be to cast the value to `i64` and
/// forward to `serialize_i64`.
fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error>;
/// Serialize an `i16` value.
///
/// If the format does not differentiate between `i16` and `i64`, a
/// reasonable implementation would be to cast the value to `i64` and
/// forward to `serialize_i64`.
fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error>;
/// Serialize an `i32` value.
///
/// If the format does not differentiate between `i32` and `i64`, a
/// reasonable implementation would be to cast the value to `i64` and
/// forward to `serialize_i64`.
fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error>;
/// Serialize an `i64` value.
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error>;
/// Serialize a `u8` value.
///
/// If the format does not differentiate between `u8` and `u64`, a
/// reasonable implementation would be to cast the value to `u64` and
/// forward to `serialize_u64`.
fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error>;
/// Serialize a `u16` value.
///
/// If the format does not differentiate between `u16` and `u64`, a
/// reasonable implementation would be to cast the value to `u64` and
/// forward to `serialize_u64`.
fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error>;
/// Serialize a `u32` value.
///
/// If the format does not differentiate between `u32` and `u64`, a
/// reasonable implementation would be to cast the value to `u64` and
/// forward to `serialize_u64`.
fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error>;
/// Serialize a `u64` value.
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error>;
/// Serialize an `f32` value.
///
/// If the format does not differentiate between `f32` and `f64`, a
/// reasonable implementation would be to cast the value to `f64` and
/// forward to `serialize_f64`.
fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error>;
/// Serialize an `f64` value.
fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error>;
/// Serialize a character.
///
/// If the format does not support characters, it is reasonable to serialize
/// it as a single element `str` or a `u32`.
fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error>;
/// Serialize a `&str`.
fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error>;
/// Serialize a chunk of raw byte data.
///
/// Enables serializers to serialize byte slices more compactly or more
/// efficiently than other types of slices. If no efficient implementation
/// is available, a reasonable implementation would be to forward to
/// `serialize_seq`. If forwarded, the implementation looks usually just
/// like this:
///
/// ```rust,ignore
/// let mut seq = self.serialize_seq(Some(value.len()))?;
/// for b in value {
/// seq.serialize_element(b)?;
/// }
/// seq.end()
/// ```
fn serialize_bytes(self, value: &[u8]) -> Result<Self::Ok, Self::Error>;
/// Serialize a `None` value.
fn serialize_none(self) -> Result<Self::Ok, Self::Error>;
/// Serialize a `Some(T)` value.
fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok, Self::Error>;
/// Serialize a `()` value.
fn serialize_unit(self) -> Result<Self::Ok, Self::Error>;
/// Serialize a unit struct like `struct Unit` or `PhantomData<T>`.
///
/// A reasonable implementation would be to forward to `serialize_unit`.
fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error>;
/// Serialize a unit variant like `E::A` in `enum E { A, B }`.
///
/// The `name` is the name of the enum, the `variant_index` is the index of
/// this variant within the enum, and the `variant` is the name of the
/// variant.
///
/// A reasonable implementation would be to forward to `serialize_unit`.
///
/// ```rust,ignore
/// match *self {
/// E::A => serializer.serialize_unit_variant("E", 0, "A"),
/// E::B => serializer.serialize_unit_variant("E", 1, "B"),
/// }
/// ```
fn serialize_unit_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str)
-> Result<Self::Ok, Self::Error>;
/// Serialize a newtype struct like `struct Millimeters(u8)`.
///
/// Serializers are encouraged to treat newtype structs as insignificant
/// wrappers around the data they contain. A reasonable implementation would
/// be to forward to `value.serialize(self)`.
///
/// ```rust,ignore
/// serializer.serialize_newtype_struct("Millimeters", &self.0)
/// ```
fn serialize_newtype_struct<T: ?Sized + Serialize>(self,
name: &'static str,
value: &T)
-> Result<Self::Ok, Self::Error>;
/// Serialize a newtype variant like `E::N` in `enum E { N(u8) }`.
///
/// The `name` is the name of the enum, the `variant_index` is the index of
/// this variant within the enum, and the `variant` is the name of the
/// variant. The `value` is the data contained within this newtype variant.
///
/// ```rust,ignore
/// match *self {
/// E::N(ref n) => serializer.serialize_newtype_variant("E", 0, "N", n),
/// }
/// ```
fn serialize_newtype_variant<T: ?Sized + Serialize>(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
value: &T)
-> Result<Self::Ok, Self::Error>;
/// Begin to serialize a dynamically sized sequence. This call must be
/// followed by zero or more calls to `serialize_element`, then a call to
/// `end`.
///
/// The argument is the number of elements in the sequence, which may or may
/// not be computable before the sequence is iterated. Some serializers only
/// support sequences whose length is known up front.
///
/// ```rust,ignore
/// let mut seq = serializer.serialize_seq(Some(self.len()))?;
/// for element in self {
/// seq.serialize_element(element)?;
/// }
/// seq.end()
/// ```
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error>;
/// Begin to serialize a statically sized sequence whose length will be
/// known at deserialization time without looking at the serialized data.
/// This call must be followed by zero or more calls to `serialize_element`,
/// then a call to `end`.
///
/// ```rust,ignore
/// let mut seq = serializer.serialize_seq_fixed_size(self.len())?;
/// for element in self {
/// seq.serialize_element(element)?;
/// }
/// seq.end()
/// ```
fn serialize_seq_fixed_size(self, size: usize) -> Result<Self::SerializeSeq, Self::Error>;
/// Begin to serialize a tuple. This call must be followed by zero or more
/// calls to `serialize_element`, then a call to `end`.
///
/// ```rust,ignore
/// let mut tup = serializer.serialize_tuple(3)?;
/// tup.serialize_element(&self.0)?;
/// tup.serialize_element(&self.1)?;
/// tup.serialize_element(&self.2)?;
/// tup.end()
/// ```
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error>;
/// Begin to serialize a tuple struct like `struct Rgb(u8, u8, u8)`. This
/// call must be followed by zero or more calls to `serialize_field`, then a
/// call to `end`.
///
/// The `name` is the name of the tuple struct and the `len` is the number
/// of data fields that will be serialized.
///
/// ```rust,ignore
/// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?;
/// ts.serialize_field(&self.0)?;
/// ts.serialize_field(&self.1)?;
/// ts.serialize_field(&self.2)?;
/// ts.end()
/// ```
fn serialize_tuple_struct(self,
name: &'static str,
len: usize)
-> Result<Self::SerializeTupleStruct, Self::Error>;
/// Begin to serialize a tuple variant like `E::T` in `enum E { T(u8, u8)
/// }`. This call must be followed by zero or more calls to
/// `serialize_field`, then a call to `end`.
///
/// The `name` is the name of the enum, the `variant_index` is the index of
/// this variant within the enum, the `variant` is the name of the variant,
/// and the `len` is the number of data fields that will be serialized.
///
/// ```rust,ignore
/// match *self {
/// E::T(ref a, ref b) => {
/// let mut tv = serializer.serialize_tuple_variant("E", 0, "T", 2)?;
/// tv.serialize_field(a)?;
/// tv.serialize_field(b)?;
/// tv.end()
/// }
/// }
/// ```
fn serialize_tuple_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize)
-> Result<Self::SerializeTupleVariant, Self::Error>;
/// Begin to serialize a map. This call must be followed by zero or more
/// calls to `serialize_key` and `serialize_value`, then a call to `end`.
///
/// The argument is the number of elements in the map, which may or may not
/// be computable before the map is iterated. Some serializers only support
/// maps whose length is known up front.
///
/// ```rust,ignore
/// let mut map = serializer.serialize_map(Some(self.len()))?;
/// for (k, v) in self {
/// map.serialize_entry(k, v)?;
/// }
/// map.end()
/// ```
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error>;
/// Begin to serialize a struct like `struct Rgb { r: u8, g: u8, b: u8 }`.
/// This call must be followed by zero or more calls to `serialize_field`,
/// then a call to `end`.
///
/// The `name` is the name of the struct and the `len` is the number of
/// data fields that will be serialized.
///
/// ```rust,ignore
/// let mut struc = serializer.serialize_struct("Rgb", 3)?;
/// struc.serialize_field("r", &self.r)?;
/// struc.serialize_field("g", &self.g)?;
/// struc.serialize_field("b", &self.b)?;
/// struc.end()
/// ```
fn serialize_struct(self,
name: &'static str,
len: usize)
-> Result<Self::SerializeStruct, Self::Error>;
/// Begin to serialize a struct variant like `E::S` in `enum E { S { r: u8,
/// g: u8, b: u8 } }`. This call must be followed by zero or more calls to
/// `serialize_field`, then a call to `end`.
///
/// The `name` is the name of the enum, the `variant_index` is the index of
/// this variant within the enum, the `variant` is the name of the variant,
/// and the `len` is the number of data fields that will be serialized.
///
/// ```rust,ignore
/// match *self {
/// E::S { ref r, ref g, ref b } => {
/// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?;
/// sv.serialize_field("r", r)?;
/// sv.serialize_field("g", g)?;
/// sv.serialize_field("b", b)?;
/// sv.end()
/// }
/// }
/// ```
fn serialize_struct_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize)
-> Result<Self::SerializeStructVariant, Self::Error>;
/// Collect an iterator as a sequence.
///
/// The default implementation serializes each item yielded by the iterator
/// using `Self::SerializeSeq`. Implementors should not need to override
/// this method.
fn collect_seq<I>(self, iter: I) -> Result<Self::Ok, Self::Error>
where I: IntoIterator,
<I as IntoIterator>::Item: Serialize
{
let iter = iter.into_iter();
let mut serializer = try!(self.serialize_seq(iter.len_hint()));
for item in iter {
try!(serializer.serialize_element(&item));
}
serializer.end()
}
/// Collect an iterator as a map.
///
/// The default implementation serializes each pair yielded by the iterator
/// using `Self::SerializeMap`. Implementors should not need to override
/// this method.
fn collect_map<K, V, I>(self, iter: I) -> Result<Self::Ok, Self::Error>
where K: Serialize,
V: Serialize,
I: IntoIterator<Item = (K, V)>
{
let iter = iter.into_iter();
let mut serializer = try!(self.serialize_map(iter.len_hint()));
for (key, value) in iter {
try!(serializer.serialize_entry(&key, &value));
}
serializer.end()
}
/// Serialize a string produced by an implementation of `Display`.
///
/// The default implementation builds a heap-allocated `String` and
/// delegates to `serialize_str`. Serializers are encouraged to provide a
/// more efficient implementation if possible.
///
/// ```rust
/// # use serde::{Serialize, Serializer};
/// # struct DateTime;
/// # impl DateTime {
/// # fn naive_local(&self) -> () { () }
/// # fn offset(&self) -> () { () }
/// # }
/// impl Serialize for DateTime {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// {
/// serializer.collect_str(&format_args!("{:?}{:?}",
/// self.naive_local(),
/// self.offset()))
/// }
/// }
/// ```
#[cfg(any(feature = "std", feature = "collections"))]
fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
where T: Display
{
let mut string = String::new();
write!(string, "{}", value).unwrap();
self.serialize_str(&string)
}
/// Serialize a string produced by an implementation of `Display`.
///
/// The default implementation returns an error unconditionally when
/// compiled with `no_std`.
///
/// ```rust
/// # use serde::{Serialize, Serializer};
/// # struct DateTime;
/// # impl DateTime {
/// # fn naive_local(&self) -> () { () }
/// # fn offset(&self) -> () { () }
/// # }
/// impl Serialize for DateTime {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// {
/// serializer.collect_str(&format_args!("{:?}{:?}",
/// self.naive_local(),
/// self.offset()))
/// }
/// }
/// ```
#[cfg(not(any(feature = "std", feature = "collections")))]
fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
where T: Display
{
// TODO https://github.com/serde-rs/serde/issues/805
// Remove this impl and force no_std formats to implement collect_str.
let _ = value;
Err(Error::custom("this no_std format does not support serializing strings with collect_str"))
}
}
/// Returned from `Serializer::serialize_seq` and
/// `Serializer::serialize_seq_fixed_size`.
///
/// ```rust,ignore
/// let mut seq = serializer.serialize_seq(Some(self.len()))?;
/// for element in self {
/// seq.serialize_element(element)?;
/// }
/// seq.end()
/// ```
pub trait SerializeSeq {
/// Must match the `Ok` type of our `Serializer`.
type Ok;
/// Must match the `Error` type of our `Serializer`.
type Error: Error;
/// Serialize a sequence element.
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error>;
/// Finish serializing a sequence.
fn end(self) -> Result<Self::Ok, Self::Error>;
}
/// Returned from `Serializer::serialize_tuple`.
///
/// ```rust,ignore
/// let mut tup = serializer.serialize_tuple(3)?;
/// tup.serialize_element(&self.0)?;
/// tup.serialize_element(&self.1)?;
/// tup.serialize_element(&self.2)?;
/// tup.end()
/// ```
pub trait SerializeTuple {
/// Must match the `Ok` type of our `Serializer`.
type Ok;
/// Must match the `Error` type of our `Serializer`.
type Error: Error;
/// Serialize a tuple element.
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error>;
/// Finish serializing a tuple.
fn end(self) -> Result<Self::Ok, Self::Error>;
}
/// Returned from `Serializer::serialize_tuple_struct`.
///
/// ```rust,ignore
/// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?;
/// ts.serialize_field(&self.0)?;
/// ts.serialize_field(&self.1)?;
/// ts.serialize_field(&self.2)?;
/// ts.end()
/// ```
pub trait SerializeTupleStruct {
/// Must match the `Ok` type of our `Serializer`.
type Ok;
/// Must match the `Error` type of our `Serializer`.
type Error: Error;
/// Serialize a tuple struct field.
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error>;
/// Finish serializing a tuple struct.
fn end(self) -> Result<Self::Ok, Self::Error>;
}
/// Returned from `Serializer::serialize_tuple_variant`.
///
/// ```rust,ignore
/// match *self {
/// E::T(ref a, ref b) => {
/// let mut tv = serializer.serialize_tuple_variant("E", 0, "T", 2)?;
/// tv.serialize_field(a)?;
/// tv.serialize_field(b)?;
/// tv.end()
/// }
/// }
/// ```
pub trait SerializeTupleVariant {
/// Must match the `Ok` type of our `Serializer`.
type Ok;
/// Must match the `Error` type of our `Serializer`.
type Error: Error;
/// Serialize a tuple variant field.
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error>;
/// Finish serializing a tuple variant.
fn end(self) -> Result<Self::Ok, Self::Error>;
}
/// Returned from `Serializer::serialize_map`.
///
/// ```rust,ignore
/// let mut map = serializer.serialize_map(Some(self.len()))?;
/// for (k, v) in self {
/// map.serialize_entry(k, v)?;
/// }
/// map.end()
/// ```
pub trait SerializeMap {
/// Must match the `Ok` type of our `Serializer`.
type Ok;
/// Must match the `Error` type of our `Serializer`.
type Error: Error;
/// Serialize a map key.
fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<(), Self::Error>;
/// Serialize a map value.
fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error>;
/// Serialize a map entry consisting of a key and a value.
///
/// Some `Serialize` types are not able to hold a key and value in memory at
/// the same time so `SerializeMap` implementations are required to support
/// `serialize_key` and `serialize_value` individually. The
/// `serialize_entry` method allows serializers to optimize for the case
/// where key and value are both available. `Serialize` implementations are
/// encouraged to use `serialize_entry` if possible.
///
/// The default implementation delegates to `serialize_key` and
/// `serialize_value`. This is appropriate for serializers that do not care
/// about performance or are not able to optimize `serialize_entry` any
/// better than this.
fn serialize_entry<K: ?Sized + Serialize, V: ?Sized + Serialize>(&mut self,
key: &K,
value: &V)
-> Result<(), Self::Error> {
try!(self.serialize_key(key));
self.serialize_value(value)
}
/// Finish serializing a map.
fn end(self) -> Result<Self::Ok, Self::Error>;
}
/// Returned from `Serializer::serialize_struct`.
///
/// ```rust,ignore
/// let mut struc = serializer.serialize_struct("Rgb", 3)?;
/// struc.serialize_field("r", &self.r)?;
/// struc.serialize_field("g", &self.g)?;
/// struc.serialize_field("b", &self.b)?;
/// struc.end()
/// ```
pub trait SerializeStruct {
/// Must match the `Ok` type of our `Serializer`.
type Ok;
/// Must match the `Error` type of our `Serializer`.
type Error: Error;
/// Serialize a struct field.
fn serialize_field<T: ?Sized + Serialize>(&mut self,
key: &'static str,
value: &T)
-> Result<(), Self::Error>;
/// Finish serializing a struct.
fn end(self) -> Result<Self::Ok, Self::Error>;
}
/// Returned from `Serializer::serialize_struct_variant`.
///
/// ```rust,ignore
/// match *self {
/// E::S { ref r, ref g, ref b } => {
/// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?;
/// sv.serialize_field("r", r)?;
/// sv.serialize_field("g", g)?;
/// sv.serialize_field("b", b)?;
/// sv.end()
/// }
/// }
/// ```
pub trait SerializeStructVariant {
/// Must match the `Ok` type of our `Serializer`.
type Ok;
/// Must match the `Error` type of our `Serializer`.
type Error: Error;
/// Serialize a struct variant field.
fn serialize_field<T: ?Sized + Serialize>(&mut self,
key: &'static str,
value: &T)
-> Result<(), Self::Error>;
/// Finish serializing a struct variant.
fn end(self) -> Result<Self::Ok, Self::Error>;
}
trait LenHint: Iterator {
fn len_hint(&self) -> Option<usize>;
}
impl<I: Iterator> LenHint for I {
#[cfg(not(feature = "unstable"))]
fn len_hint(&self) -> Option<usize> {
iterator_len_hint(self)
}
#[cfg(feature = "unstable")]
default fn len_hint(&self) -> Option<usize> {
iterator_len_hint(self)
}
}
#[cfg(feature = "unstable")]
impl<I: ExactSizeIterator> LenHint for I {
fn len_hint(&self) -> Option<usize> {
Some(self.len())
}
}
fn iterator_len_hint<I: Iterator>(iter: &I) -> Option<usize> {
match iter.size_hint() {
(lo, Some(hi)) if lo == hi => Some(lo),
_ => None,
}
}
+315
View File
@@ -0,0 +1,315 @@
use core::fmt::{self, Display};
use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct, Impossible};
#[cfg(any(feature = "std", feature = "collections"))]
use ser::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMapValue};
/// Not public API.
pub fn serialize_tagged_newtype<S, T>(serializer: S,
type_ident: &'static str,
variant_ident: &'static str,
tag: &'static str,
variant_name: &'static str,
value: &T)
-> Result<S::Ok, S::Error>
where S: Serializer,
T: Serialize
{
value.serialize(TaggedSerializer {
type_ident: type_ident,
variant_ident: variant_ident,
tag: tag,
variant_name: variant_name,
delegate: serializer,
})
}
struct TaggedSerializer<S> {
type_ident: &'static str,
variant_ident: &'static str,
tag: &'static str,
variant_name: &'static str,
delegate: S,
}
enum Unsupported {
Boolean,
Integer,
Float,
Char,
String,
ByteArray,
Optional,
Unit,
UnitStruct,
Sequence,
Tuple,
TupleStruct,
#[cfg(not(any(feature = "std", feature = "collections")))]
Enum,
}
impl Display for Unsupported {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match *self {
Unsupported::Boolean => formatter.write_str("a boolean"),
Unsupported::Integer => formatter.write_str("an integer"),
Unsupported::Float => formatter.write_str("a float"),
Unsupported::Char => formatter.write_str("a char"),
Unsupported::String => formatter.write_str("a string"),
Unsupported::ByteArray => formatter.write_str("a byte array"),
Unsupported::Optional => formatter.write_str("an optional"),
Unsupported::Unit => formatter.write_str("unit"),
Unsupported::UnitStruct => formatter.write_str("a unit struct"),
Unsupported::Sequence => formatter.write_str("a sequence"),
Unsupported::Tuple => formatter.write_str("a tuple"),
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
#[cfg(not(any(feature = "std", feature = "collections")))]
Unsupported::Enum => formatter.write_str("an enum"),
}
}
}
struct Error {
type_ident: &'static str,
variant_ident: &'static str,
ty: Unsupported,
}
impl Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter,
"cannot serialize tagged newtype variant {}::{} containing {}",
self.type_ident,
self.variant_ident,
self.ty)
}
}
impl<S> TaggedSerializer<S>
where S: Serializer
{
fn bad_type(self, what: Unsupported) -> S::Error {
ser::Error::custom(Error {
type_ident: self.type_ident,
variant_ident: self.variant_ident,
ty: what,
})
}
}
impl<S> Serializer for TaggedSerializer<S>
where S: Serializer
{
type Ok = S::Ok;
type Error = S::Error;
type SerializeSeq = Impossible<S::Ok, S::Error>;
type SerializeTuple = Impossible<S::Ok, S::Error>;
type SerializeTupleStruct = Impossible<S::Ok, S::Error>;
type SerializeMap = S::SerializeMap;
type SerializeStruct = S::SerializeStruct;
#[cfg(not(any(feature = "std", feature = "collections")))]
type SerializeTupleVariant = Impossible<S::Ok, S::Error>;
#[cfg(any(feature = "std", feature = "collections"))]
type SerializeTupleVariant = SerializeTupleVariantAsMapValue<S::SerializeMap>;
#[cfg(not(any(feature = "std", feature = "collections")))]
type SerializeStructVariant = Impossible<S::Ok, S::Error>;
#[cfg(any(feature = "std", feature = "collections"))]
type SerializeStructVariant = SerializeStructVariantAsMapValue<S::SerializeMap>;
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Boolean))
}
fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
}
fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
}
fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Char))
}
fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::String))
}
fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::ByteArray))
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Optional))
}
fn serialize_some<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
where T: Serialize
{
Err(self.bad_type(Unsupported::Optional))
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Unit))
}
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::UnitStruct))
}
fn serialize_unit_variant(self,
_: &'static str,
_: usize,
inner_variant: &'static str)
-> Result<Self::Ok, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_entry(inner_variant, &()));
map.end()
}
fn serialize_newtype_struct<T: ?Sized>(self,
_: &'static str,
value: &T)
-> Result<Self::Ok, Self::Error>
where T: Serialize
{
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(self,
_: &'static str,
_: usize,
inner_variant: &'static str,
inner_value: &T)
-> Result<Self::Ok, Self::Error>
where T: Serialize
{
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_entry(inner_variant, inner_value));
map.end()
}
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Err(self.bad_type(Unsupported::Sequence))
}
fn serialize_seq_fixed_size(self, _: usize) -> Result<Self::SerializeSeq, Self::Error> {
Err(self.bad_type(Unsupported::Sequence))
}
fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
Err(self.bad_type(Unsupported::Tuple))
}
fn serialize_tuple_struct(self,
_: &'static str,
_: usize)
-> Result<Self::SerializeTupleStruct, Self::Error> {
Err(self.bad_type(Unsupported::TupleStruct))
}
#[cfg(not(any(feature = "std", feature = "collections")))]
fn serialize_tuple_variant(self,
_: &'static str,
_: usize,
_: &'static str,
_: usize)
-> Result<Self::SerializeTupleVariant, Self::Error> {
// Lack of push-based serialization means we need to buffer the content
// of the tuple variant, so it requires std.
Err(self.bad_type(Unsupported::Enum))
}
#[cfg(any(feature = "std", feature = "collections"))]
fn serialize_tuple_variant(self,
_: &'static str,
_: usize,
inner_variant: &'static str,
len: usize)
-> Result<Self::SerializeTupleVariant, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_key(inner_variant));
Ok(SerializeTupleVariantAsMapValue::new(map, inner_variant, len))
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
let mut map = try!(self.delegate.serialize_map(len.map(|len| len + 1)));
try!(map.serialize_entry(self.tag, self.variant_name));
Ok(map)
}
fn serialize_struct(self,
name: &'static str,
len: usize)
-> Result<Self::SerializeStruct, Self::Error> {
let mut state = try!(self.delegate.serialize_struct(name, len + 1));
try!(state.serialize_field(self.tag, self.variant_name));
Ok(state)
}
#[cfg(not(any(feature = "std", feature = "collections")))]
fn serialize_struct_variant(self,
_: &'static str,
_: usize,
_: &'static str,
_: usize)
-> Result<Self::SerializeStructVariant, Self::Error> {
// Lack of push-based serialization means we need to buffer the content
// of the struct variant, so it requires std.
Err(self.bad_type(Unsupported::Enum))
}
#[cfg(any(feature = "std", feature = "collections"))]
fn serialize_struct_variant(self,
_: &'static str,
_: usize,
inner_variant: &'static str,
len: usize)
-> Result<Self::SerializeStructVariant, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_key(inner_variant));
Ok(SerializeStructVariantAsMapValue::new(map, inner_variant, len))
}
}
+74
View File
@@ -0,0 +1,74 @@
//! Private utility functions
const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
const TAG_THREE_B: u8 = 0b1110_0000;
const TAG_FOUR_B: u8 = 0b1111_0000;
const MAX_ONE_B: u32 = 0x80;
const MAX_TWO_B: u32 = 0x800;
const MAX_THREE_B: u32 = 0x10000;
#[inline]
pub fn encode_utf8(c: char) -> EncodeUtf8 {
let code = c as u32;
let mut buf = [0; 4];
let pos = if code < MAX_ONE_B {
buf[3] = code as u8;
3
} else if code < MAX_TWO_B {
buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
2
} else if code < MAX_THREE_B {
buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
1
} else {
buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
0
};
EncodeUtf8 {
buf: buf,
pos: pos,
}
}
pub struct EncodeUtf8 {
buf: [u8; 4],
pos: usize,
}
impl EncodeUtf8 {
// FIXME: use this from_utf8_unchecked, since we know it can never fail
pub fn as_str(&self) -> &str {
::core::str::from_utf8(&self.buf[self.pos..]).unwrap()
}
}
#[allow(non_upper_case_globals)]
const Pattern_White_Space_table: &'static [(char, char)] = &[('\u{9}', '\u{d}'),
('\u{20}', '\u{20}'),
('\u{85}', '\u{85}'),
('\u{200e}', '\u{200f}'),
('\u{2028}', '\u{2029}')];
fn bsearch_range_table(c: char, r: &'static [(char, char)]) -> bool {
use core::cmp::Ordering::{Equal, Less, Greater};
r.binary_search_by(|&(lo, hi)| if c < lo {
Greater
} else if hi < c {
Less
} else {
Equal
})
.is_ok()
}
#[allow(non_snake_case)]
pub fn Pattern_White_Space(c: char) -> bool {
bsearch_range_table(c, Pattern_White_Space_table)
}
+18
View File
@@ -0,0 +1,18 @@
[package]
name = "serde_codegen_internals"
version = "0.14.2"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "AST representation used by Serde codegen. Unstable."
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_codegen_internals/"
keywords = ["serde", "serialization"]
readme = "../README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[dependencies]
syn = { version = "0.11", default-features = false, features = ["parsing"] }
[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
+122
View File
@@ -0,0 +1,122 @@
use syn;
use attr;
use Ctxt;
pub struct Item<'a> {
pub ident: syn::Ident,
pub attrs: attr::Item,
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,
}
pub enum Style {
Struct,
Tuple,
Newtype,
Unit,
}
impl<'a> Item<'a> {
pub fn from_ast(cx: &Ctxt, item: &'a syn::MacroInput) -> Item<'a> {
let attrs = attr::Item::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());
}
}
}
Item {
ident: item.ident.clone(),
attrs: attrs,
body: body,
generics: &item.generics,
}
}
}
impl<'a> Body<'a> {
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
match *self {
Body::Enum(ref variants) => {
Box::new(variants.iter()
.flat_map(|variant| variant.fields.iter()))
}
Body::Struct(_, ref fields) => Box::new(fields.iter()),
}
}
}
fn enum_from_ast<'a>(cx: &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()
}
+838
View File
@@ -0,0 +1,838 @@
use Ctxt;
use syn;
use syn::MetaItem::{List, NameValue, Word};
use syn::NestedMetaItem::{Literal, MetaItem};
use std::str::FromStr;
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
// are `attr::Item::from_ast`, `attr::Variant::from_ast`, and
// `attr::Field::from_ast`. Each returns an instance of the corresponding
// struct. Note that none of them return a Result. Unrecognized, malformed, or
// duplicated attributes result in a span_err but otherwise are ignored. The
// user will see errors simultaneously for all bad attributes in the crate
// rather than just the first.
pub use case::RenameRule;
struct Attr<'c, T> {
cx: &'c Ctxt,
name: &'static str,
value: Option<T>,
}
impl<'c, T> Attr<'c, T> {
fn none(cx: &'c Ctxt, name: &'static str) -> Self {
Attr {
cx: cx,
name: name,
value: None,
}
}
fn set(&mut self, value: T) {
if self.value.is_some() {
self.cx.error(format!("duplicate serde attribute `{}`", self.name));
} else {
self.value = Some(value);
}
}
fn set_opt(&mut self, value: Option<T>) {
if let Some(value) = value {
self.set(value);
}
}
fn set_if_none(&mut self, value: T) {
if self.value.is_none() {
self.value = Some(value);
}
}
fn get(self) -> Option<T> {
self.value
}
}
struct BoolAttr<'c>(Attr<'c, ()>);
impl<'c> BoolAttr<'c> {
fn none(cx: &'c Ctxt, name: &'static str) -> Self {
BoolAttr(Attr::none(cx, name))
}
fn set_true(&mut self) {
self.0.set(());
}
fn get(&self) -> bool {
self.0.value.is_some()
}
}
#[derive(Debug)]
pub struct Name {
serialize: String,
deserialize: String,
}
impl Name {
/// Return the container name for the container when serializing.
pub fn serialize_name(&self) -> String {
self.serialize.clone()
}
/// Return the container name for the container when deserializing.
pub fn deserialize_name(&self) -> String {
self.deserialize.clone()
}
}
/// Represents container (e.g. struct) attribute information
#[derive(Debug)]
pub struct Item {
name: Name,
deny_unknown_fields: bool,
default: Default,
rename_all: RenameRule,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
tag: EnumTag,
from_type: Option<syn::Ty>,
into_type: Option<syn::Ty>,
}
/// Styles of representing an enum.
#[derive(Debug)]
pub enum EnumTag {
/// The default.
///
/// ```json
/// {"variant1": {"key1": "value1", "key2": "value2"}}
/// ```
External,
/// `#[serde(tag = "type")]`
///
/// ```json
/// {"type": "variant1", "key1": "value1", "key2": "value2"}
/// ```
Internal { tag: String },
/// `#[serde(tag = "t", content = "c")]`
///
/// ```json
/// {"t": "variant1", "c": {"key1": "value1", "key2": "value2"}}
/// ```
Adjacent { tag: String, content: String },
/// `#[serde(untagged)]`
///
/// ```json
/// {"key1": "value1", "key2": "value2"}
/// ```
None,
}
impl Item {
/// Extract out the `#[serde(...)]` attributes from an item.
pub fn from_ast(cx: &Ctxt, item: &syn::MacroInput) -> Self {
let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename");
let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields");
let mut default = Attr::none(cx, "default");
let mut rename_all = Attr::none(cx, "rename_all");
let mut ser_bound = Attr::none(cx, "bound");
let mut de_bound = Attr::none(cx, "bound");
let mut untagged = BoolAttr::none(cx, "untagged");
let mut internal_tag = Attr::none(cx, "tag");
let mut content = Attr::none(cx, "content");
let mut from_type = Attr::none(cx, "from");
let mut into_type = Attr::none(cx, "into");
for meta_items in item.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
match meta_item {
// Parse `#[serde(rename="foo")]`
MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
ser_name.set(s.clone());
de_name.set(s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser);
de_name.set_opt(de);
}
}
// Parse `#[serde(rename_all="foo")]`
MetaItem(NameValue(ref name, ref lit)) if name == "rename_all" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match RenameRule::from_str(&s) {
Ok(rename_rule) => rename_all.set(rename_rule),
Err(()) => {
cx.error(format!("unknown rename rule for #[serde(rename_all \
= {:?})]",
s))
}
}
}
}
// Parse `#[serde(deny_unknown_fields)]`
MetaItem(Word(ref name)) if name == "deny_unknown_fields" => {
deny_unknown_fields.set_true();
}
// Parse `#[serde(default)]`
MetaItem(Word(ref name)) if name == "default" => {
match item.body {
syn::Body::Struct(syn::VariantData::Struct(_)) => {
default.set(Default::Default);
}
_ => {
cx.error("#[serde(default)] can only be used on structs \
with named fields")
}
}
}
// Parse `#[serde(default="...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "default" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
match item.body {
syn::Body::Struct(syn::VariantData::Struct(_)) => {
default.set(Default::Path(path));
}
_ => {
cx.error("#[serde(default = \"...\")] can only be used \
on structs with named fields")
}
}
}
}
// Parse `#[serde(bound="D: Serialize")]`
MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
if let Ok(where_predicates) =
parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
}
}
// Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
MetaItem(List(ref name, ref meta_items)) if name == "bound" => {
if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
ser_bound.set_opt(ser);
de_bound.set_opt(de);
}
}
// Parse `#[serde(untagged)]`
MetaItem(Word(ref name)) if name == "untagged" => {
match item.body {
syn::Body::Enum(_) => {
untagged.set_true();
}
syn::Body::Struct(_) => {
cx.error("#[serde(untagged)] can only be used on enums")
}
}
}
// Parse `#[serde(tag = "type")]`
MetaItem(NameValue(ref name, ref lit)) if name == "tag" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match item.body {
syn::Body::Enum(_) => {
internal_tag.set(s);
}
syn::Body::Struct(_) => {
cx.error("#[serde(tag = \"...\")] can only be used on enums")
}
}
}
}
// Parse `#[serde(content = "c")]`
MetaItem(NameValue(ref name, ref lit)) if name == "content" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match item.body {
syn::Body::Enum(_) => {
content.set(s);
}
syn::Body::Struct(_) => {
cx.error("#[serde(content = \"...\")] can only be used on \
enums")
}
}
}
}
// Parse `#[serde(from = "Type")]
MetaItem(NameValue(ref name, ref lit)) if name == "from" => {
if let Ok(from_ty) = parse_lit_into_ty(cx, name.as_ref(), lit) {
from_type.set_opt(Some(from_ty));
}
}
// Parse `#[serde(into = "Type")]
MetaItem(NameValue(ref name, ref lit)) if name == "into" => {
if let Ok(into_ty) = parse_lit_into_ty(cx, name.as_ref(), lit) {
into_type.set_opt(Some(into_ty));
}
}
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde container attribute `{}`",
meta_item.name()));
}
Literal(_) => {
cx.error("unexpected literal in serde container attribute");
}
}
}
}
let tag = match (untagged.get(), internal_tag.get(), content.get()) {
(false, None, None) => EnumTag::External,
(true, None, None) => EnumTag::None,
(false, Some(tag), None) => {
// Check that there are no tuple variants.
if let syn::Body::Enum(ref variants) = item.body {
for variant in variants {
match variant.data {
syn::VariantData::Struct(_) |
syn::VariantData::Unit => {}
syn::VariantData::Tuple(ref fields) => {
if fields.len() != 1 {
cx.error("#[serde(tag = \"...\")] cannot be used with tuple \
variants");
break;
}
}
}
}
}
EnumTag::Internal { tag: tag }
}
(true, Some(_), None) => {
cx.error("enum cannot be both untagged and internally tagged");
EnumTag::External // doesn't matter, will error
}
(false, None, Some(_)) => {
cx.error("#[serde(tag = \"...\", content = \"...\")] must be used together");
EnumTag::External
}
(true, None, Some(_)) => {
cx.error("untagged enum cannot have #[serde(content = \"...\")]");
EnumTag::External
}
(false, Some(tag), Some(content)) => {
EnumTag::Adjacent {
tag: tag,
content: content,
}
}
(true, Some(_), Some(_)) => {
cx.error("untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]");
EnumTag::External
}
};
Item {
name: Name {
serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()),
deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()),
},
deny_unknown_fields: deny_unknown_fields.get(),
default: default.get().unwrap_or(Default::None),
rename_all: rename_all.get().unwrap_or(RenameRule::None),
ser_bound: ser_bound.get(),
de_bound: de_bound.get(),
tag: tag,
from_type: from_type.get(),
into_type: into_type.get(),
}
}
pub fn name(&self) -> &Name {
&self.name
}
pub fn rename_all(&self) -> &RenameRule {
&self.rename_all
}
pub fn deny_unknown_fields(&self) -> bool {
self.deny_unknown_fields
}
pub fn default(&self) -> &Default {
&self.default
}
pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
self.ser_bound.as_ref().map(|vec| &vec[..])
}
pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
pub fn tag(&self) -> &EnumTag {
&self.tag
}
pub fn from_type(&self) -> Option<&syn::Ty> {
self.from_type.as_ref()
}
pub fn into_type(&self) -> Option<&syn::Ty> {
self.into_type.as_ref()
}
}
/// Represents variant attribute information
#[derive(Debug)]
pub struct Variant {
name: Name,
ser_renamed: bool,
de_renamed: bool,
rename_all: RenameRule,
skip_deserializing: bool,
skip_serializing: bool,
}
impl Variant {
pub fn from_ast(cx: &Ctxt, variant: &syn::Variant) -> Self {
let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename");
let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing");
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
let mut rename_all = Attr::none(cx, "rename_all");
for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
match meta_item {
// Parse `#[serde(rename="foo")]`
MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
ser_name.set(s.clone());
de_name.set(s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser);
de_name.set_opt(de);
}
}
// Parse `#[serde(rename_all="foo")]`
MetaItem(NameValue(ref name, ref lit)) if name == "rename_all" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match RenameRule::from_str(&s) {
Ok(rename_rule) => rename_all.set(rename_rule),
Err(()) => {
cx.error(format!("unknown rename rule for #[serde(rename_all \
= {:?})]",
s))
}
}
}
}
// Parse `#[serde(skip_deserializing)]`
MetaItem(Word(ref name)) if name == "skip_deserializing" => {
skip_deserializing.set_true();
}
// Parse `#[serde(skip_serializing)]`
MetaItem(Word(ref name)) if name == "skip_serializing" => {
skip_serializing.set_true();
}
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde variant attribute `{}`", meta_item.name()));
}
Literal(_) => {
cx.error("unexpected literal in serde variant attribute");
}
}
}
}
let ser_name = ser_name.get();
let ser_renamed = ser_name.is_some();
let de_name = de_name.get();
let de_renamed = de_name.is_some();
Variant {
name: Name {
serialize: ser_name.unwrap_or_else(|| variant.ident.to_string()),
deserialize: de_name.unwrap_or_else(|| variant.ident.to_string()),
},
ser_renamed: ser_renamed,
de_renamed: de_renamed,
rename_all: rename_all.get().unwrap_or(RenameRule::None),
skip_deserializing: skip_deserializing.get(),
skip_serializing: skip_serializing.get(),
}
}
pub fn name(&self) -> &Name {
&self.name
}
pub fn rename_by_rule(&mut self, rule: &RenameRule) {
if !self.ser_renamed {
self.name.serialize = rule.apply_to_variant(&self.name.serialize);
}
if !self.de_renamed {
self.name.deserialize = rule.apply_to_variant(&self.name.deserialize);
}
}
pub fn rename_all(&self) -> &RenameRule {
&self.rename_all
}
pub fn skip_deserializing(&self) -> bool {
self.skip_deserializing
}
pub fn skip_serializing(&self) -> bool {
self.skip_serializing
}
}
/// Represents field attribute information
#[derive(Debug)]
pub struct Field {
name: Name,
ser_renamed: bool,
de_renamed: bool,
skip_serializing: bool,
skip_deserializing: bool,
skip_serializing_if: Option<syn::Path>,
default: Default,
serialize_with: Option<syn::Path>,
deserialize_with: Option<syn::Path>,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
}
/// Represents the default to use for a field when deserializing.
#[derive(Debug, PartialEq)]
pub enum Default {
/// Field must always be specified because it does not have a default.
None,
/// The default is given by `std::default::Default::default()`.
Default,
/// The default is given by this function.
Path(syn::Path),
}
impl Field {
/// Extract out the `#[serde(...)]` attributes from a struct field.
pub fn from_ast(cx: &Ctxt, index: usize, field: &syn::Field) -> Self {
let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename");
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing");
let mut skip_serializing_if = Attr::none(cx, "skip_serializing_if");
let mut default = Attr::none(cx, "default");
let mut serialize_with = Attr::none(cx, "serialize_with");
let mut deserialize_with = Attr::none(cx, "deserialize_with");
let mut ser_bound = Attr::none(cx, "bound");
let mut de_bound = Attr::none(cx, "bound");
let ident = match field.ident {
Some(ref ident) => ident.to_string(),
None => index.to_string(),
};
for meta_items in field.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
match meta_item {
// Parse `#[serde(rename="foo")]`
MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
ser_name.set(s.clone());
de_name.set(s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser);
de_name.set_opt(de);
}
}
// Parse `#[serde(default)]`
MetaItem(Word(ref name)) if name == "default" => {
default.set(Default::Default);
}
// Parse `#[serde(default="...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "default" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
default.set(Default::Path(path));
}
}
// Parse `#[serde(skip_serializing)]`
MetaItem(Word(ref name)) if name == "skip_serializing" => {
skip_serializing.set_true();
}
// Parse `#[serde(skip_deserializing)]`
MetaItem(Word(ref name)) if name == "skip_deserializing" => {
skip_deserializing.set_true();
}
// Parse `#[serde(skip_serializing_if="...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "skip_serializing_if" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
skip_serializing_if.set(path);
}
}
// Parse `#[serde(serialize_with="...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "serialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
serialize_with.set(path);
}
}
// Parse `#[serde(deserialize_with="...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "deserialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
deserialize_with.set(path);
}
}
// Parse `#[serde(with="...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "with" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
let mut ser_path = path.clone();
ser_path.segments.push("serialize".into());
serialize_with.set(ser_path);
let mut de_path = path;
de_path.segments.push("deserialize".into());
deserialize_with.set(de_path);
}
}
// Parse `#[serde(bound="D: Serialize")]`
MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
if let Ok(where_predicates) =
parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
}
}
// Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
MetaItem(List(ref name, ref meta_items)) if name == "bound" => {
if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
ser_bound.set_opt(ser);
de_bound.set_opt(de);
}
}
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde field attribute `{}`", meta_item.name()));
}
Literal(_) => {
cx.error("unexpected literal in serde field attribute");
}
}
}
}
// Is skip_deserializing, initialize the field to Default::default()
// unless a different default is specified by `#[serde(default="...")]`
if skip_deserializing.0.value.is_some() {
default.set_if_none(Default::Default);
}
let ser_name = ser_name.get();
let ser_renamed = ser_name.is_some();
let de_name = de_name.get();
let de_renamed = de_name.is_some();
Field {
name: Name {
serialize: ser_name.unwrap_or_else(|| ident.clone()),
deserialize: de_name.unwrap_or(ident),
},
ser_renamed: ser_renamed,
de_renamed: de_renamed,
skip_serializing: skip_serializing.get(),
skip_deserializing: skip_deserializing.get(),
skip_serializing_if: skip_serializing_if.get(),
default: default.get().unwrap_or(Default::None),
serialize_with: serialize_with.get(),
deserialize_with: deserialize_with.get(),
ser_bound: ser_bound.get(),
de_bound: de_bound.get(),
}
}
pub fn name(&self) -> &Name {
&self.name
}
pub fn rename_by_rule(&mut self, rule: &RenameRule) {
if !self.ser_renamed {
self.name.serialize = rule.apply_to_field(&self.name.serialize);
}
if !self.de_renamed {
self.name.deserialize = rule.apply_to_field(&self.name.deserialize);
}
}
pub fn skip_serializing(&self) -> bool {
self.skip_serializing
}
pub fn skip_deserializing(&self) -> bool {
self.skip_deserializing
}
pub fn skip_serializing_if(&self) -> Option<&syn::Path> {
self.skip_serializing_if.as_ref()
}
pub fn default(&self) -> &Default {
&self.default
}
pub fn serialize_with(&self) -> Option<&syn::Path> {
self.serialize_with.as_ref()
}
pub fn deserialize_with(&self) -> Option<&syn::Path> {
self.deserialize_with.as_ref()
}
pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
self.ser_bound.as_ref().map(|vec| &vec[..])
}
pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
}
type SerAndDe<T> = (Option<T>, Option<T>);
fn get_ser_and_de<T, F>(cx: &Ctxt,
attr_name: &'static str,
items: &[syn::NestedMetaItem],
f: F)
-> Result<SerAndDe<T>, ()>
where F: Fn(&Ctxt, &str, &str, &syn::Lit) -> Result<T, ()>
{
let mut ser_item = Attr::none(cx, attr_name);
let mut de_item = Attr::none(cx, attr_name);
for item in items {
match *item {
MetaItem(NameValue(ref name, ref lit)) if name == "serialize" => {
if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) {
ser_item.set(v);
}
}
MetaItem(NameValue(ref name, ref lit)) if name == "deserialize" => {
if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) {
de_item.set(v);
}
}
_ => {
cx.error(format!("malformed {0} attribute, expected `{0}(serialize = ..., \
deserialize = ...)`",
attr_name));
return Err(());
}
}
}
Ok((ser_item.get(), de_item.get()))
}
fn get_renames(cx: &Ctxt, items: &[syn::NestedMetaItem]) -> Result<SerAndDe<String>, ()> {
get_ser_and_de(cx, "rename", items, get_string_from_lit)
}
fn get_where_predicates(cx: &Ctxt,
items: &[syn::NestedMetaItem])
-> Result<SerAndDe<Vec<syn::WherePredicate>>, ()> {
get_ser_and_de(cx, "bound", items, parse_lit_into_where)
}
pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option<Vec<syn::NestedMetaItem>> {
match attr.value {
List(ref name, ref items) if name == "serde" => Some(items.iter().cloned().collect()),
_ => None,
}
}
fn get_string_from_lit(cx: &Ctxt,
attr_name: &str,
meta_item_name: &str,
lit: &syn::Lit)
-> Result<String, ()> {
if let syn::Lit::Str(ref s, _) = *lit {
Ok(s.clone())
} else {
cx.error(format!("expected serde {} attribute to be a string: `{} = \"...\"`",
attr_name,
meta_item_name));
Err(())
}
}
fn parse_lit_into_path(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::Path, ()> {
let string = try!(get_string_from_lit(cx, attr_name, attr_name, lit));
syn::parse_path(&string).map_err(|err| cx.error(err))
}
fn parse_lit_into_where(cx: &Ctxt,
attr_name: &str,
meta_item_name: &str,
lit: &syn::Lit)
-> Result<Vec<syn::WherePredicate>, ()> {
let string = try!(get_string_from_lit(cx, attr_name, meta_item_name, lit));
if string.is_empty() {
return Ok(Vec::new());
}
let where_string = format!("where {}", string);
syn::parse_where_clause(&where_string).map(|wh| wh.predicates).map_err(|err| cx.error(err))
}
fn parse_lit_into_ty(cx: &Ctxt,
attr_name: &str,
lit: &syn::Lit)
-> Result<syn::Ty, ()> {
let string = try!(get_string_from_lit(cx, attr_name, attr_name, lit));
syn::parse_type(&string).map_err(|_| {
cx.error(format!("failed to parse type: {} = {:?}", attr_name, string))
})
}
+115
View File
@@ -0,0 +1,115 @@
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 "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(),
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 | 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 {
"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, camel, snake, screaming, kebab) in
&[("Outcome", "outcome", "outcome", "OUTCOME", "outcome"),
("VeryTasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty"),
("A", "a", "a", "A", "a"),
("Z42", "z42", "z42", "Z42", "z42")] {
assert_eq!(None.apply_to_variant(original), original);
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);
}
}
+41
View File
@@ -0,0 +1,41 @@
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");
}
}
}
+9
View File
@@ -0,0 +1,9 @@
extern crate syn;
pub mod ast;
pub mod attr;
mod ctxt;
pub use ctxt::Ctxt;
mod case;
+27
View File
@@ -0,0 +1,27 @@
[package]
name = "serde_derive"
version = "0.9.13"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde.rs/codegen.html"
keywords = ["serde", "serialization", "no_std"]
readme = "../README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[features]
unstable = []
[badges]
travis-ci = { repository = "serde-rs/serde" }
[lib]
name = "serde_derive"
proc-macro = true
[dependencies]
quote = "0.3.8"
serde_codegen_internals = { version = "=0.14.2", default-features = false, path = "../serde_codegen_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
+228
View File
@@ -0,0 +1,228 @@
use std::collections::HashSet;
use syn::{self, visit};
use internals::ast::Item;
use internals::attr;
macro_rules! path {
($first:ident $(:: $rest:ident)*) => {
syn::Path {
global: false,
segments: vec![
stringify!($first).into(),
$(
stringify!($rest).into(),
)*
],
}
};
(::$first:ident $(:: $rest:ident)*) => {
syn::Path {
global: true,
segments: vec![
stringify!($first).into(),
$(
stringify!($rest).into(),
)*
],
}
};
}
// 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>(item: &Item,
generics: &syn::Generics,
from_field: F)
-> syn::Generics
where F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>
{
let predicates = item.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>(item: &Item,
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 = item.body
.all_fields()
.filter(|&field| filter(&field.attrs))
.map(|field| &field.ty);
let mut visitor = FindTyParams {
all_ty_params: all_ty_params,
relevant_ty_params: HashSet::new(),
};
for ty in relevant_tys {
visit::walk_ty(&mut visitor, ty);
}
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(item: &Item,
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(item),
// 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(item: &Item) -> syn::Ty {
syn::Ty::Path(None, syn::Path {
global: false,
segments: vec![
syn::PathSegment {
ident: item.ident.clone(),
parameters: syn::PathParameters::AngleBracketed(syn::AngleBracketedParameterData {
lifetimes: item.generics
.lifetimes
.iter()
.map(|def| def.lifetime.clone())
.collect(),
types: item.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
+67
View File
@@ -0,0 +1,67 @@
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("}");
}
}
}
}
+40
View File
@@ -0,0 +1,40 @@
#![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_codegen_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),
}
}
+792
View File
@@ -0,0 +1,792 @@
use syn::{self, Ident};
use quote::Tokens;
use bound;
use fragment::{Fragment, Stmts, Match};
use internals::ast::{Body, Field, Item, Style, Variant};
use internals::{self, attr};
pub fn expand_derive_serialize(item: &syn::DeriveInput) -> Result<Tokens, String> {
let ctxt = internals::Ctxt::new();
let item = Item::from_ast(&ctxt, item);
try!(ctxt.check());
let ident = &item.ident;
let generics = build_generics(&item);
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let dummy_const = Ident::new(format!("_IMPL_SERIALIZE_FOR_{}", ident));
let body = Stmts(serialize_body(&item, &generics));
Ok(quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
extern crate serde as _serde;
#[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
}
}
};
})
}
// 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(item: &Item) -> syn::Generics {
let generics = bound::without_defaults(item.generics);
let generics =
bound::with_where_predicates_from_fields(item, &generics, attr::Field::ser_bound);
match item.attrs.ser_bound() {
Some(predicates) => bound::with_where_predicates(&generics, predicates),
None => {
bound::with_bound(item,
&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(item: &Item, generics: &syn::Generics) -> Fragment {
if let Some(into_type) = item.attrs.into_type() {
serialize_into(into_type)
} else {
match item.body {
Body::Enum(ref variants) => {
serialize_item_enum(&item.ident, generics, variants, &item.attrs)
}
Body::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) {
panic!("struct has unnamed fields");
}
serialize_struct(&item.ident, generics, fields, &item.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(&item.ident, generics, fields, &item.attrs)
}
Body::Struct(Style::Newtype, ref fields) => {
serialize_newtype_struct(&item.ident, generics, &fields[0], &item.attrs)
}
Body::Struct(Style::Unit, _) => serialize_unit_struct(&item.attrs),
}
}
}
fn serialize_into(into_type: &syn::Ty) -> Fragment {
quote_block! {
_serde::Serialize::serialize(
&<Self as _serde::export::Into<#into_type>>::into(_serde::export::Clone::clone(self)),
__serializer)
}
}
fn serialize_unit_struct(item_attrs: &attr::Item) -> Fragment {
let type_name = item_attrs.name().serialize_name();
quote_expr! {
_serde::Serializer::serialize_unit_struct(__serializer, #type_name)
}
}
fn serialize_newtype_struct(ident: &syn::Ident,
generics: &syn::Generics,
field: &Field,
item_attrs: &attr::Item)
-> Fragment {
let type_name = item_attrs.name().serialize_name();
let mut field_expr = quote!(&self.0);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(ident, generics, field.ty, path, field_expr);
}
quote_expr! {
_serde::Serializer::serialize_newtype_struct(__serializer, #type_name, #field_expr)
}
}
fn serialize_tuple_struct(ident: &syn::Ident,
generics: &syn::Generics,
fields: &[Field],
item_attrs: &attr::Item)
-> Fragment {
let serialize_stmts =
serialize_tuple_struct_visitor(ident,
fields,
generics,
false,
quote!(_serde::ser::SerializeTupleStruct::serialize_field));
let type_name = item_attrs.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(ident: &syn::Ident,
generics: &syn::Generics,
fields: &[Field],
item_attrs: &attr::Item)
-> Fragment {
let serialize_fields =
serialize_struct_visitor(ident,
fields,
generics,
false,
quote!(_serde::ser::SerializeStruct::serialize_field));
let type_name = item_attrs.name().serialize_name();
let mut serialized_fields = fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields.map(|field| {
let ident = field.ident.clone().expect("struct has unnamed fields");
let field_expr = quote!(&self.#ident);
match field.attrs.skip_serializing_if() {
Some(path) => quote!(if #path(#field_expr) { 0 } else { 1 }),
None => quote!(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_item_enum(ident: &syn::Ident,
generics: &syn::Generics,
variants: &[Variant],
item_attrs: &attr::Item)
-> Fragment {
let arms: Vec<_> = variants.iter()
.enumerate()
.map(|(variant_index, variant)| {
serialize_variant(ident,
generics,
variant,
variant_index,
item_attrs)
})
.collect();
quote_expr! {
match *self {
#(#arms)*
}
}
}
fn serialize_variant(ident: &syn::Ident,
generics: &syn::Generics,
variant: &Variant,
variant_index: usize,
item_attrs: &attr::Item)
-> Tokens {
let variant_ident = variant.ident.clone();
if variant.attrs.skip_serializing() {
let skipped_msg = format!("the enum variant {}::{} cannot be serialized",
ident, 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! {
#ident::#variant_ident #fields_pat => #skipped_err,
}
} else {
// variant wasn't skipped
let case = match variant.style {
Style::Unit => {
quote! {
#ident::#variant_ident
}
}
Style::Newtype => {
quote! {
#ident::#variant_ident(ref __field0)
}
}
Style::Tuple => {
let field_names = (0..variant.fields.len())
.map(|i| Ident::new(format!("__field{}", i)));
quote! {
#ident::#variant_ident(#(ref #field_names),*)
}
}
Style::Struct => {
let fields = variant.fields
.iter()
.map(|f| f.ident.clone().expect("struct variant has unnamed fields"));
quote! {
#ident::#variant_ident { #(ref #fields),* }
}
}
};
let body = Match(match *item_attrs.tag() {
attr::EnumTag::External => {
serialize_externally_tagged_variant(ident,
generics,
variant,
variant_index,
item_attrs)
}
attr::EnumTag::Internal { ref tag } => {
serialize_internally_tagged_variant(ident,
generics,
variant,
item_attrs,
tag)
}
attr::EnumTag::Adjacent { ref tag, ref content } => {
serialize_adjacently_tagged_variant(ident,
generics,
variant,
item_attrs,
tag,
content)
}
attr::EnumTag::None => serialize_untagged_variant(ident, generics, variant, item_attrs),
});
quote! {
#case => #body
}
}
}
fn serialize_externally_tagged_variant(ident: &syn::Ident,
generics: &syn::Generics,
variant: &Variant,
variant_index: usize,
item_attrs: &attr::Item)
-> Fragment {
let type_name = item_attrs.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(ident, generics, 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,
},
ident,
generics,
&variant.fields)
}
Style::Struct => {
serialize_struct_variant(StructVariant::ExternallyTagged {
variant_index: variant_index,
variant_name: variant_name,
},
ident,
generics,
&variant.fields,
&type_name)
}
}
}
fn serialize_internally_tagged_variant(ident: &syn::Ident,
generics: &syn::Generics,
variant: &Variant,
item_attrs: &attr::Item,
tag: &str)
-> Fragment {
let type_name = item_attrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name();
let enum_ident_str = ident.as_ref();
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(ident, generics, field.ty, path, field_expr);
}
quote_expr! {
_serde::ser::private::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,
},
ident,
generics,
&variant.fields,
&type_name)
}
Style::Tuple => unreachable!("checked in serde_codegen_internals"),
}
}
fn serialize_adjacently_tagged_variant(ident: &syn::Ident,
generics: &syn::Generics,
variant: &Variant,
item_attrs: &attr::Item,
tag: &str,
content: &str)
-> Fragment {
let type_name = item_attrs.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(ident, generics, field.ty, path, field_expr);
}
quote_expr! {
_serde::Serialize::serialize(#field_expr, __serializer)
}
}
Style::Tuple => {
serialize_tuple_variant(TupleVariant::Untagged,
ident,
generics,
&variant.fields)
}
Style::Struct => {
serialize_struct_variant(StructVariant::Untagged,
ident,
generics,
&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) = generics.split_for_impl();
let wrapper_generics = bound::with_lifetime_bound(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<#ident #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::<#ident #ty_generics>,
}));
_serde::ser::SerializeStruct::end(__struct)
}
}
fn serialize_untagged_variant(ident: &syn::Ident,
generics: &syn::Generics,
variant: &Variant,
item_attrs: &attr::Item)
-> 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(ident, generics, field.ty, path, field_expr);
}
quote_expr! {
_serde::Serialize::serialize(#field_expr, __serializer)
}
}
Style::Tuple => {
serialize_tuple_variant(TupleVariant::Untagged, ident, generics, &variant.fields)
}
Style::Struct => {
let type_name = item_attrs.name().serialize_name();
serialize_struct_variant(StructVariant::Untagged,
ident,
generics,
&variant.fields,
&type_name)
}
}
}
enum TupleVariant {
ExternallyTagged {
type_name: String,
variant_index: usize,
variant_name: String,
},
Untagged,
}
fn serialize_tuple_variant(context: TupleVariant,
ident: &syn::Ident,
generics: &syn::Generics,
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(ident, fields, generics, 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: usize,
variant_name: String,
},
InternallyTagged { tag: &'a str, variant_name: String },
Untagged,
}
fn serialize_struct_variant<'a>(context: StructVariant<'a>,
ident: &syn::Ident,
generics: &syn::Generics,
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(ident, fields, generics, 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(ident: &syn::Ident,
fields: &[Field],
generics: &syn::Generics,
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 {
let i = Ident::new(i);
quote!(&self.#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(ident, generics, 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(ident: &syn::Ident,
fields: &[Field],
generics: &syn::Generics,
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 {
quote!(&self.#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(ident, generics, 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(ident: &syn::Ident,
generics: &syn::Generics,
field_ty: &syn::Ty,
serialize_with: &syn::Path,
value: Tokens)
-> Tokens {
let (_, ty_generics, where_clause) = generics.split_for_impl();
let wrapper_generics = bound::with_lifetime_bound(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<#ident #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::<#ident #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 }
}
-2
View File
@@ -1,2 +0,0 @@
/target
/Cargo.lock
-16
View File
@@ -1,16 +0,0 @@
[package]
name = "serde_macros"
version = "0.2.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A quasi-quoting macro system"
repository = "https://github.com/erickt/rust-quasi"
[lib]
name = "serde_macros"
plugin = true
[dependencies]
quasi = "0.1.3"
quasi_macros = "0.1.3"
aster = "0.1.3"
File diff suppressed because it is too large Load Diff
+18
View File
@@ -0,0 +1,18 @@
[package]
name = "serde_test"
version = "0.9.13"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://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 = "0.9", path = "../serde" }
[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
+57
View File
@@ -0,0 +1,57 @@
use serde::{Serialize, Deserialize};
use de::Deserializer;
use error::Error;
use ser::Serializer;
use token::Token;
use std::fmt::Debug;
/// Runs both `assert_ser_tokens` and `assert_de_tokens`.
pub fn assert_tokens<T>(value: &T, tokens: &[Token<'static>])
where T: Serialize + Deserialize + PartialEq + Debug
{
assert_ser_tokens(value, tokens);
assert_de_tokens(value, tokens);
}
/// Asserts that `value` serializes to the given `tokens`.
pub fn assert_ser_tokens<T>(value: &T, tokens: &[Token])
where T: Serialize
{
let mut ser = Serializer::new(tokens.iter());
assert_eq!(Serialize::serialize(value, &mut ser), Ok(()));
assert_eq!(ser.next_token(), None);
}
/// Asserts that `value` serializes to the given `tokens`, and then yields `error`.
pub fn assert_ser_tokens_error<T>(value: &T, tokens: &[Token], error: Error)
where T: Serialize + PartialEq + Debug
{
let mut ser = Serializer::new(tokens.iter());
let v: Result<(), Error> = Serialize::serialize(value, &mut ser);
assert_eq!(v.as_ref(), Err(&error));
assert_eq!(ser.next_token(), None);
}
/// Asserts that the given `tokens` deserialize into `value`.
pub fn assert_de_tokens<T>(value: &T, tokens: &[Token<'static>])
where T: Deserialize + PartialEq + Debug
{
let mut de = Deserializer::new(tokens.to_vec().into_iter());
let v: Result<T, Error> = Deserialize::deserialize(&mut de);
assert_eq!(v.as_ref(), Ok(value));
assert_eq!(de.next_token(), None);
}
/// Asserts that the given `tokens` yield `error` when deserializing.
pub fn assert_de_tokens_error<T>(tokens: &[Token<'static>], error: Error)
where T: Deserialize + PartialEq + Debug
{
let mut de = Deserializer::new(tokens.to_vec().into_iter());
let v: Result<T, Error> = Deserialize::deserialize(&mut de);
assert_eq!(v, Err(error));
// There may be one token left if a peek caused the error
de.next_token();
assert_eq!(de.next_token(), None);
}
+623
View File
@@ -0,0 +1,623 @@
use std::iter;
use serde::de::{self, Deserialize, DeserializeSeed, EnumVisitor, MapVisitor, SeqVisitor,
VariantVisitor, Visitor};
use serde::de::value::{ValueDeserializer, MapVisitorDeserializer, SeqVisitorDeserializer};
use error::Error;
use token::Token;
/// A `Deserializer` that reads from a list of tokens.
pub struct Deserializer<I>
where I: Iterator<Item = Token<'static>>
{
tokens: iter::Peekable<I>,
}
impl<I> Deserializer<I>
where I: Iterator<Item = Token<'static>>
{
/// Creates the deserializer.
pub fn new(tokens: I) -> Deserializer<I> {
Deserializer { tokens: tokens.peekable() }
}
/// Pulls the next token off of the deserializer, ignoring it.
pub fn next_token(&mut self) -> Option<Token<'static>> {
self.tokens.next()
}
/// Pulls the next token off of the deserializer and checks if it matches an expected token.
pub fn expect_token(&mut self, expected: Token) -> Result<(), Error> {
match self.tokens.next() {
Some(token) => {
if expected == token {
Ok(())
} else {
Err(Error::UnexpectedToken(token))
}
}
None => Err(Error::EndOfTokens),
}
}
fn visit_seq<V>(&mut self,
len: Option<usize>,
sep: Token<'static>,
end: Token<'static>,
visitor: V)
-> Result<V::Value, Error>
where V: Visitor
{
let value = try!(visitor.visit_seq(DeserializerSeqVisitor {
de: self,
len: len,
sep: sep,
end: end.clone(),
}));
try!(self.expect_token(end));
Ok(value)
}
fn visit_map<V>(&mut self,
len: Option<usize>,
sep: Token<'static>,
end: Token<'static>,
visitor: V)
-> Result<V::Value, Error>
where V: Visitor
{
let value = try!(visitor.visit_map(DeserializerMapVisitor {
de: self,
len: len,
sep: sep,
end: end.clone(),
}));
try!(self.expect_token(end));
Ok(value)
}
}
impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
where I: Iterator<Item = Token<'static>>
{
type Error = Error;
forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit
seq bytes byte_buf map struct_field ignored_any
}
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
where V: Visitor
{
match self.tokens.next() {
Some(Token::Bool(v)) => visitor.visit_bool(v),
Some(Token::I8(v)) => visitor.visit_i8(v),
Some(Token::I16(v)) => visitor.visit_i16(v),
Some(Token::I32(v)) => visitor.visit_i32(v),
Some(Token::I64(v)) => visitor.visit_i64(v),
Some(Token::U8(v)) => visitor.visit_u8(v),
Some(Token::U16(v)) => visitor.visit_u16(v),
Some(Token::U32(v)) => visitor.visit_u32(v),
Some(Token::U64(v)) => visitor.visit_u64(v),
Some(Token::F32(v)) => visitor.visit_f32(v),
Some(Token::F64(v)) => visitor.visit_f64(v),
Some(Token::Char(v)) => visitor.visit_char(v),
Some(Token::Str(v)) => visitor.visit_str(v),
Some(Token::String(v)) => visitor.visit_string(v),
Some(Token::Bytes(v)) => visitor.visit_bytes(v),
Some(Token::ByteBuf(v)) => visitor.visit_byte_buf(v),
Some(Token::Option(false)) => visitor.visit_none(),
Some(Token::Option(true)) => visitor.visit_some(self),
Some(Token::Unit) => visitor.visit_unit(),
Some(Token::UnitStruct(_name)) => visitor.visit_unit(),
Some(Token::SeqStart(len)) => {
self.visit_seq(len, Token::SeqSep, Token::SeqEnd, visitor)
}
Some(Token::SeqArrayStart(len)) => {
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
}
Some(Token::TupleStart(len)) => {
self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor)
}
Some(Token::TupleStructStart(_, len)) => {
self.visit_seq(Some(len),
Token::TupleStructSep,
Token::TupleStructEnd,
visitor)
}
Some(Token::MapStart(len)) => {
self.visit_map(len, Token::MapSep, Token::MapEnd, visitor)
}
Some(Token::StructStart(_, len)) => {
self.visit_map(Some(len), Token::StructSep, Token::StructEnd, visitor)
}
Some(Token::EnumUnit(_, variant)) => visitor.visit_str(variant),
Some(Token::EnumStart(variant)) |
Some(Token::EnumNewType(_, variant)) |
Some(Token::EnumSeqStart(_, variant, _)) |
Some(Token::EnumMapStart(_, variant, _)) => {
visitor.visit_map(EnumMapVisitor::new(self, variant))
}
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfTokens),
}
}
/// Hook into `Option` deserializing so we can treat `Unit` as a
/// `None`, or a regular value as `Some(value)`.
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
where V: Visitor
{
match self.tokens.peek() {
Some(&Token::Unit) |
Some(&Token::Option(false)) => {
self.tokens.next();
visitor.visit_none()
}
Some(&Token::Option(true)) => {
self.tokens.next();
visitor.visit_some(self)
}
Some(_) => visitor.visit_some(self),
None => Err(Error::EndOfTokens),
}
}
fn deserialize_enum<V>(self,
name: &str,
_variants: &'static [&'static str],
visitor: V)
-> Result<V::Value, Error>
where V: Visitor
{
match self.tokens.peek() {
Some(&Token::EnumStart(n)) if name == n => {
self.tokens.next();
visitor.visit_enum(DeserializerEnumVisitor { de: self })
}
Some(&Token::EnumUnit(n, _)) |
Some(&Token::EnumNewType(n, _)) |
Some(&Token::EnumSeqStart(n, _, _)) |
Some(&Token::EnumMapStart(n, _, _)) if name == n => {
visitor.visit_enum(DeserializerEnumVisitor { de: self })
}
Some(_) => {
let token = self.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfTokens),
}
}
fn deserialize_unit_struct<V>(self, name: &str, visitor: V) -> Result<V::Value, Error>
where V: Visitor
{
match self.tokens.peek() {
Some(&Token::UnitStruct(n)) => {
self.tokens.next();
if name == n {
visitor.visit_unit()
} else {
Err(Error::InvalidName(n))
}
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfTokens),
}
}
fn deserialize_newtype_struct<V>(self, name: &str, visitor: V) -> Result<V::Value, Error>
where V: Visitor
{
match self.tokens.peek() {
Some(&Token::StructNewType(n)) => {
self.tokens.next();
if name == n {
visitor.visit_newtype_struct(self)
} else {
Err(Error::InvalidName(n))
}
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfTokens),
}
}
fn deserialize_seq_fixed_size<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
where V: Visitor
{
match self.tokens.peek() {
Some(&Token::SeqArrayStart(_)) => {
self.tokens.next();
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfTokens),
}
}
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
where V: Visitor
{
match self.tokens.peek() {
Some(&Token::Unit) |
Some(&Token::UnitStruct(_)) => {
self.tokens.next();
visitor.visit_unit()
}
Some(&Token::SeqStart(_)) => {
self.tokens.next();
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
}
Some(&Token::SeqArrayStart(_)) => {
self.tokens.next();
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
}
Some(&Token::TupleStart(_)) => {
self.tokens.next();
self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor)
}
Some(&Token::TupleStructStart(_, _)) => {
self.tokens.next();
self.visit_seq(Some(len),
Token::TupleStructSep,
Token::TupleStructEnd,
visitor)
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfTokens),
}
}
fn deserialize_tuple_struct<V>(self,
name: &str,
len: usize,
visitor: V)
-> Result<V::Value, Error>
where V: Visitor
{
match self.tokens.peek() {
Some(&Token::Unit) => {
self.tokens.next();
visitor.visit_unit()
}
Some(&Token::UnitStruct(n)) => {
self.tokens.next();
if name == n {
visitor.visit_unit()
} else {
Err(Error::InvalidName(n))
}
}
Some(&Token::SeqStart(_)) => {
self.tokens.next();
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
}
Some(&Token::SeqArrayStart(_)) => {
self.tokens.next();
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
}
Some(&Token::TupleStart(_)) => {
self.tokens.next();
self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor)
}
Some(&Token::TupleStructStart(n, _)) => {
self.tokens.next();
if name == n {
self.visit_seq(Some(len),
Token::TupleStructSep,
Token::TupleStructEnd,
visitor)
} else {
Err(Error::InvalidName(n))
}
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfTokens),
}
}
fn deserialize_struct<V>(self,
name: &str,
fields: &'static [&'static str],
visitor: V)
-> Result<V::Value, Error>
where V: Visitor
{
match self.tokens.peek() {
Some(&Token::StructStart(n, _)) => {
self.tokens.next();
if name == n {
self.visit_map(Some(fields.len()),
Token::StructSep,
Token::StructEnd,
visitor)
} else {
Err(Error::InvalidName(n))
}
}
Some(&Token::MapStart(_)) => {
self.tokens.next();
self.visit_map(Some(fields.len()), Token::MapSep, Token::MapEnd, visitor)
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfTokens),
}
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerSeqVisitor<'a, I: 'a>
where I: Iterator<Item = Token<'static>>
{
de: &'a mut Deserializer<I>,
len: Option<usize>,
sep: Token<'static>,
end: Token<'static>,
}
impl<'a, I> SeqVisitor for DeserializerSeqVisitor<'a, I>
where I: Iterator<Item = Token<'static>>
{
type Error = Error;
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where T: DeserializeSeed
{
if self.de.tokens.peek() == Some(&self.end) {
return Ok(None);
}
match self.de.tokens.next() {
Some(ref token) if *token == self.sep => {
self.len = self.len.map(|len| len.saturating_sub(1));
seed.deserialize(&mut *self.de).map(Some)
}
Some(other) => Err(Error::UnexpectedToken(other)),
None => Err(Error::EndOfTokens),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len.unwrap_or(0);
(len, self.len)
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerMapVisitor<'a, I: 'a>
where I: Iterator<Item = Token<'static>>
{
de: &'a mut Deserializer<I>,
len: Option<usize>,
sep: Token<'static>,
end: Token<'static>,
}
impl<'a, I> MapVisitor for DeserializerMapVisitor<'a, I>
where I: Iterator<Item = Token<'static>>
{
type Error = Error;
fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where K: DeserializeSeed
{
if self.de.tokens.peek() == Some(&self.end) {
return Ok(None);
}
match self.de.tokens.next() {
Some(ref token) if *token == self.sep => {
self.len = self.len.map(|len| len.saturating_sub(1));
seed.deserialize(&mut *self.de).map(Some)
}
Some(other) => Err(Error::UnexpectedToken(other)),
None => Err(Error::EndOfTokens),
}
}
fn visit_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
where V: DeserializeSeed
{
seed.deserialize(&mut *self.de)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len.unwrap_or(0);
(len, self.len)
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerEnumVisitor<'a, I: 'a>
where I: Iterator<Item = Token<'static>>
{
de: &'a mut Deserializer<I>,
}
impl<'a, I> EnumVisitor for DeserializerEnumVisitor<'a, I>
where I: Iterator<Item = Token<'static>>
{
type Error = Error;
type Variant = Self;
fn visit_variant_seed<V>(self, seed: V) -> Result<(V::Value, Self), Error>
where V: DeserializeSeed
{
match self.de.tokens.peek() {
Some(&Token::EnumUnit(_, v)) |
Some(&Token::EnumNewType(_, v)) |
Some(&Token::EnumSeqStart(_, v, _)) |
Some(&Token::EnumMapStart(_, v, _)) => {
let de = v.into_deserializer();
let value = try!(seed.deserialize(de));
Ok((value, self))
}
Some(_) => {
let value = try!(seed.deserialize(&mut *self.de));
Ok((value, self))
}
None => Err(Error::EndOfTokens),
}
}
}
impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I>
where I: Iterator<Item = Token<'static>>
{
type Error = Error;
fn visit_unit(self) -> Result<(), Error> {
match self.de.tokens.peek() {
Some(&Token::EnumUnit(_, _)) => {
self.de.tokens.next();
Ok(())
}
Some(_) => Deserialize::deserialize(self.de),
None => Err(Error::EndOfTokens),
}
}
fn visit_newtype_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
where T: DeserializeSeed
{
match self.de.tokens.peek() {
Some(&Token::EnumNewType(_, _)) => {
self.de.tokens.next();
seed.deserialize(self.de)
}
Some(_) => seed.deserialize(self.de),
None => Err(Error::EndOfTokens),
}
}
fn visit_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
where V: Visitor
{
match self.de.tokens.peek() {
Some(&Token::EnumSeqStart(_, _, enum_len)) => {
let token = self.de.tokens.next().unwrap();
if len == enum_len {
self.de.visit_seq(Some(len), Token::EnumSeqSep, Token::EnumSeqEnd, visitor)
} else {
Err(Error::UnexpectedToken(token))
}
}
Some(&Token::SeqStart(Some(enum_len))) => {
let token = self.de.tokens.next().unwrap();
if len == enum_len {
self.de.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
} else {
Err(Error::UnexpectedToken(token))
}
}
Some(_) => de::Deserializer::deserialize(self.de, visitor),
None => Err(Error::EndOfTokens),
}
}
fn visit_struct<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value, Error>
where V: Visitor
{
match self.de.tokens.peek() {
Some(&Token::EnumMapStart(_, _, enum_len)) => {
let token = self.de.tokens.next().unwrap();
if fields.len() == enum_len {
self.de.visit_map(Some(fields.len()),
Token::EnumMapSep,
Token::EnumMapEnd,
visitor)
} else {
Err(Error::UnexpectedToken(token))
}
}
Some(&Token::MapStart(Some(enum_len))) => {
let token = self.de.tokens.next().unwrap();
if fields.len() == enum_len {
self.de.visit_map(Some(fields.len()), Token::MapSep, Token::MapEnd, visitor)
} else {
Err(Error::UnexpectedToken(token))
}
}
Some(_) => de::Deserializer::deserialize(self.de, visitor),
None => Err(Error::EndOfTokens),
}
}
}
//////////////////////////////////////////////////////////////////////////
struct EnumMapVisitor<'a, I: 'a>
where I: Iterator<Item = Token<'static>>
{
de: &'a mut Deserializer<I>,
variant: Option<&'a str>,
}
impl<'a, I: 'a> EnumMapVisitor<'a, I>
where I: Iterator<Item = Token<'static>>
{
fn new(de: &'a mut Deserializer<I>, variant: &'a str) -> Self {
EnumMapVisitor {
de: de,
variant: Some(variant),
}
}
}
impl<'a, I: 'a> MapVisitor for EnumMapVisitor<'a, I>
where I: Iterator<Item = Token<'static>>
{
type Error = Error;
fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where K: DeserializeSeed
{
match self.variant.take() {
Some(variant) => seed.deserialize(variant.into_deserializer()).map(Some),
None => Ok(None),
}
}
fn visit_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
where V: DeserializeSeed
{
match self.de.tokens.peek() {
Some(&Token::EnumSeqSep) => {
let value = {
let visitor = DeserializerSeqVisitor {
de: self.de,
len: None,
sep: Token::EnumSeqSep,
end: Token::EnumSeqEnd,
};
try!(seed.deserialize(SeqVisitorDeserializer::new(visitor)))
};
try!(self.de.expect_token(Token::EnumSeqEnd));
Ok(value)
}
Some(&Token::EnumMapSep) => {
let value = {
let visitor = DeserializerMapVisitor {
de: self.de,
len: None,
sep: Token::EnumMapSep,
end: Token::EnumMapEnd,
};
try!(seed.deserialize(MapVisitorDeserializer::new(visitor)))
};
try!(self.de.expect_token(Token::EnumMapEnd));
Ok(value)
}
_ => seed.deserialize(&mut *self.de),
}
}
}
+56
View File
@@ -0,0 +1,56 @@
use std::error;
use std::fmt::{self, Display};
use serde::{ser, de};
use token::Token;
/// Error returned by the test `Serializer` and `Deserializer`.
#[derive(Clone, PartialEq, Debug)]
pub enum Error {
/// A custom error.
Message(String),
/// `Deserialize` was expecting a struct of one name, and another was found.
InvalidName(&'static str),
/// `Serialize` generated a token that didn't match the test.
UnexpectedToken(Token<'static>),
/// The expected token list was too short.
EndOfTokens,
}
impl ser::Error for Error {
fn custom<T: Display>(msg: T) -> Error {
Error::Message(msg.to_string())
}
}
impl de::Error for Error {
fn custom<T: Display>(msg: T) -> Error {
Error::Message(msg.to_string())
}
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Message(ref msg) => formatter.write_str(msg),
Error::InvalidName(name) => write!(formatter, "invalid name `{}`", name),
Error::UnexpectedToken(_) => formatter.write_str("unexpected token"),
Error::EndOfTokens => formatter.write_str("end of tokens"),
}
}
}
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::Message(ref msg) => msg,
Error::InvalidName(_) => "invalid name",
Error::UnexpectedToken(_) => "unexpected token",
Error::EndOfTokens => "end of tokens",
}
}
}
+18
View File
@@ -0,0 +1,18 @@
#[macro_use]
extern crate serde;
mod assert;
pub use assert::{assert_tokens, assert_ser_tokens, assert_ser_tokens_error, assert_de_tokens,
assert_de_tokens_error};
mod ser;
pub use ser::Serializer;
mod de;
pub use de::Deserializer;
mod token;
pub use token::Token;
mod error;
pub use error::Error;
+366
View File
@@ -0,0 +1,366 @@
use std::marker::PhantomData;
use serde::{ser, Serialize};
use error::Error;
use token::Token;
/// A `Serializer` that ensures that a value serializes to a given list of tokens.
pub struct Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
tokens: I,
phantom: PhantomData<&'a Token<'a>>,
}
impl<'a, I> Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
/// Creates the serializer.
pub fn new(tokens: I) -> Serializer<'a, I> {
Serializer {
tokens: tokens,
phantom: PhantomData,
}
}
/// Pulls the next token off of the serializer, ignoring it.
pub fn next_token(&mut self) -> Option<&'a Token<'a>> {
self.tokens.next()
}
}
impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = ();
type Error = Error;
type SerializeSeq = Self;
type SerializeTuple = Self;
type SerializeTupleStruct = Self;
type SerializeTupleVariant = Self;
type SerializeMap = Self;
type SerializeStruct = Self;
type SerializeStructVariant = Self;
fn serialize_bool(self, v: bool) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Bool(v)));
Ok(())
}
fn serialize_i8(self, v: i8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I8(v)));
Ok(())
}
fn serialize_i16(self, v: i16) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I16(v)));
Ok(())
}
fn serialize_i32(self, v: i32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I32(v)));
Ok(())
}
fn serialize_i64(self, v: i64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I64(v)));
Ok(())
}
fn serialize_u8(self, v: u8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U8(v)));
Ok(())
}
fn serialize_u16(self, v: u16) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U16(v)));
Ok(())
}
fn serialize_u32(self, v: u32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U32(v)));
Ok(())
}
fn serialize_u64(self, v: u64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U64(v)));
Ok(())
}
fn serialize_f32(self, v: f32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::F32(v)));
Ok(())
}
fn serialize_f64(self, v: f64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::F64(v)));
Ok(())
}
fn serialize_char(self, v: char) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Char(v)));
Ok(())
}
fn serialize_str(self, v: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Str(v)));
Ok(())
}
fn serialize_bytes(self, value: &[u8]) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::Bytes(value)));
Ok(())
}
fn serialize_unit(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Unit));
Ok(())
}
fn serialize_unit_struct(self, name: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::UnitStruct(name)));
Ok(())
}
fn serialize_unit_variant(self,
name: &str,
_variant_index: usize,
variant: &str)
-> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumUnit(name, variant)));
Ok(())
}
fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::StructNewType(name)));
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(self,
name: &str,
_variant_index: usize,
variant: &str,
value: &T)
-> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::EnumNewType(name, variant)));
value.serialize(self)
}
fn serialize_none(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Option(false)));
Ok(())
}
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::Option(true)));
value.serialize(self)
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::SeqStart(len)));
Ok(self)
}
fn serialize_seq_fixed_size(self, len: usize) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::SeqArrayStart(len)));
Ok(self)
}
fn serialize_tuple(self, len: usize) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleStart(len)));
Ok(self)
}
fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
assert_eq!(self.tokens.next(),
Some(&Token::TupleStructStart(name, len)));
Ok(self)
}
fn serialize_tuple_variant(self,
name: &str,
_variant_index: usize,
variant: &str,
len: usize)
-> Result<Self, Error> {
assert_eq!(self.tokens.next(),
Some(&Token::EnumSeqStart(name, variant, len)));
Ok(self)
}
fn serialize_map(self, len: Option<usize>) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::MapStart(len)));
Ok(self)
}
fn serialize_struct(self, name: &str, len: usize) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::StructStart(name, len)));
Ok(self)
}
fn serialize_struct_variant(self,
name: &str,
_variant_index: usize,
variant: &str,
len: usize)
-> Result<Self, Error> {
assert_eq!(self.tokens.next(),
Some(&Token::EnumMapStart(name, variant, len)));
Ok(self)
}
}
impl<'s, 'a, I> ser::SerializeSeq for &'s mut Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = ();
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::SeqSep));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::SeqEnd));
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeTuple for &'s mut Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = ();
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::TupleSep));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleEnd));
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeTupleStruct for &'s mut Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::TupleStructSep));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleStructEnd));
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeTupleVariant for &'s mut Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqSep));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqEnd));
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeMap for &'s mut Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = ();
type Error = Error;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::MapSep));
key.serialize(&mut **self)
}
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where T: Serialize
{
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::MapEnd));
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeStruct for &'s mut Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self,
key: &'static str,
value: &T)
-> Result<(), Self::Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::StructSep));
try!(key.serialize(&mut **self));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::StructEnd));
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeStructVariant for &'s mut Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self,
key: &'static str,
value: &T)
-> Result<(), Self::Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::EnumMapSep));
try!(key.serialize(&mut **self));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumMapEnd));
Ok(())
}
}
+170
View File
@@ -0,0 +1,170 @@
#[derive(Clone, PartialEq, Debug)]
pub enum Token<'a> {
/// A serialized `bool`.
Bool(bool),
/// A serialized `i8`.
I8(i8),
/// A serialized `i16`.
I16(i16),
/// A serialized `i32`.
I32(i32),
/// A serialized `i64`.
I64(i64),
/// A serialized `u8`.
U8(u8),
/// A serialized `u16`.
U16(u16),
/// A serialized `u32`.
U32(u32),
/// A serialized `u64`.
U64(u64),
/// A serialized `f32`.
F32(f32),
/// A serialized `f64`.
F64(f64),
/// A serialized `char`.
Char(char),
/// A serialized `str`.
Str(&'a str),
/// A serialized `String`.
String(String),
/// A serialized `[u8]`
Bytes(&'a [u8]),
/// A serialized `ByteBuf`
ByteBuf(Vec<u8>),
/// The header to a serialized `Option<T>`.
///
/// `None` is serialized as `Option(false)`, while `Some` is serialized as `Option(true)`, then
/// the value contained in the option.
Option(bool),
/// A serialized `()`.
Unit,
/// A serialized unit struct of the given name.
UnitStruct(&'a str),
/// The header to a serialized newtype struct of the given name.
///
/// Newtype structs are serialized with this header, followed by the value contained in the
/// newtype struct.
StructNewType(&'a str),
/// The header to an enum of the given name.
///
/// This token is only used for deserializers, and ensures that the following tokens are read as
/// an enum. Because this is never emitted by serializers, calling `assert_ser_tokens` or
/// `assert_tokens` will fail if this token is used.
///
/// TODO: Trash this.
EnumStart(&'a str),
/// A unit variant of an enum of the given name, of the given name.
///
/// The first string represents the name of the enum, and the second represents the name of the
/// variant.
EnumUnit(&'a str, &'a str),
/// The header to a newtype variant of an enum of the given name, of the given name.
///
/// The first string represents the name of the enum, and the second represents the name of the
/// variant. The value contained within this enum works the same as `StructNewType`.
EnumNewType(&'a str, &'a str),
/// The header to a sequence of the given length.
///
/// These are serialized via `serialize_seq`, which takes an optional length. After this
/// header is a list of elements, followed by `SeqEnd`.
SeqStart(Option<usize>),
/// The header to an array of the given length.
///
/// These are serialized via `serialize_seq_fized_size`, which requires a length. After this
/// header is a list of elements, followed by `SeqEnd`.
SeqArrayStart(usize),
/// A separator, which occurs *before* every element in a sequence.
///
/// Elements in sequences are represented by a `SeqSep`, followed by the value of the element.
SeqSep,
/// An indicator of the end of a sequence.
SeqEnd,
/// The header to a tuple of the given length, similar to `SeqArrayStart`.
TupleStart(usize),
/// A separator, similar to `SeqSep`.
TupleSep,
/// An indicator of the end of a tuple, similar to `SeqEnd`.
TupleEnd,
/// The header to a tuple struct of the given name and length.
TupleStructStart(&'a str, usize),
/// A separator, similar to `TupleSep`.
TupleStructSep,
/// An indicator of the end of a tuple struct, similar to `TupleEnd`.
TupleStructEnd,
/// The header to a map of the given length.
///
/// These are serialized via `serialize_map`, which takes an optional length. After this header
/// is a list of key-value pairs, followed by `MapEnd`.
MapStart(Option<usize>),
/// A separator, which occurs *before* every key-value pair in a map.
///
/// Elements in maps are represented by a `MapSep`, followed by a serialized key, followed
/// by a serialized value.
MapSep,
/// An indicator of the end of a map.
MapEnd,
/// The header of a struct of the given name and length, similar to `MapStart`.
StructStart(&'a str, usize),
/// A separator, similar to `MapSep`.
StructSep,
/// An indicator of the end of a struct, similar to `MapEnd`.
StructEnd,
/// The header to a tuple variant of an enum of the given name, of the given name and length.
EnumSeqStart(&'a str, &'a str, usize),
/// A separator, similar to `TupleSep`.
EnumSeqSep,
/// An indicator of the end of a tuple variant, similar to `TupleEnd`.
EnumSeqEnd,
/// The header of a struct variant of an enum of the given name, of the given name and length,
/// similar to `StructStart`.
EnumMapStart(&'a str, &'a str, usize),
/// A separator, similar to `StructSep`.
EnumMapSep,
/// An indicator of the end of a struct, similar to `StructEnd`.
EnumMapEnd,
}
-819
View File
@@ -1,819 +0,0 @@
use std::collections::{HashMap, BTreeMap};
use std::hash::Hash;
use std::marker::PhantomData;
use std::num::FromPrimitive;
use std::path;
use std::str;
///////////////////////////////////////////////////////////////////////////////
pub trait Error {
fn syntax_error() -> Self;
fn end_of_stream_error() -> Self;
fn missing_field_error(&'static str) -> Self;
}
pub trait Deserialize {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer;
}
pub trait Deserializer {
type Error: Error;
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_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, 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,
{
// The unwraps in here should be safe.
let mut s = &mut [0; 4];
let len = v.encode_utf8(s).unwrap();
self.visit_str(str::from_utf8(&s[..len]).unwrap())
}
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())
}
#[inline]
fn visit_named_seq<V>(&mut self, _name: &str, visitor: V) -> Result<Self::Value, V::Error>
where V: SeqVisitor,
{
self.visit_seq(visitor)
}
fn visit_map<V>(&mut self, _visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor,
{
Err(Error::syntax_error())
}
#[inline]
fn visit_named_map<V>(&mut self, _name: &str, visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor,
{
self.visit_map(visitor)
}
#[inline]
fn visit_enum<V>(&mut self,
_name: &str,
_variant: &str,
_visitor: V) -> Result<Self::Value, V::Error>
where V: EnumVisitor,
{
Err(Error::syntax_error())
}
#[inline]
fn visit_variant<V>(&mut self, _name: &str, _visitor: V) -> Result<Self::Value, V::Error>
where V: EnumVisitor,
{
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)
}
}
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()
}
}
///////////////////////////////////////////////////////////////////////////////
pub trait EnumVisitor {
type Error: Error;
fn visit_unit(&mut self) -> Result<(), Self::Error> {
Err(Error::syntax_error())
}
fn visit_seq<V>(&mut self, _visitor: V) -> Result<V::Value, Self::Error>
where V: EnumSeqVisitor,
{
Err(Error::syntax_error())
}
fn visit_map<V>(&mut self, _visitor: V) -> Result<V::Value, Self::Error>
where V: EnumMapVisitor,
{
Err(Error::syntax_error())
}
}
///////////////////////////////////////////////////////////////////////////////
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;
}
///////////////////////////////////////////////////////////////////////////////
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
> self::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 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_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);
}
Ok(values)
}
}
impl<T: Deserialize> Deserialize for Vec<T> {
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 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_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);
}
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())
}
}
///////////////////////////////////////////////////////////////////////////////
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_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);
}
Ok(values)
}
}
impl<
K: Deserialize + Eq + Ord,
V: Deserialize,
> Deserialize for BTreeMap<K, V> {
fn deserialize<D>(deserializer: &mut D) -> Result<BTreeMap<K, V>, D::Error>
where D: Deserializer,
{
deserializer.visit(BTreeMapVisitor::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(path::PathBuf::new(&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)
}
}
-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
}
}
-636
View File
@@ -1,636 +0,0 @@
use std::char;
use std::num::Float;
use unicode::str::Utf16Item;
use std::str;
use de;
use super::error::{Error, ErrorCode};
pub struct Deserializer<Iter> {
rdr: Iter,
ch: Option<u8>,
line: usize,
col: usize,
buf: Vec<u8>,
}
impl<Iter> Deserializer<Iter>
where Iter: Iterator<Item=u8>,
{
/// Creates the JSON parser.
#[inline]
pub fn new(rdr: Iter) -> Deserializer<Iter> {
let mut p = Deserializer {
rdr: rdr,
ch: Some(b'\x00'),
line: 1,
col: 0,
buf: Vec::with_capacity(128),
};
p.bump();
return p;
}
#[inline]
pub fn end(&mut self) -> Result<(), Error> {
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) {
self.ch = self.rdr.next();
if self.ch_is(b'\n') {
self.line += 1;
self.col = 1;
} else {
self.col += 1;
}
}
fn next_char(&mut self) -> Option<u8> {
self.bump();
self.ch
}
fn ch_is(&self, c: u8) -> bool {
self.ch == Some(c)
}
fn error(&mut self, reason: ErrorCode) -> Error {
Error::SyntaxError(reason, self.line, self.col)
}
fn parse_whitespace(&mut self) {
while self.ch_is(b' ') ||
self.ch_is(b'\n') ||
self.ch_is(b'\t') ||
self.ch_is(b'\r') { self.bump(); }
}
fn parse_value<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
self.parse_whitespace();
if self.eof() {
return Err(self.error(ErrorCode::EOFWhileParsingValue));
}
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.buf).unwrap();
visitor.visit_str(s)
}
b'[' => {
self.bump();
visitor.visit_seq(SeqVisitor::new(self))
}
b'{' => {
self.bump();
visitor.visit_map(MapVisitor::new(self))
}
_ => {
Err(self.error(ErrorCode::ExpectedSomeValue))
}
}
}
fn parse_ident(&mut self, ident: &[u8]) -> Result<(), Error> {
if ident.iter().all(|c| Some(*c) == self.next_char()) {
self.bump();
Ok(())
} else {
Err(self.error(ErrorCode::ExpectedSomeIdent))
}
}
fn parse_number<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
let mut neg = 1;
if self.ch_is(b'-') {
self.bump();
neg = -1;
}
let res = try!(self.parse_integer());
if self.ch_is(b'.') || self.ch_is(b'e') || self.ch_is(b'E') {
let neg = neg as f64;
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));
}
visitor.visit_f64(neg * res)
} else {
visitor.visit_i64(neg * res)
}
}
fn parse_integer(&mut self) -> Result<i64, Error> {
let mut res = 0;
match self.ch_or_null() {
b'0' => {
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 i64) - (b'0' as i64);
self.bump();
}
_ => break,
}
}
}
_ => { return Err(self.error(ErrorCode::InvalidNumber)); }
}
Ok(res)
}
fn parse_decimal(&mut self, res: f64) -> Result<f64, Error> {
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;
self.bump();
}
_ => break,
}
}
Ok(res)
}
fn parse_exponent(&mut self, mut res: f64) -> Result<f64, Error> {
self.bump();
let mut exp = 0;
let mut neg_exp = false;
if self.ch_is(b'+') {
self.bump();
} else if self.ch_is(b'-') {
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);
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() {
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.buf.clear();
let mut escape = false;
loop {
let ch = match self.next_char() {
Some(ch) => ch,
None => { return Err(self.error(ErrorCode::EOFWhileParsingString)); }
};
if escape {
match ch {
b'"' => self.buf.push(b'"'),
b'\\' => self.buf.push(b'\\'),
b'/' => self.buf.push(b'/'),
b'b' => self.buf.push(b'\x08'),
b'f' => self.buf.push(b'\x0c'),
b'n' => self.buf.push(b'\n'),
b'r' => self.buf.push(b'\r'),
b't' => self.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 => {
let c1 = self.next_char();
let c2 = self.next_char();
match (c1, c2) {
(Some(b'\\'), Some(b'u')) => (),
_ => {
return Err(self.error(ErrorCode::UnexpectedEndOfHexEscape));
}
}
let buf = &[n1, try!(self.decode_hex_escape())];
match ::unicode::str::utf16_items(buf).next() {
Some(Utf16Item::ScalarValue(c)) => c,
_ => {
return Err(self.error(ErrorCode::LoneLeadingSurrogateInHexEscape));
}
}
}
n => match char::from_u32(n as u32) {
Some(c) => c,
None => {
return Err(self.error(ErrorCode::InvalidUnicodeCodePoint));
}
}
};
let buf = &mut [0; 4];
let len = c.encode_utf8(buf).unwrap_or(0);
self.buf.extend(buf[..len].iter().map(|b| *b));
}
_ => {
return Err(self.error(ErrorCode::InvalidEscape));
}
}
escape = false;
} else {
match ch {
b'"' => {
self.bump();
return Ok(());
}
b'\\' => {
escape = true;
}
ch => {
self.buf.push(ch);
}
}
}
}
}
fn parse_object_colon(&mut self) -> Result<(), Error> {
self.parse_whitespace();
if self.ch_is(b':') {
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=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,
{
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, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
self.parse_whitespace();
if self.ch_is(b'{') {
self.bump();
self.parse_whitespace();
try!(self.parse_string());
try!(self.parse_object_colon());
let variant = str::from_utf8(&self.buf).unwrap().to_string();
let value = try!(visitor.visit_variant(&variant, EnumVisitor {
de: self,
}));
self.parse_whitespace();
if self.ch_is(b'}') {
self.bump();
Ok(value)
} else {
return Err(self.error(ErrorCode::ExpectedSomeValue));
}
} else {
Err(self.error(ErrorCode::ExpectedSomeValue))
}
}
}
struct SeqVisitor<'a, Iter: 'a> {
de: &'a mut Deserializer<Iter>,
first: bool,
}
impl<'a, Iter> 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=u8>
{
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: de::Deserialize,
{
self.de.parse_whitespace();
if self.de.ch_is(b']') {
self.de.bump();
return Ok(None);
}
if self.first {
self.first = false;
} else {
if self.de.ch_is(b',') {
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> {
self.de.parse_whitespace();
if self.de.ch_is(b']') {
self.de.bump();
Ok(())
} else if self.de.eof() {
Err(self.de.error(ErrorCode::EOFWhileParsingList))
} else {
Err(self.de.error(ErrorCode::TrailingCharacters))
}
}
}
struct MapVisitor<'a, Iter: 'a> {
de: &'a mut Deserializer<Iter>,
first: bool,
}
impl<'a, Iter> 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=u8>
{
type Error = Error;
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
where K: de::Deserialize,
{
self.de.parse_whitespace();
if self.de.ch_is(b'}') {
self.de.bump();
return Ok(None);
}
if self.first {
self.first = false;
} else {
if self.de.ch_is(b',') {
self.de.bump();
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> {
self.de.parse_whitespace();
if self.de.ch_is(b']') {
self.de.bump();
Ok(())
} else if self.de.eof() {
Err(self.de.error(ErrorCode::EOFWhileParsingList))
} else {
Err(self.de.error(ErrorCode::TrailingCharacters))
}
}
}
struct EnumVisitor<'a, Iter: 'a> {
de: &'a mut Deserializer<Iter>,
}
impl<'a, Iter> de::EnumVisitor for EnumVisitor<'a, Iter>
where Iter: Iterator<Item=u8>,
{
type Error = Error;
fn visit_unit(&mut self) -> Result<(), Error> {
de::Deserialize::deserialize(self.de)
}
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::EnumSeqVisitor,
{
self.de.parse_whitespace();
if self.de.ch_is(b'[') {
self.de.bump();
visitor.visit(SeqVisitor::new(self.de))
} else {
Err(self.de.error(ErrorCode::ExpectedSomeValue))
}
}
fn visit_map<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::EnumMapVisitor,
{
self.de.parse_whitespace();
if self.de.ch_is(b'{') {
self.de.bump();
visitor.visit(MapVisitor::new(self.de))
} else {
Err(self.de.error(ErrorCode::ExpectedSomeValue))
}
}
}
/// Decodes a json value from an `Iterator<u8>`.
pub fn from_iter<I, T>(iter: I) -> Result<T, Error>
where I: Iterator<Item=u8>,
T: de::Deserialize
{
let mut de = 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 string
pub fn from_str<'a, T>(s: &'a str) -> Result<T, Error>
where T: de::Deserialize
{
from_iter(s.bytes())
}
-160
View File
@@ -1,160 +0,0 @@
use std::error;
use std::fmt;
use std::io;
use de;
/// The errors that can arise while parsing a JSON stream.
#[derive(Copy, 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,
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::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(Clone, PartialEq, 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.description(),
/*
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 error::FromError<io::Error> for Error {
fn from_error(error: io::Error) -> Error {
Error::IoError(error)
}
}
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 missing_field_error(field: &'static str) -> Error {
Error::MissingFieldError(field)
}
}
-19
View File
@@ -1,19 +0,0 @@
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;
-457
View File
@@ -1,457 +0,0 @@
use std::{f32, f64};
use std::io;
use std::num::{Float, FpCategory};
use std::string::FromUtf8Error;
use ser;
/// A structure for implementing serialization to JSON.
pub struct Serializer<W> {
writer: W,
format: Format,
current_indent: usize,
indent: usize,
}
#[derive(Copy, PartialEq)]
enum Format {
Compact,
Pretty,
}
impl<W: io::Write> Serializer<W> {
/// Creates a new JSON visitr whose output will be written to the writer
/// specified.
#[inline]
pub fn new(writer: W) -> Serializer<W> {
Serializer {
writer: writer,
format: Format::Compact,
current_indent: 0,
indent: 0,
}
}
/// Creates a new JSON visitr whose output will be written to the writer
/// specified.
#[inline]
pub fn new_pretty(writer: W) -> Serializer<W> {
Serializer {
writer: writer,
format: Format::Pretty,
current_indent: 0,
indent: 2,
}
}
/// Unwrap the `Writer` from the `Serializer`.
#[inline]
pub fn into_inner(self) -> W {
self.writer
}
}
impl<W: io::Write> ser::Serializer for Serializer<W> {
type Value = ();
type Error = io::Error;
#[inline]
fn visit<T>(&mut self, value: &T) -> io::Result<()>
where T: ser::Serialize,
{
value.visit(&mut Visitor {
writer: &mut self.writer,
format: self.format,
current_indent: self.current_indent,
indent: self.indent,
})
}
}
struct Visitor<'a, W: 'a> {
writer: &'a mut W,
format: Format,
current_indent: usize,
indent: usize,
}
impl<'a, W> Visitor<'a, W> where W: io::Write, {
fn serialize_sep(&mut self, first: bool) -> io::Result<()> {
match self.format {
Format::Compact => {
if first {
Ok(())
} else {
self.writer.write_all(b",")
}
}
Format::Pretty => {
if first {
self.current_indent += self.indent;
try!(self.writer.write_all(b"\n"));
} else {
try!(self.writer.write_all(b",\n"));
}
spaces(&mut self.writer, self.current_indent)
}
}
}
fn serialize_colon(&mut self) -> io::Result<()> {
match self.format {
Format::Compact => self.writer.write_all(b":"),
Format::Pretty => self.writer.write_all(b": "),
}
}
fn serialize_end(&mut self, current_indent: usize, s: &[u8]) -> io::Result<()> {
if self.format == Format::Pretty && current_indent != self.current_indent {
self.current_indent -= self.indent;
try!(self.writer.write(b"\n"));
try!(spaces(&mut self.writer, self.current_indent));
}
self.writer.write_all(s)
}
}
impl<'a, W> ser::Visitor for Visitor<'a, W> where W: io::Write, {
type Value = ();
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!(self.writer, "{}", value)
}
#[inline]
fn visit_i8(&mut self, value: i8) -> io::Result<()> {
write!(self.writer, "{}", value)
}
#[inline]
fn visit_i16(&mut self, value: i16) -> io::Result<()> {
write!(self.writer, "{}", value)
}
#[inline]
fn visit_i32(&mut self, value: i32) -> io::Result<()> {
write!(self.writer, "{}", value)
}
#[inline]
fn visit_i64(&mut self, value: i64) -> io::Result<()> {
write!(self.writer, "{}", value)
}
#[inline]
fn visit_usize(&mut self, value: usize) -> io::Result<()> {
write!(self.writer, "{}", value)
}
#[inline]
fn visit_u8(&mut self, value: u8) -> io::Result<()> {
write!(self.writer, "{}", value)
}
#[inline]
fn visit_u16(&mut self, value: u16) -> io::Result<()> {
write!(self.writer, "{}", value)
}
#[inline]
fn visit_u32(&mut self, value: u32) -> io::Result<()> {
write!(self.writer, "{}", value)
}
#[inline]
fn visit_u64(&mut self, value: u64) -> io::Result<()> {
write!(self.writer, "{}", value)
}
#[inline]
fn visit_f32(&mut self, value: f32) -> io::Result<()> {
fmt_f32_or_null(self.writer, value)
}
#[inline]
fn visit_f64(&mut self, value: f64) -> io::Result<()> {
fmt_f64_or_null(self.writer, value)
}
#[inline]
fn visit_char(&mut self, value: char) -> io::Result<()> {
escape_char(self.writer, value)
}
#[inline]
fn visit_str(&mut self, value: &str) -> io::Result<()> {
escape_str(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.visit(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<()> {
let current_indent = self.current_indent;
try!(self.writer.write_all(b"{"));
try!(self.serialize_sep(true));
try!(self.visit_str(variant));
try!(self.serialize_colon());
try!(self.writer.write_all(b"[]"));
self.serialize_end(current_indent, b"}")
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> io::Result<()>
where V: ser::SeqVisitor,
{
let current_indent = self.current_indent;
try!(self.writer.write_all(b"["));
while let Some(()) = try!(visitor.visit(self)) { }
self.serialize_end(current_indent, b"]")
}
#[inline]
fn visit_enum_seq<V>(&mut self, _name: &str, variant: &str, visitor: V) -> io::Result<()>
where V: ser::SeqVisitor,
{
let current_indent = self.current_indent;
try!(self.writer.write_all(b"{"));
try!(self.serialize_sep(true));
try!(self.visit_str(variant));
try!(self.serialize_colon());
try!(self.visit_seq(visitor));
self.serialize_end(current_indent, b"}")
}
#[inline]
fn visit_seq_elt<T>(&mut self, first: bool, value: T) -> io::Result<()>
where T: ser::Serialize,
{
try!(self.serialize_sep(first));
value.visit(self)
}
#[inline]
fn visit_map<V>(&mut self, mut visitor: V) -> io::Result<()>
where V: ser::MapVisitor,
{
let current_indent = self.current_indent;
try!(self.writer.write_all(b"{"));
while let Some(()) = try!(visitor.visit(self)) { }
self.serialize_end(current_indent, b"}")
}
#[inline]
fn visit_enum_map<V>(&mut self, _name: &str, variant: &str, visitor: V) -> io::Result<()>
where V: ser::MapVisitor,
{
let current_indent = self.current_indent;
try!(self.writer.write_all(b"{"));
try!(self.serialize_sep(true));
try!(self.visit_str(variant));
try!(self.serialize_colon());
try!(self.visit_map(visitor));
self.serialize_end(current_indent, b"}")
}
#[inline]
fn visit_map_elt<K, V>(&mut self, first: bool, key: K, value: V) -> io::Result<()>
where K: ser::Serialize,
V: ser::Serialize,
{
try!(self.serialize_sep(first));
try!(key.visit(self));
try!(self.serialize_colon());
value.visit(self)
}
}
#[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
{
let buf = &mut [0; 4];
value.encode_utf8(buf);
escape_bytes(wr, buf)
}
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"),
_ => wr.write_all(f32::to_str_digits(value, 6).as_bytes()),
}
}
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"),
_ => wr.write_all(f64::to_str_digits(value, 6).as_bytes()),
}
}
/// 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!(ser::Serializer::visit(&mut ser, value));
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::new_pretty(writer);
try!(ser::Serializer::visit(&mut ser, value));
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 spaces<W>(wr: &mut W, mut n: usize) -> io::Result<()>
where W: io::Write,
{
const LEN: usize = 16;
const BUF: &'static [u8; LEN] = &[b' '; 16];
while n >= LEN {
try!(wr.write_all(BUF));
n -= LEN;
}
if n > 0 {
wr.write_all(&BUF[..n])
} else {
Ok(())
}
}
-604
View File
@@ -1,604 +0,0 @@
use std::collections::{BTreeMap, btree_map};
use std::fmt;
use std::io;
use std::str;
use std::vec;
use de;
use ser;
use super::error::Error;
#[derive(Clone, PartialEq)]
pub enum Value {
Null,
Bool(bool),
I64(i64),
F64(f64),
String(String),
Array(Vec<Value>),
Object(BTreeMap<String, Value>),
}
impl ser::Serialize for Value {
#[inline]
fn visit<V>(&self, visitor: &mut V) -> Result<V::Value, V::Error>
where V: ser::Visitor,
{
match *self {
Value::Null => visitor.visit_unit(),
Value::Bool(v) => visitor.visit_bool(v),
Value::I64(v) => visitor.visit_i64(v),
Value::F64(v) => visitor.visit_f64(v),
Value::String(ref v) => visitor.visit_str(&v),
Value::Array(ref v) => v.visit(visitor),
Value::Object(ref v) => v.visit(visitor),
}
}
}
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> {
Ok(Value::I64(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::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::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 Value = ();
type Error = ();
#[inline]
fn visit<T>(&mut self, value: &T) -> Result<(), ()>
where T: ser::Serialize,
{
try!(value.visit(self));
Ok(())
}
}
impl ser::Visitor for Serializer {
type Value = ();
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<(), ()> {
self.state.push(State::Value(Value::I64(value)));
Ok(())
}
#[inline]
fn visit_u64(&mut self, value: u64) -> Result<(), ()> {
self.state.push(State::Value(Value::I64(value as i64)));
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.visit(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 = match visitor.size_hint() {
(_, Some(len)) => len,
(len, None) => len,
};
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, _first: bool, value: T) -> Result<(), ()>
where T: ser::Serialize,
{
try!(value.visit(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, _first: bool, key: K, value: V) -> Result<(), ()>
where K: ser::Serialize,
V: ser::Serialize,
{
try!(key.visit(self));
let key = match self.state.pop().unwrap() {
State::Value(Value::String(value)) => value,
state => panic!("expected key, found {:?}", state),
};
try!(value.visit(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::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, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
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))) => {
let len = fields.len();
try!(visitor.visit_variant(&variant, SeqDeserializer {
de: self,
iter: fields.into_iter(),
len: len,
}))
}
Some((variant, Value::Object(fields))) => {
let len = fields.len();
try!(visitor.visit_variant(&variant, MapDeserializer {
de: self,
iter: fields.into_iter(),
value: None,
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::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::EnumVisitor for SeqDeserializer<'a> {
type Error = Error;
fn visit_unit(&mut self) -> Result<(), Error> {
if self.len == 0 {
Ok(())
} else {
Err(de::Error::syntax_error())
}
}
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::EnumSeqVisitor,
{
visitor.visit(self)
}
}
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 size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl<'a> de::EnumVisitor for MapDeserializer<'a> {
type Error = Error;
fn visit_map<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::EnumMapVisitor,
{
visitor.visit(self)
}
}
/// 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();
ser::Serializer::visit(&mut ser, value).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)
}
-10
View File
@@ -1,10 +0,0 @@
#![feature(core, io, path, std_misc, unicode)]
extern crate unicode;
pub use ser::{Serialize, Serializer};
pub use de::{Deserialize, Deserializer, Error};
pub mod ser;
pub mod de;
pub mod json;
-660
View File
@@ -1,660 +0,0 @@
use std::collections::hash_state::HashState;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::hash::Hash;
use std::path;
use std::rc::Rc;
use std::str;
use std::sync::Arc;
///////////////////////////////////////////////////////////////////////////////
pub trait Serialize {
fn visit<V>(&self, visitor: &mut V) -> Result<V::Value, V::Error>
where V: Visitor;
}
///////////////////////////////////////////////////////////////////////////////
pub trait Serializer {
type Value;
type Error;
fn visit<T>(&mut self, value: &T) -> Result<Self::Value, Self::Error>
where T: Serialize;
}
///////////////////////////////////////////////////////////////////////////////
pub trait Visitor {
type Value;
type Error;
fn visit_bool(&mut self, v: bool) -> Result<Self::Value, Self::Error>;
#[inline]
fn visit_isize(&mut self, v: isize) -> Result<Self::Value, Self::Error> {
self.visit_i64(v as i64)
}
#[inline]
fn visit_i8(&mut self, v: i8) -> Result<Self::Value, Self::Error> {
self.visit_i64(v as i64)
}
#[inline]
fn visit_i16(&mut self, v: i16) -> Result<Self::Value, Self::Error> {
self.visit_i64(v as i64)
}
#[inline]
fn visit_i32(&mut self, v: i32) -> Result<Self::Value, Self::Error> {
self.visit_i64(v as i64)
}
#[inline]
fn visit_i64(&mut self, v: i64) -> Result<Self::Value, Self::Error>;
#[inline]
fn visit_usize(&mut self, v: usize) -> Result<Self::Value, Self::Error> {
self.visit_u64(v as u64)
}
#[inline]
fn visit_u8(&mut self, v: u8) -> Result<Self::Value, Self::Error> {
self.visit_u64(v as u64)
}
#[inline]
fn visit_u16(&mut self, v: u16) -> Result<Self::Value, Self::Error> {
self.visit_u64(v as u64)
}
#[inline]
fn visit_u32(&mut self, v: u32) -> Result<Self::Value, Self::Error> {
self.visit_u64(v as u64)
}
#[inline]
fn visit_u64(&mut self, v: u64) -> Result<Self::Value, Self::Error>;
#[inline]
fn visit_f32(&mut self, v: f32) -> Result<Self::Value, Self::Error> {
self.visit_f64(v as f64)
}
fn visit_f64(&mut self, v: f64) -> Result<Self::Value, Self::Error>;
#[inline]
fn visit_char(&mut self, v: char) -> Result<Self::Value, Self::Error> {
// The unwraps in here should be safe.
let mut s = &mut [0; 4];
let len = v.encode_utf8(s).unwrap();
self.visit_str(str::from_utf8(&s[..len]).unwrap())
}
fn visit_str(&mut self, value: &str) -> Result<Self::Value, Self::Error>;
fn visit_unit(&mut self) -> Result<Self::Value, Self::Error>;
#[inline]
fn visit_named_unit(&mut self, _name: &str) -> Result<Self::Value, Self::Error> {
self.visit_unit()
}
#[inline]
fn visit_enum_unit(&mut self,
_name: &str,
_variant: &str) -> Result<Self::Value, Self::Error> {
self.visit_unit()
}
fn visit_none(&mut self) -> Result<Self::Value, Self::Error>;
fn visit_some<V>(&mut self, value: V) -> Result<Self::Value, Self::Error>
where V: Serialize;
fn visit_seq<V>(&mut self, visitor: V) -> Result<Self::Value, Self::Error>
where V: SeqVisitor;
#[inline]
fn visit_named_seq<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<Self::Value, 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::Value, Self::Error>
where V: SeqVisitor,
{
self.visit_seq(visitor)
}
fn visit_seq_elt<T>(&mut self,
first: bool,
value: T) -> Result<Self::Value, Self::Error>
where T: Serialize;
fn visit_map<V>(&mut self, visitor: V) -> Result<Self::Value, Self::Error>
where V: MapVisitor;
#[inline]
fn visit_named_map<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<Self::Value, 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::Value, Self::Error>
where V: MapVisitor,
{
self.visit_map(visitor)
}
fn visit_map_elt<K, V>(&mut self,
first: bool,
key: K,
value: V) -> Result<Self::Value, Self::Error>
where K: Serialize,
V: Serialize;
}
pub trait SeqVisitor {
fn visit<V>(&mut self, visitor: &mut V) -> Result<Option<V::Value>, V::Error>
where V: Visitor;
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
pub trait MapVisitor {
fn visit<V>(&mut self, visitor: &mut V) -> Result<Option<V::Value>, V::Error>
where V: Visitor;
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! impl_visit {
($ty:ty, $method:ident) => {
impl Serialize for $ty {
#[inline]
fn visit<V>(&self, visitor: &mut V) -> Result<V::Value, V::Error>
where V: Visitor,
{
visitor.$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<'a> Serialize for &'a str {
#[inline]
fn visit<V>(&self, visitor: &mut V) -> Result<V::Value, V::Error>
where V: Visitor,
{
visitor.visit_str(*self)
}
}
impl Serialize for String {
#[inline]
fn visit<V>(&self, visitor: &mut V) -> Result<V::Value, V::Error>
where V: Visitor,
{
(&self[..]).visit(visitor)
}
}
///////////////////////////////////////////////////////////////////////////////
impl<T> Serialize for Option<T> where T: Serialize {
#[inline]
fn visit<V>(&self, visitor: &mut V) -> Result<V::Value, V::Error>
where V: Visitor,
{
match *self {
Some(ref value) => visitor.visit_some(value),
None => visitor.visit_none(),
}
}
}
///////////////////////////////////////////////////////////////////////////////
pub struct SeqIteratorVisitor<Iter> {
iter: Iter,
first: bool,
}
impl<T, Iter> SeqIteratorVisitor<Iter>
where Iter: Iterator<Item=T>
{
#[inline]
pub fn new(iter: Iter) -> SeqIteratorVisitor<Iter> {
SeqIteratorVisitor {
iter: iter,
first: true,
}
}
}
impl<T, Iter> SeqVisitor for SeqIteratorVisitor<Iter>
where T: Serialize,
Iter: Iterator<Item=T>,
{
#[inline]
fn visit<V>(&mut self, visitor: &mut V) -> Result<Option<V::Value>, V::Error>
where V: Visitor,
{
let first = self.first;
self.first = false;
match self.iter.next() {
Some(value) => {
let value = try!(visitor.visit_seq_elt(first, value));
Ok(Some(value))
}
None => Ok(None),
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
///////////////////////////////////////////////////////////////////////////////
impl<'a, T> Serialize for &'a [T]
where T: Serialize,
{
#[inline]
fn visit<V>(&self, visitor: &mut V) -> Result<V::Value, V::Error>
where V: Visitor,
{
visitor.visit_seq(SeqIteratorVisitor::new(self.iter()))
}
}
impl<T> Serialize for Vec<T> where T: Serialize {
#[inline]
fn visit<V>(&self, visitor: &mut V) -> Result<V::Value, V::Error>
where V: Visitor,
{
(&self[..]).visit(visitor)
}
}
impl<T> Serialize for BTreeSet<T> where T: Serialize {
#[inline]
fn visit<V>(&self, visitor: &mut V) -> Result<V::Value, V::Error>
where V: Visitor,
{
visitor.visit_seq(SeqIteratorVisitor::new(self.iter()))
}
}
impl<T, S> Serialize for HashSet<T, S>
where T: Serialize + Eq + Hash,
S: HashState,
{
#[inline]
fn visit<V: Visitor>(&self, visitor: &mut V) -> Result<V::Value, V::Error> {
visitor.visit_seq(SeqIteratorVisitor::new(self.iter()))
}
}
///////////////////////////////////////////////////////////////////////////////
impl Serialize for () {
#[inline]
fn visit<V>(&self, visitor: &mut V) -> Result<V::Value, V::Error>
where V: Visitor,
{
visitor.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,
first: bool,
}
impl<'a, $($T: 'a),+> $TupleVisitor<'a, $($T),+> {
pub fn new(tuple: &'a ($($T,)+)) -> $TupleVisitor<'a, $($T),+> {
$TupleVisitor {
tuple: tuple,
state: 0,
first: true,
}
}
}
impl<'a, $($T),+> SeqVisitor for $TupleVisitor<'a, $($T),+>
where $($T: Serialize),+
{
fn visit<V>(&mut self, visitor: &mut V) -> Result<Option<V::Value>, V::Error>
where V: Visitor,
{
let first = self.first;
self.first = false;
match self.state {
$(
$state => {
self.state += 1;
Ok(Some(try!(visitor.visit_seq_elt(first, &e!(self.tuple.$idx)))))
}
)+
_ => {
Ok(None)
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
($len, Some($len))
}
}
impl<$($T),+> Serialize for ($($T,)+)
where $($T: Serialize),+
{
#[inline]
fn visit<V: Visitor>(&self, visitor: &mut V) -> Result<V::Value, V::Error> {
visitor.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,
first: bool,
}
impl<K, V, Iter> MapIteratorVisitor<Iter>
where Iter: Iterator<Item=(K, V)>
{
#[inline]
pub fn new(iter: Iter) -> MapIteratorVisitor<Iter> {
MapIteratorVisitor {
iter: iter,
first: true,
}
}
}
impl<K, V, I> MapVisitor for MapIteratorVisitor<I>
where K: Serialize,
V: Serialize,
I: Iterator<Item=(K, V)>,
{
#[inline]
fn visit<V_>(&mut self, visitor: &mut V_) -> Result<Option<V_::Value>, V_::Error>
where V_: Visitor,
{
let first = self.first;
self.first = false;
match self.iter.next() {
Some((key, value)) => {
let value = try!(visitor.visit_map_elt(first, key, value));
Ok(Some(value))
}
None => Ok(None)
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
///////////////////////////////////////////////////////////////////////////////
impl<K, V> Serialize for BTreeMap<K, V>
where K: Serialize + Ord,
V: Serialize,
{
#[inline]
fn visit<V_: Visitor>(&self, visitor: &mut V_) -> Result<V_::Value, V_::Error> {
visitor.visit_map(MapIteratorVisitor::new(self.iter()))
}
}
impl<K, V, S> Serialize for HashMap<K, V, S>
where K: Serialize + Eq + Hash,
V: Serialize,
S: HashState,
{
#[inline]
fn visit<V_: Visitor>(&self, visitor: &mut V_) -> Result<V_::Value, V_::Error> {
visitor.visit_map(MapIteratorVisitor::new(self.iter()))
}
}
///////////////////////////////////////////////////////////////////////////////
impl<'a, T> Serialize for &'a T where T: Serialize {
#[inline]
fn visit<V>(&self, visitor: &mut V) -> Result<V::Value, V::Error>
where V: Visitor,
{
(**self).visit(visitor)
}
}
impl<'a, T> Serialize for &'a mut T where T: Serialize {
#[inline]
fn visit<V>(&self, visitor: &mut V) -> Result<V::Value, V::Error>
where V: Visitor,
{
(**self).visit(visitor)
}
}
impl<T> Serialize for Box<T> where T: Serialize {
#[inline]
fn visit<V>(&self, visitor: &mut V) -> Result<V::Value, V::Error>
where V: Visitor,
{
(**self).visit(visitor)
}
}
impl<T> Serialize for Rc<T> where T: Serialize, {
#[inline]
fn visit<V>(&self, visitor: &mut V) -> Result<V::Value, V::Error>
where V: Visitor,
{
(**self).visit(visitor)
}
}
impl<T> Serialize for Arc<T> where T: Serialize, {
#[inline]
fn visit<V>(&self, visitor: &mut V) -> Result<V::Value, V::Error>
where V: Visitor,
{
(**self).visit(visitor)
}
}
///////////////////////////////////////////////////////////////////////////////
impl Serialize for path::Path {
fn visit<V>(&self, visitor: &mut V) -> Result<V::Value, V::Error>
where V: Visitor,
{
self.to_str().unwrap().visit(visitor)
}
}
impl Serialize for path::PathBuf {
fn visit<V>(&self, visitor: &mut V) -> Result<V::Value, V::Error>
where V: Visitor,
{
self.to_str().unwrap().visit(visitor)
}
}
+18
View File
@@ -0,0 +1,18 @@
[package]
name = "serde_test_suite"
version = "0.0.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@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,8 @@
#[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,8 @@
#[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,10 @@
#[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,11 @@
#[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,10 @@
#[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,11 @@
#[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,10 @@
#[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() {}
@@ -0,0 +1,11 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S {
#[serde(rename(serialize="x"))]
#[serde(rename(serialize="y"))] //~^^^ HELP: duplicate serde attribute `rename`
x: (),
}
fn main() {}
@@ -0,0 +1,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S {
#[serde(with = "w", serialize_with = "s")] //~^^ HELP: duplicate serde attribute `serialize_with`
x: (),
}
fn main() {}
@@ -0,0 +1,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(tag = "type")] //~^ HELP: #[serde(tag = "...")] cannot be used with tuple variants
enum E {
Tuple(u8, u8),
}
fn main() {}
@@ -0,0 +1,8 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(tag = "type")] //~^ HELP: #[serde(tag = "...")] can only be used on enums
struct S;
fn main() {}
@@ -0,0 +1,12 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(untagged)]
#[serde(tag = "type")] //~^^ HELP: enum cannot be both untagged and internally tagged
enum E {
A(u8),
B(String),
}
fn main() {}
@@ -0,0 +1,8 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(untagged)] //~^ HELP: #[serde(untagged)] can only be used on enums
struct S;
fn main() {}
@@ -0,0 +1,9 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize, Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test<'a> {
s: &'a str, //~^^ HELP: Serde does not support deserializing fields of type &str
}
fn main() {}
@@ -0,0 +1,11 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(from = "Option<T")] //~^ HELP: failed to parse type: from = "Option<T"
enum TestOne {
Testing,
One,
Two,
Three,
}
@@ -0,0 +1,11 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(into = "Option<T")] //~^ HELP: failed to parse type: into = "Option<T"
enum TestOne {
Testing,
One,
Two,
Three,
}
@@ -0,0 +1,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(abc="xyz")] //~^ HELP: unknown serde container attribute `abc`
struct A {
x: u32,
}
fn main() { }
@@ -0,0 +1,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct C {
#[serde(abc="xyz")] //~^^ HELP: unknown serde field attribute `abc`
x: u32,
}
fn main() { }
@@ -0,0 +1,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
enum E {
#[serde(abc="xyz")] //~^^ HELP: unknown serde variant attribute `abc`
V,
}
fn main() { }
+28
View File
@@ -0,0 +1,28 @@
#![cfg(feature = "unstable")]
extern crate compiletest_rs as compiletest;
use std::env;
fn run_mode(mode: &'static str) {
let mut config = compiletest::default_config();
config.mode = mode.parse().expect("invalid mode");
config.target_rustcflags = Some("-L deps/target/debug/deps".to_owned());
if let Ok(name) = env::var("TESTNAME") {
config.filter = Some(name);
}
config.src_base = format!("tests/{}", mode).into();
compiletest::run_tests(&config);
}
#[test]
fn compile_fail() {
run_mode("compile-fail");
}
#[test]
fn run_pass() {
run_mode("run-pass");
}
+67
View File
@@ -0,0 +1,67 @@
macro_rules! btreeset {
() => {
BTreeSet::new()
};
($($value:expr),+) => {
{
let mut set = BTreeSet::new();
$(set.insert($value);)+
set
}
}
}
macro_rules! btreemap {
() => {
BTreeMap::new()
};
($($key:expr => $value:expr),+) => {
{
let mut map = BTreeMap::new();
$(map.insert($key, $value);)+
map
}
}
}
macro_rules! hashset {
() => {
HashSet::new()
};
($($value:expr),+) => {
{
let mut set = HashSet::new();
$(set.insert($value);)+
set
}
};
($hasher:ident @ $($value:expr),+) => {
{
use std::hash::BuildHasherDefault;
let mut set = HashSet::with_hasher(BuildHasherDefault::<$hasher>::default());
$(set.insert($value);)+
set
}
}
}
macro_rules! hashmap {
() => {
HashMap::new()
};
($($key:expr => $value:expr),+) => {
{
let mut map = HashMap::new();
$(map.insert($key, $value);)+
map
}
};
($hasher:ident @ $($key:expr => $value:expr),+) => {
{
use std::hash::BuildHasherDefault;
let mut map = HashMap::with_hasher(BuildHasherDefault::<$hasher>::default());
$(map.insert($key, $value);)+
map
}
}
}

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