Compare commits

...

296 Commits

Author SHA1 Message Date
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
60 changed files with 7516 additions and 8663 deletions
+2 -1
View File
@@ -1,2 +1,3 @@
target
Cargo.lock
target
*.sw[po]
+36 -27
View File
@@ -1,34 +1,43 @@
language: rust
sudo: false
rust:
- stable
- beta
- nightly
addons:
apt:
packages:
- libcurl4-openssl-dev
- libelf-dev
- libdw-dev
before_script:
- |
pip install 'travis-cargo<0.2' --user &&
export PATH=$HOME/.local/bin:$PATH
script:
- |
(cd serde && travis-cargo build) &&
(cd serde && travis-cargo test) &&
(cd serde && travis-cargo --only nightly test -- --features nightly-testing) &&
(cd serde_tests && travis-cargo test) &&
(cd serde_tests && travis-cargo --only nightly test -- --features nightly-testing) &&
(cd serde_macros && travis-cargo --only nightly test -- --features nightly-testing) &&
(cd serde_macros && travis-cargo --only nightly bench -- --features nightly-testing) &&
(cd serde && travis-cargo --only stable doc) &&
(cd serde_codegen && travis-cargo --only stable doc)
after_success:
- (cd serde && travis-cargo --only stable doc-upload)
- (cd serde_tests && travis-cargo coveralls --no-sudo)
env:
global:
secure: HO41LMpMXkF2In9+1sxWVu7fgolL+y9+4Q5PI6wZX2L5pDwpPJCjxaQarQXCEnoIxED1PlP03JuF7ULNz0zw1ylYhAOfOSdkxFZRnE2wMZqq6qvXBHwyMiDrAociIzoPKSGv7JVrKPsjsnd+96K6xxueIodQZrmAdyq7N/M82Mc=
matrix:
- CRATE=serde_tests TARGET=test
matrix:
include:
- rust: nightly
env: CRATE=serde_macros TARGET=test
- rust: nightly
env: CRATE=serde_macros TARGET=bench
- rust: nightly
env: CRATE=serde_tests TARGET=bench
script:
- (cd $CRATE && cargo $TARGET)
after_success: |
[ $TRAVIS_BRANCH = "master" ] &&
[ $TRAVIS_PULL_REQUEST = false ] &&
mkdir -p target/doc &&
(cd serde && cargo doc --no-deps) &&
(cd serde_codegen && cargo doc --no-deps) &&
(cd serde_macros && cargo doc --no-deps) &&
cp -r serde/target/doc target/doc/serde &&
cp -r serde_codegen/target/doc target/doc/serde_codegen &&
cp -r serde_macros/target/doc target/doc/serde_macros &&
echo "<meta http-equiv=refresh content=0;url=`echo $TRAVIS_REPO_SLUG | cut -d '/' -f 2`/index.html>" > target/doc/index.html &&
sudo pip install ghp-import &&
ghp-import -n target/doc &&
git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
# override the default `--features unstable` used for the nightly branch (optional)
- TRAVIS_CARGO_NIGHTLY_FEATURE=""
# encrypted github token for doc upload (see `GH_TOKEN` link above)
- secure: HO41LMpMXkF2In9+1sxWVu7fgolL+y9+4Q5PI6wZX2L5pDwpPJCjxaQarQXCEnoIxED1PlP03JuF7ULNz0zw1ylYhAOfOSdkxFZRnE2wMZqq6qvXBHwyMiDrAociIzoPKSGv7JVrKPsjsnd+96K6xxueIodQZrmAdyq7N/M82Mc=
+399 -93
View File
@@ -1,7 +1,8 @@
Serde Rust Serialization Framework
==================================
[![Build Status](https://api.travis-ci.org/serde-rs/serde.png?branch=master)](https://travis-ci.org/serde-rs/serde)
[![Build Status](https://api.travis-ci.org/serde-rs/serde.svg?branch=master)](https://travis-ci.org/serde-rs/serde)
[![Coverage Status](https://coveralls.io/repos/serde-rs/serde/badge.svg?branch=master&service=github)](https://coveralls.io/github/serde-rs/serde?branch=master)
[![Latest Version](https://img.shields.io/crates/v/serde.svg)](https://crates.io/crates/serde)
Serde is a powerful framework that enables serialization libraries to
@@ -10,76 +11,246 @@ information. In many situations, the handshake protocol between serializers and
serializees can be completely optimized away, leaving Serde to perform roughly
the same speed as a hand written serializer for a specific type.
Documentation is available at http://serde-rs.github.io/serde/serde
Documentation is available at:
Making a Type Serializable
==========================
* [serde](https://serde-rs.github.io/serde/serde/serde/serde/index.html)
* [serde\_codegen](https://serde-rs.github.io/serde/serde/serde_codegen/serde_codegen/index.html)
The simplest way to make a type serializable is to use the `serde_macros`
syntax extension, which comes with a `#[derive(Serialize, Deserialize)]`
annotation, which automatically generates implementations of
[Serialize](http://serde-rs.github.io/serde/serde/ser/trait.Serialize.html)
and
[Deserialize](http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html)
for the annotated type:
Using Serde with Nightly Rust and serde\_macros
===============================================
Here is a simple example that demonstrates how to use Serde by serializing and
deserializing to JSON. Serde comes with some powerful code generation libraries
that work with Stable and Nightly Rust that eliminate much of the complexity of
hand rolling serialization and deserialization for a given type. First lets see
how we would use Nightly Rust, which is currently a bit simpler than Stable
Rust:
`Cargo.toml`:
```toml
[package]
name = "serde_example_nightly"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
[dependencies]
serde = "*"
serde_json = "*"
serde_macros = "*"
```
`src/main.rs`
```rust
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
extern crate serde_json;
...
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
println!("{}", serialized);
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
println!("{:?}", deserialized);
}
```
Serde bundles a high performance JSON serializer and deserializer,
[serde::json](http://serde-rs.github.io/serde/serde/json/index.html),
which comes with the helper functions
[to_string](http://serde-rs.github.io/serde/serde/json/ser/fn.to_string.html)
and
[from_str](http://serde-rs.github.io/serde/serde/json/de/fn.from_str.html)
that make it easy to go to and from JSON:
When run, it produces:
```rust
use serde::json;
```
% cargo run
{"x":1,"y":2}
Point { x: 1, y: 2 }
```
Using Serde with Stable Rust, syntex, and serde\_codegen
========================================================
Stable Rust is a little more complicated because it does not yet support
compiler plugins. Instead we need to use the code generation library
[syntex](https://github.com/serde-rs/syntex) for this:
```toml
[package]
name = "serde_example"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
build = "build.rs"
[build-dependencies]
serde_codegen = "*"
syntex = "*"
[dependencies]
serde = "*"
serde_json = "*"
```
`src/main.rs`:
```rust,ignore
extern crate serde;
extern crate serde_json;
include!(concat!(env!("OUT_DIR"), "/main.rs"));
```
`src/main.rs.in`:
```rust,ignore
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
println!("{}", serialized);
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
println!("{:?}", deserialized);
}
```
`build.rs`
```rust,ignore
extern crate syntex;
extern crate serde_codegen;
use std::env;
use std::path::Path;
pub fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let src = Path::new("src/main.rs.in");
let dst = Path::new(&out_dir).join("main.rs");
let mut registry = syntex::Registry::new();
serde_codegen::register(&mut registry);
registry.expand("", &src, &dst).unwrap();
}
```
This also produces:
```
% cargo run
{"x":1,"y":2}
Point { x: 1, y: 2 }
```
While this works well with Stable Rust, be aware that the error locations
currently are reported in the generated file instead of in the source file. You
may find it easier to develop with Nightly Rust and `serde\_macros`, then
deploy with Stable Rust and `serde_codegen`. It's possible to combine both
approaches in one setup:
`Cargo.toml`:
```toml
[package]
name = "serde_example"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
build = "build.rs"
[features]
default = ["serde_codegen"]
nightly = ["serde_macros"]
[build-dependencies]
serde_codegen = { version = "*", optional = true }
syntex = "*"
[dependencies]
serde = "*"
serde_json = "*"
serde_macros = { version = "*", optional = true }
```
`build.rs`:
```rust,ignore
#[cfg(not(feature = "serde_macros"))]
mod inner {
extern crate syntex;
extern crate serde_codegen;
use std::env;
use std::path::Path;
pub fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let src = Path::new("src/main.rs.in");
let dst = Path::new(&out_dir).join("main.rs");
let mut registry = syntex::Registry::new();
serde_codegen::register(&mut registry);
registry.expand("", &src, &dst).unwrap();
}
}
#[cfg(feature = "serde_macros")]
mod inner {
pub fn main() {}
}
fn main() {
inner::main();
}
```
`src/main.rs`:
```rust,ignore
#![cfg_attr(feature = "serde_macros", feature(custom_derive, plugin))]
#![cfg_attr(feature = "serde_macros", plugin(serde_macros))]
extern crate serde;
extern crate serde_json;
#[cfg(feature = "serde_macros")]
include!("main.rs.in");
#[cfg(not(feature = "serde_macros"))]
include!(concat!(env!("OUT_DIR"), "/main.rs"));
```
The `src/main.rs.in` is the same as before.
Then to run with stable:
```
% cargo build
...
let point = Point { x: 1, y: 2 };
let serialized_point = json::to_string(&point).unwrap();
println!("{}", serialized_point); // prints: {"x":1,"y":2}
let deserialize_point: Point = json::from_str(&serialized_point).unwrap();
```
[serde::json](http://serde-rs.github.io/serde/serde/json/index.html) also
supports a generic
[Value](http://serde-rs.github.io/serde/serde/json/value/enum.Value.html)
type, which can represent any JSON value. Also, any
[Serialize](http://serde-rs.github.io/serde/serde/ser/trait.Serialize.html)
and
[Deserialize](http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html)
can be converted into a
[Value](http://serde-rs.github.io/serde/serde/json/value/enum.Value.html)
with the methods
[to_value](http://serde-rs.github.io/serde/serde/json/value/fn.to_value.html)
and
[from_value](http://serde-rs.github.io/serde/serde/json/value/fn.from_value.html):
Or with nightly:
```rust
let point = Point { x: 1, y: 2 };
let point_value = json::to_value(&point).unwrap();
println!("{}", point_value.find("x")); // prints: Some(1)
let deserialize_point: Point = json::from_value(point_value).unwrap();
```
% cargo build --features nightly --no-default-features
...
```
Serialization without Macros
@@ -87,9 +258,9 @@ Serialization without Macros
Under the covers, Serde extensively uses the Visitor pattern to thread state
between the
[Serializer](http://serde-rs.github.io/serde/serde/ser/trait.Serializer.html)
[Serializer](http://serde-rs.github.io/serde/serde/serde/ser/trait.Serializer.html)
and
[Serialize](http://serde-rs.github.io/serde/serde/ser/trait.Serialize.html)
[Serialize](http://serde-rs.github.io/serde/serde/serde/ser/trait.Serialize.html)
without the two having specific information about each other's concrete type.
This has many of the same benefits as frameworks that use runtime type
information without the overhead. In fact, when compiling with optimizations,
@@ -98,27 +269,27 @@ nearly as fast as a hand written serializer format for a specific type.
To see it in action, lets look at how a simple type like `i32` is serialized.
The
[Serializer](http://serde-rs.github.io/serde/serde/ser/trait.Serializer.html)
[Serializer](http://serde-rs.github.io/serde/serde/serde/ser/trait.Serializer.html)
is threaded through the type:
```rust
```rust,ignore
impl serde::Serialize for i32 {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: serde::Serializer,
{
serializer.visit_i32(*self)
serializer.serialize_i32(*self)
}
}
```
As you can see it's pretty simple. More complex types like `BTreeMap` need to
pass a
[MapVisitor](http://serde-rs.github.io/serde/serde/ser/trait.MapVisitor.html)
[MapVisitor](http://serde-rs.github.io/serde/serde/serde/ser/trait.MapVisitor.html)
to the
[Serializer](http://serde-rs.github.io/serde/serde/ser/trait.Serializer.html)
[Serializer](http://serde-rs.github.io/serde/serde/serde/ser/trait.Serializer.html)
in order to walk through the type:
```rust
```rust,ignore
impl<K, V> Serialize for BTreeMap<K, V>
where K: Serialize + Ord,
V: Serialize,
@@ -127,7 +298,7 @@ impl<K, V> Serialize for BTreeMap<K, V>
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
@@ -159,7 +330,7 @@ impl<K, V, I> MapVisitor for MapIteratorVisitor<I>
{
match self.iter.next() {
Some((key, value)) => {
let value = try!(serializer.visit_map_elt(key, value));
let value = try!(serializer.serialize_map_elt(key, value));
Ok(Some(value))
}
None => Ok(None)
@@ -178,6 +349,9 @@ as a named map. Its visitor uses a simple state machine to iterate through all
the fields:
```rust
extern crate serde;
extern crate serde_json;
struct Point {
x: i32,
y: i32,
@@ -187,7 +361,7 @@ impl serde::Serialize for Point {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: serde::Serializer
{
serializer.visit_named_map("Point", PointMapVisitor {
serializer.serialize_struct("Point", PointMapVisitor {
value: self,
state: 0,
})
@@ -206,11 +380,11 @@ impl<'a> serde::ser::MapVisitor for PointMapVisitor<'a> {
match self.state {
0 => {
self.state += 1;
Ok(Some(try!(serializer.visit_map_elt("x", &self.value.x))))
Ok(Some(try!(serializer.serialize_struct_elt("x", &self.value.x))))
}
1 => {
self.state += 1;
Ok(Some(try!(serializer.visit_map_elt("y", &self.value.y))))
Ok(Some(try!(serializer.serialize_struct_elt("y", &self.value.y))))
}
_ => {
Ok(None)
@@ -218,6 +392,13 @@ impl<'a> serde::ser::MapVisitor for PointMapVisitor<'a> {
}
}
}
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
println!("{}", serialized);
}
```
Deserialization without Macros
@@ -225,19 +406,19 @@ Deserialization without Macros
Deserialization is a little more complicated since there's a bit more error
handling that needs to occur. Let's start with the simple `i32`
[Deserialize](http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html)
[Deserialize](http://serde-rs.github.io/serde/serde/serde/de/trait.Deserialize.html)
implementation. It passes a
[Visitor](http://serde-rs.github.io/serde/serde/de/trait.Visitor.html) to the
[Deserializer](http://serde-rs.github.io/serde/serde/de/trait.Deserializer.html).
The [Visitor](http://serde-rs.github.io/serde/serde/de/trait.Visitor.html)
[Visitor](http://serde-rs.github.io/serde/serde/serde/de/trait.Visitor.html) to the
[Deserializer](http://serde-rs.github.io/serde/serde/serde/de/trait.Deserializer.html).
The [Visitor](http://serde-rs.github.io/serde/serde/serde/de/trait.Visitor.html)
can create the `i32` from a variety of different types:
```rust
```rust,ignore
impl Deserialize for i32 {
fn deserialize<D>(deserializer: &mut D) -> Result<i32, D::Error>
where D: serde::Deserializer,
{
deserializer.visit(I32Visitor)
deserializer.deserialize(I32Visitor)
}
}
@@ -246,7 +427,7 @@ struct I32Visitor;
impl serde::de::Visitor for I32Visitor {
type Value = i32;
fn visit_i16<E>(&mut self, value: i16) -> Result<i16, E>
fn visit_i16<E>(&mut self, value: i16) -> Result<i32, E>
where E: Error,
{
self.visit_i32(value as i32)
@@ -264,18 +445,18 @@ impl serde::de::Visitor for I32Visitor {
Since it's possible for this type to get passed an unexpected type, we need a
way to error out. This is done by way of the
[Error](http://serde-rs.github.io/serde/serde/de/trait.Error.html) trait,
[Error](http://serde-rs.github.io/serde/serde/serde/de/trait.Error.html) trait,
which allows a
[Deserialize](http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html)
[Deserialize](http://serde-rs.github.io/serde/serde/serde/de/trait.Deserialize.html)
to generate an error for a few common error conditions. Here's how it could be used:
```rust
```rust,ignore
...
fn visit_string<E>(&mut self, _: String) -> Result<i32, E>
where E: Error,
{
Err(serde::de::Error::syntax_error())
Err(serde::de::Error::custom("expect a string"))
}
...
@@ -283,11 +464,11 @@ to generate an error for a few common error conditions. Here's how it could be u
```
Maps follow a similar pattern as before, and use a
[MapVisitor](http://serde-rs.github.io/serde/serde/de/trait.MapVisitor.html)
[MapVisitor](http://serde-rs.github.io/serde/serde/serde/de/trait.MapVisitor.html)
to walk through the values generated by the
[Deserializer](http://serde-rs.github.io/serde/serde/de/trait.Deserializer.html).
[Deserializer](http://serde-rs.github.io/serde/serde/serde/de/trait.Deserializer.html).
```rust
```rust,ignore
impl<K, V> serde::Deserialize for BTreeMap<K, V>
where K: serde::Deserialize + Eq + Ord,
V: serde::Deserialize,
@@ -295,7 +476,7 @@ impl<K, V> serde::Deserialize for BTreeMap<K, V>
fn deserialize<D>(deserializer: &mut D) -> Result<BTreeMap<K, V>, D::Error>
where D: serde::Deserializer,
{
deserializer.visit(BTreeMapVisitor::new())
deserializer.deserialize(BTreeMapVisitor::new())
}
}
@@ -337,7 +518,6 @@ impl<K, V> serde::de::Visitor for BTreeMapVisitor<K, V>
Ok(values)
}
}
```
Deserializing structs goes a step further in order to support not allocating a
@@ -346,6 +526,15 @@ deserializes an enum variant from a string. So for our `Point` example from
before, we need to generate:
```rust
extern crate serde;
extern crate serde_json;
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
enum PointField {
X,
Y,
@@ -355,35 +544,32 @@ impl serde::Deserialize for PointField {
fn deserialize<D>(deserializer: &mut D) -> Result<PointField, D::Error>
where D: serde::de::Deserializer
{
struct FieldVisitor;
struct PointFieldVisitor;
impl serde::de::Visitor for FieldVisitor {
type Value = Field;
impl serde::de::Visitor for PointFieldVisitor {
type Value = PointField;
fn visit_str<E>(&mut self, value: &str) -> Result<PointField, E>
where E: serde::de::Error
{
match value {
"x" => Ok(Field::X),
"y" => Ok(Field::Y),
_ => Err(serde::de::Error::syntax_error()),
"x" => Ok(PointField::X),
"y" => Ok(PointField::Y),
_ => Err(serde::de::Error::custom("expected x or y")),
}
}
}
deserializer.visit(FieldVisitor)
deserializer.deserialize(PointFieldVisitor)
}
}
```
This is then used in our actual deserializer:
```rust
impl serde::Deserialize for Point {
fn deserialize<D>(deserializer: &mut D) -> Result<Point, D::Error>
where D: serde::de::Deserializer
{
deserializer.visit_named_map("Point", PointVisitor)
static FIELDS: &'static [&'static str] = &["x", "y"];
deserializer.deserialize_struct("Point", FIELDS, PointVisitor)
}
}
@@ -400,8 +586,8 @@ impl serde::de::Visitor for PointVisitor {
loop {
match try!(visitor.visit_key()) {
Some(Field::X) => { x = Some(try!(visitor.visit_value())); }
Some(Field::Y) => { y = Some(try!(visitor.visit_value())); }
Some(PointField::X) => { x = Some(try!(visitor.visit_value())); }
Some(PointField::Y) => { y = Some(try!(visitor.visit_value())); }
None => { break; }
}
}
@@ -421,4 +607,124 @@ impl serde::de::Visitor for PointVisitor {
Ok(Point{ x: x, y: y })
}
}
fn main() {
let serialized = "{\"x\":1,\"y\":2}";
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
println!("{:?}", deserialized);
}
```
Design Considerations and tradeoffs for Serializers and Deserializers
=====================================================================
Serde serialization and deserialization implementations are written in such a
way that they err on being able to represent more values, and also provide
better error messages when they are passed an incorrect type to deserialize
from. For example, by default, it is a syntax error to deserialize a `String`
into an `Option<String>`. This is implemented such that it is possible to
distinguish between the values `None` and `Some(())`, if the serialization
format supports option types.
However, many formats do not have option types, and represents optional values
as either a `null`, or some other value. Serde `Serializer`s and
`Deserializer`s can opt-in support for this. For serialization, this is pretty
easy. Simply implement these methods:
```rust,ignore
...
fn visit_none(&mut self) -> Result<(), Self::Error> {
self.visit_unit()
}
fn visit_some<T>(&mut self, value: T) -> Result<(), Self::Error> {
value.serialize(self)
}
...
```
For deserialization, this can be implemented by way of the
`Deserializer::visit_option` hook, which presumes that there is some ability to peek at what is the
next value in the serialized token stream. This following example is from
[serde_tests::TokenDeserializer](https://github.com/serde-rs/serde/blob/master/serde_tests/tests/token.rs#L435-L454),
where it checks to see if the next value is an `Option`, a `()`, or some other
value:
```rust,ignore
...
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.tokens.peek() {
Some(&Token::Option(false)) => {
self.tokens.next();
visitor.visit_none()
}
Some(&Token::Option(true)) => {
self.tokens.next();
visitor.visit_some(self)
}
Some(&Token::Unit) => {
self.tokens.next();
visitor.visit_none()
}
Some(_) => visitor.visit_some(self),
None => Err(Error::EndOfStreamError),
}
}
...
```
Annotations
===========
`serde_codegen` and `serde_macros` support annotations that help to customize
how types are serialized. Here are the supported annotations:
Container Annotations:
| Annotation | Function |
| ---------- | -------- |
| `#[serde(rename="name")` | Serialize and deserialize this container with the given name |
| `#[serde(rename(serialize="name1"))` | Serialize this container with the given name |
| `#[serde(rename(deserialize="name1"))` | Deserialize this container with the given name |
| `#[serde(deny_unknown_fields)` | Always error during serialization when encountering unknown fields. When absent, unknown fields are ignored for self-describing formats like JSON. |
Variant Annotations:
| Annotation | Function |
| ---------- | -------- |
| `#[serde(rename="name")` | Serialize and deserialize this variant with the given name |
| `#[serde(rename(serialize="name1"))` | Serialize this variant with the given name |
| `#[serde(rename(deserialize="name1"))` | Deserialize this variant with the given name |
Field Annotations:
| Annotation | Function |
| ---------- | -------- |
| `#[serde(rename="name")` | Serialize and deserialize this field with the given name |
| `#[serde(rename(serialize="name1"))` | Serialize this field with the given name |
| `#[serde(rename(deserialize="name1"))` | Deserialize this field with the given name |
| `#[serde(default)` | If the value is not specified, use the `Default::default()` |
| `#[serde(default="$path")` | Call the path to a function `fn() -> T` to build the value |
| `#[serde(skip_serializing)` | Do not serialize this value |
| `#[serde(skip_serializing_if="$path")` | Do not serialize this value if this function `fn(&T) -> bool` returns `false` |
| `#[serde(serialize_with="$path")` | Call a function `fn<T, S>(&T, &mut S) -> Result<(), S::Error> where S: Serializer` to serialize this value |
| `#[serde(deserialize_with="$path")` | Call a function `fn<T, D>(&mut D) -> Result<T, D::Error> where D: Deserializer` to deserialize this value |
Serialization Formats Using Serde
=================================
| Format | Name |
| ------ | ---- |
| Bincode | [bincode](https://crates.io/crates/bincode) |
| JSON | [serde\_json](https://crates.io/crates/serde_json) |
| MessagePack | [rmp](https://crates.io/crates/rmp) |
| XML | [serde\_xml](https://github.com/serde-rs/xml) |
| YAML | [serde\_yaml](https://github.com/dtolnay/serde-yaml) |
+2
View File
@@ -0,0 +1,2 @@
target
Cargo.lock
+18
View File
@@ -0,0 +1,18 @@
[package]
name = "serde-syntex-example"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
build = "build.rs"
[features]
default = ["serde_codegen"]
nightly = ["serde_macros"]
[build-dependencies]
serde_codegen = { version = "^0.6.4", optional = true }
syntex = "^0.22.0"
[dependencies]
serde = "^0.6.1"
serde_json = "^0.6.0"
serde_macros = { version = "^0.6.1", optional = true }
+20
View File
@@ -0,0 +1,20 @@
This example demonstrates how to use Serde with Syntex. On stable or nightly
with Syntex, it can be built with:
```
% multirust run stable cargo run
Running `target/debug/serde-syntex-example`
{"x":1,"y":2}
Point { x: 1, y: 2 }
% multirust run nightly cargo run
Running `target/debug/serde-syntex-example`
{"x":1,"y":2}
Point { x: 1, y: 2 }
```
On nightly, it can use a plugin with:
```
% multirust run nightly cargo run --features nightly --no-default-features
```
+29
View File
@@ -0,0 +1,29 @@
#[cfg(not(feature = "serde_macros"))]
mod inner {
extern crate syntex;
extern crate serde_codegen;
use std::env;
use std::path::Path;
pub fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let src = Path::new("src/main.rs.in");
let dst = Path::new(&out_dir).join("main.rs");
let mut registry = syntex::Registry::new();
serde_codegen::register(&mut registry);
registry.expand("", &src, &dst).unwrap();
}
}
#[cfg(feature = "serde_macros")]
mod inner {
pub fn main() {}
}
fn main() {
inner::main();
}
+11
View File
@@ -0,0 +1,11 @@
#![cfg_attr(nightly, feature(custom_derive, plugin))]
#![cfg_attr(nightly, plugin(serde_macros))]
extern crate serde;
extern crate serde_json;
#[cfg(feature = "serde_macros")]
include!("main.rs.in");
#[cfg(not(feature = "serde_macros"))]
include!(concat!(env!("OUT_DIR"), "/main.rs"));
@@ -0,0 +1,16 @@
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
println!("{}", serialized);
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
println!("{:?}", deserialized);
}
+6 -6
View File
@@ -1,17 +1,17 @@
[package]
name = "serde"
version = "0.4.3"
version = "0.7.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
repository = "https://github.com/serde-rs/serde"
documentation = "http://serde-rs.github.io/serde/serde"
documentation = "https://serde-rs.github.io/serde/serde/serde/index.html"
readme = "../README.md"
keywords = ["serialization"]
[dependencies]
num = "*"
keywords = ["serde", "serialization"]
[features]
nightly = []
nightly-testing = ["clippy", "nightly"]
[dependencies]
clippy = { version = "^0.*", optional = true }
-94
View File
@@ -1,94 +0,0 @@
use std::cmp;
use std::io;
use std::slice;
trait IntoBufRead {
type IntoBuf: io::BufRead + BufReadExt;
fn into_buf_read(self) -> Self::IntoBuf;
}
trait BufReadExt {
fn get_buf(&self) -> &[u8];
fn read_u8(&mut self) -> io::Result<Option<u8>>;
}
struct SliceReader<'a> {
buf: &'a [u8],
}
impl<'a> io::Read for SliceReader<'a> {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let amt = cmp::min(buf.len(), self.buf.len());
let (a, b) = self.buf.split_at(amt);
slice::bytes::copy_memory(buf, a);
*self.buf = b;
Ok(amt)
}
}
impl<'a> io::BufRead for SliceReader<'a> {
fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(*self) }
fn consume(&mut self, amt: usize) { *self.buf = &self.buf[amt..]; }
}
impl<'a> BufReadExt for SliceReader<'a> {
fn get_buf(&self) -> &[u8] { self.buf }
fn read_u8(&mut self) -> io::Result<Option<u8>> {
let byte = self.buf.get(0);
*self.buf = &self.buf[1..];
byte
}
}
struct BufReader<R> {
inner: R,
buf: io::Cursor<Vec<u8>>,
}
impl<R> BufReader<R> where R: io::Read {
fn new(inner: R) -> Self {
BufferedReader::with_capacity(io::DEFAULT_BUF_SIZE, inner)
}
fn new(cap: usize, inner: R) -> Self {
BufferedReader {
inner: inner,
buf: io::Cursor::new(Vec::with_capacity(cap)),
}
}
fn into_inner(self) -> R {
self.inner
}
}
impl<R> Read for BufReader<R> where R: io::Read {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
// If we don't have any buffered data and we're doing a massive read
// (larger than our internal buffer), bypass our internal buffer
// entirely.
if self.buf.get_ref().len() == self.buf.position() as usize &&
buf.len() >= self.buf.get_ref().capacity() {
return self.inner.read(buf);
}
try!(self.fill_buf());
self.buf.read(buf)
}
}
impl<R> BufReadExt for BufReader<R> {
fn get_buf(&self) -> &[u8] {
self.buf.get_ref()
}
fn read_u8(&mut self) -> io::Result<Option<u8>> {
if self.buf.get_ref().len() == self.buf.position() as usize {
}
let byte = self.buf.get(0);
*self.buf = &self.buf[1..];
byte
}
}
+7 -4
View File
@@ -54,25 +54,27 @@ impl<'a> ser::Serialize for Bytes<'a> {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: ser::Serializer
{
serializer.visit_bytes(self.bytes)
serializer.serialize_bytes(self.bytes)
}
}
///////////////////////////////////////////////////////////////////////////////
/// `ByteBuf` wraps a `Vec<u8>` in order to hook into serialize and from deserialize a byte array.
/// `ByteBuf` wraps a `Vec<u8>` and serializes as a byte array.
#[derive(Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct ByteBuf {
bytes: Vec<u8>,
}
impl ByteBuf {
/// Construct a new, empty `ByteBuf`.
pub fn new() -> Self {
ByteBuf {
bytes: Vec::new(),
}
}
/// Construct a new, empty `ByteBuf` with the specified capacity.
pub fn with_capacity(cap: usize) -> Self {
ByteBuf {
bytes: Vec::with_capacity(cap)
@@ -138,10 +140,11 @@ impl ser::Serialize for ByteBuf {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: ser::Serializer
{
serializer.visit_bytes(&self)
serializer.serialize_bytes(&self)
}
}
/// This type implements the `serde::de::Visitor` trait for a `ByteBuf`.
pub struct ByteBufVisitor;
impl de::Visitor for ByteBufVisitor {
@@ -196,7 +199,7 @@ impl de::Deserialize for ByteBuf {
fn deserialize<D>(deserializer: &mut D) -> Result<ByteBuf, D::Error>
where D: de::Deserializer
{
deserializer.visit_bytes(ByteBufVisitor)
deserializer.deserialize_bytes(ByteBufVisitor)
}
}
+406
View File
@@ -0,0 +1,406 @@
// 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.
use std::{usize, u8, u16, u32, u64};
use std::{isize, i8, i16, i32, i64};
use std::{f32, f64};
use std::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 = ::std::$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 }
+356 -216
View File
@@ -1,3 +1,5 @@
//! This module contains `Deserialize` and `Visitor` implementations.
use std::borrow::Cow;
use std::collections::{
BinaryHeap,
@@ -10,17 +12,14 @@ use std::collections::{
};
#[cfg(feature = "nightly")]
use collections::enum_set::{CLike, EnumSet};
#[cfg(feature = "nightly")]
use collections::vec_map::VecMap;
use std::hash::Hash;
use std::marker::PhantomData;
use std::net;
use std::path;
use std::rc::Rc;
use std::str;
use std::sync::Arc;
use num::FromPrimitive;
#[cfg(feature = "nightly")]
use core::nonzero::{NonZero, Zeroable};
@@ -34,12 +33,15 @@ use de::{
Error,
MapVisitor,
SeqVisitor,
Type,
VariantVisitor,
Visitor,
};
use de::from_primitive::FromPrimitive;
///////////////////////////////////////////////////////////////////////////////
/// A visitor that produces a `()`.
pub struct UnitVisitor;
impl Visitor for UnitVisitor {
@@ -62,12 +64,13 @@ impl Deserialize for () {
fn deserialize<D>(deserializer: &mut D) -> Result<(), D::Error>
where D: Deserializer,
{
deserializer.visit_unit(UnitVisitor)
deserializer.deserialize_unit(UnitVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
/// A visitor that produces a `bool`.
pub struct BoolVisitor;
impl Visitor for BoolVisitor {
@@ -85,7 +88,7 @@ impl Visitor for BoolVisitor {
match s.trim() {
"true" => Ok(true),
"false" => Ok(false),
_ => Err(Error::syntax_error()),
_ => Err(Error::invalid_type(Type::Bool)),
}
}
}
@@ -94,62 +97,66 @@ impl Deserialize for bool {
fn deserialize<D>(deserializer: &mut D) -> Result<bool, D::Error>
where D: Deserializer,
{
deserializer.visit_bool(BoolVisitor)
deserializer.deserialize_bool(BoolVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! impl_deserialize_num_method {
($src_ty:ty, $method:ident, $from_method:ident) => {
($src_ty:ty, $method:ident, $from_method:ident, $ty:expr) => {
#[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()),
None => Err(Error::invalid_type($ty)),
}
}
}
}
pub struct PrimitiveVisitor<T> {
/// A visitor that produces a primitive type.
struct PrimitiveVisitor<T> {
marker: PhantomData<T>,
}
impl<T> PrimitiveVisitor<T> {
/// Construct a new `PrimitiveVisitor`.
#[inline]
pub fn new() -> Self {
fn new() -> Self {
PrimitiveVisitor {
marker: PhantomData,
}
}
}
impl<
T: Deserialize + FromPrimitive + str::FromStr
> Visitor for PrimitiveVisitor<T> {
impl<T> Visitor for PrimitiveVisitor<T>
where T: Deserialize + FromPrimitive + str::FromStr
{
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);
impl_deserialize_num_method!(isize, visit_isize, from_isize, Type::Isize);
impl_deserialize_num_method!(i8, visit_i8, from_i8, Type::I8);
impl_deserialize_num_method!(i16, visit_i16, from_i16, Type::I16);
impl_deserialize_num_method!(i32, visit_i32, from_i32, Type::I32);
impl_deserialize_num_method!(i64, visit_i64, from_i64, Type::I64);
impl_deserialize_num_method!(usize, visit_usize, from_usize, Type::Usize);
impl_deserialize_num_method!(u8, visit_u8, from_u8, Type::U8);
impl_deserialize_num_method!(u16, visit_u16, from_u16, Type::U16);
impl_deserialize_num_method!(u32, visit_u32, from_u32, Type::U32);
impl_deserialize_num_method!(u64, visit_u64, from_u64, Type::U64);
impl_deserialize_num_method!(f32, visit_f32, from_f32, Type::F32);
impl_deserialize_num_method!(f64, visit_f64, from_f64, Type::F64);
#[inline]
fn visit_str<E>(&mut self, v: &str) -> Result<T, E>
where E: Error,
{
str::FromStr::from_str(v.trim()).or(Err(Error::syntax_error()))
str::FromStr::from_str(v.trim()).or_else(|_| {
Err(Error::invalid_type(Type::Str))
})
}
}
@@ -166,18 +173,18 @@ macro_rules! impl_deserialize_num {
}
}
impl_deserialize_num!(isize, visit_isize);
impl_deserialize_num!(i8, visit_i8);
impl_deserialize_num!(i16, visit_i16);
impl_deserialize_num!(i32, visit_i32);
impl_deserialize_num!(i64, visit_i64);
impl_deserialize_num!(usize, visit_usize);
impl_deserialize_num!(u8, visit_u8);
impl_deserialize_num!(u16, visit_u16);
impl_deserialize_num!(u32, visit_u32);
impl_deserialize_num!(u64, visit_u64);
impl_deserialize_num!(f32, visit_f32);
impl_deserialize_num!(f64, visit_f64);
impl_deserialize_num!(isize, deserialize_isize);
impl_deserialize_num!(i8, deserialize_i8);
impl_deserialize_num!(i16, deserialize_i16);
impl_deserialize_num!(i32, deserialize_i32);
impl_deserialize_num!(i64, deserialize_i64);
impl_deserialize_num!(usize, deserialize_usize);
impl_deserialize_num!(u8, deserialize_u8);
impl_deserialize_num!(u16, deserialize_u16);
impl_deserialize_num!(u32, deserialize_u32);
impl_deserialize_num!(u64, deserialize_u64);
impl_deserialize_num!(f32, deserialize_f32);
impl_deserialize_num!(f64, deserialize_f64);
///////////////////////////////////////////////////////////////////////////////
@@ -200,12 +207,12 @@ impl Visitor for CharVisitor {
let mut iter = v.chars();
if let Some(v) = iter.next() {
if iter.next().is_some() {
Err(Error::syntax_error())
Err(Error::invalid_type(Type::Char))
} else {
Ok(v)
}
} else {
Err(Error::end_of_stream_error())
Err(Error::end_of_stream())
}
}
}
@@ -215,7 +222,7 @@ impl Deserialize for char {
fn deserialize<D>(deserializer: &mut D) -> Result<char, D::Error>
where D: Deserializer,
{
deserializer.visit_char(CharVisitor)
deserializer.deserialize_char(CharVisitor)
}
}
@@ -229,7 +236,7 @@ impl Visitor for StringVisitor {
fn visit_str<E>(&mut self, v: &str) -> Result<String, E>
where E: Error,
{
Ok(v.to_string())
Ok(v.to_owned())
}
fn visit_string<E>(&mut self, v: String) -> Result<String, E>
@@ -242,17 +249,17 @@ impl Visitor for StringVisitor {
where E: Error,
{
match str::from_utf8(v) {
Ok(s) => Ok(s.to_string()),
Err(_) => Err(Error::syntax_error()),
Ok(s) => Ok(s.to_owned()),
Err(_) => Err(Error::invalid_type(Type::String)),
}
}
fn visit_byte_buf<'a, E>(&mut self, v: Vec<u8>) -> Result<String, E>
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<String, E>
where E: Error,
{
match String::from_utf8(v) {
Ok(s) => Ok(s),
Err(_) => Err(Error::syntax_error()),
Err(_) => Err(Error::invalid_type(Type::String)),
}
}
}
@@ -261,7 +268,7 @@ impl Deserialize for String {
fn deserialize<D>(deserializer: &mut D) -> Result<String, D::Error>
where D: Deserializer,
{
deserializer.visit_string(StringVisitor)
deserializer.deserialize_string(StringVisitor)
}
}
@@ -276,6 +283,13 @@ impl<
> Visitor for OptionVisitor<T> {
type Value = Option<T>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<Option<T>, E>
where E: Error,
{
Ok(None)
}
#[inline]
fn visit_none<E>(&mut self) -> Result<Option<T>, E>
where E: Error,
@@ -295,13 +309,40 @@ 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 })
deserializer.deserialize_option(OptionVisitor { marker: PhantomData })
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! set_impl {
/// A visitor that produces a `PhantomData`.
pub struct PhantomDataVisitor<T> {
marker: PhantomData<T>,
}
impl<T> Visitor for PhantomDataVisitor<T> where T: Deserialize {
type Value = PhantomData<T>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<PhantomData<T>, E>
where E: Error,
{
Ok(PhantomData)
}
}
impl<T> Deserialize for PhantomData<T> where T: Deserialize {
fn deserialize<D>(deserializer: &mut D) -> Result<PhantomData<T>, D::Error>
where D: Deserializer,
{
let visitor = PhantomDataVisitor { marker: PhantomData };
deserializer.deserialize_unit_struct("PhantomData", visitor)
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! seq_impl {
(
$ty:ty,
< $($constraints:ident),* >,
@@ -311,11 +352,13 @@ macro_rules! set_impl {
$with_capacity:expr,
$insert:expr
) => {
/// A visitor that produces a sequence.
pub struct $visitor_name<T> {
marker: PhantomData<T>,
}
impl<T> $visitor_name<T> {
/// Construct a new sequence visitor.
pub fn new() -> Self {
$visitor_name {
marker: PhantomData,
@@ -357,13 +400,13 @@ macro_rules! set_impl {
fn deserialize<D>(deserializer: &mut D) -> Result<$ty, D::Error>
where D: Deserializer,
{
deserializer.visit_seq($visitor_name::new())
deserializer.deserialize_seq($visitor_name::new())
}
}
}
}
set_impl!(
seq_impl!(
BinaryHeap<T>,
<Deserialize, Ord>,
BinaryHeapVisitor,
@@ -372,7 +415,7 @@ set_impl!(
BinaryHeap::with_capacity(visitor.size_hint().0),
BinaryHeap::push);
set_impl!(
seq_impl!(
BTreeSet<T>,
<Deserialize, Eq, Ord>,
BTreeSetVisitor,
@@ -382,7 +425,7 @@ set_impl!(
BTreeSet::insert);
#[cfg(feature = "nightly")]
set_impl!(
seq_impl!(
EnumSet<T>,
<Deserialize, CLike>,
EnumSetVisitor,
@@ -391,7 +434,7 @@ set_impl!(
EnumSet::new(),
EnumSet::insert);
set_impl!(
seq_impl!(
LinkedList<T>,
<Deserialize>,
LinkedListVisitor,
@@ -400,7 +443,7 @@ set_impl!(
LinkedList::new(),
LinkedList::push_back);
set_impl!(
seq_impl!(
HashSet<T>,
<Deserialize, Eq, Hash>,
HashSetVisitor,
@@ -409,7 +452,7 @@ set_impl!(
HashSet::with_capacity(visitor.size_hint().0),
HashSet::insert);
set_impl!(
seq_impl!(
Vec<T>,
<Deserialize>,
VecVisitor,
@@ -418,7 +461,7 @@ set_impl!(
Vec::with_capacity(visitor.size_hint().0),
Vec::push);
set_impl!(
seq_impl!(
VecDeque<T>,
<Deserialize>,
VecDequeVisitor,
@@ -434,6 +477,7 @@ struct ArrayVisitor0<T> {
}
impl<T> ArrayVisitor0<T> {
/// Construct a `ArrayVisitor0<T>`.
pub fn new() -> Self {
ArrayVisitor0 {
marker: PhantomData,
@@ -466,7 +510,7 @@ impl<T> Deserialize for [T; 0]
fn deserialize<D>(deserializer: &mut D) -> Result<[T; 0], D::Error>
where D: Deserializer,
{
deserializer.visit_seq(ArrayVisitor0::new())
deserializer.deserialize_seq(ArrayVisitor0::new())
}
}
@@ -478,6 +522,7 @@ macro_rules! array_impls {
}
impl<T> $visitor<T> {
/// Construct a `ArrayVisitor*<T>`.
pub fn new() -> Self {
$visitor {
marker: PhantomData
@@ -495,7 +540,7 @@ macro_rules! array_impls {
$(
let $name = match try!(visitor.visit()) {
Some(val) => val,
None => { return Err(Error::end_of_stream_error()); }
None => { return Err(Error::end_of_stream()); }
};
)+;
@@ -511,7 +556,7 @@ macro_rules! array_impls {
fn deserialize<D>(deserializer: &mut D) -> Result<[T; $len], D::Error>
where D: Deserializer,
{
deserializer.visit_seq($visitor::new())
deserializer.deserialize_fixed_size_array($len, $visitor::new())
}
}
)+
@@ -565,12 +610,23 @@ array_impls! {
macro_rules! tuple_impls {
() => {};
($($visitor:ident => ($($name:ident),+),)+) => {
($($len:expr => $visitor:ident => ($($name:ident),+),)+) => {
$(
struct $visitor<$($name,)+> {
/// Construct a tuple visitor.
pub struct $visitor<$($name,)+> {
marker: PhantomData<($($name,)+)>,
}
impl<
$($name: Deserialize,)+
> $visitor<$($name,)+> {
/// Construct a `TupleVisitor*<T>`.
pub fn new() -> Self {
$visitor { marker: PhantomData }
}
}
impl<
$($name: Deserialize,)+
> Visitor for $visitor<$($name,)+> {
@@ -584,7 +640,7 @@ macro_rules! tuple_impls {
$(
let $name = match try!(visitor.visit()) {
Some(value) => value,
None => { return Err(Error::end_of_stream_error()); }
None => { return Err(Error::end_of_stream()); }
};
)+;
@@ -601,7 +657,7 @@ macro_rules! tuple_impls {
fn deserialize<D>(deserializer: &mut D) -> Result<($($name,)+), D::Error>
where D: Deserializer,
{
deserializer.visit_tuple($visitor { marker: PhantomData })
deserializer.deserialize_tuple($len, $visitor::new())
}
}
)+
@@ -609,18 +665,18 @@ macro_rules! tuple_impls {
}
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),
1 => TupleVisitor1 => (T0),
2 => TupleVisitor2 => (T0, T1),
3 => TupleVisitor3 => (T0, T1, T2),
4 => TupleVisitor4 => (T0, T1, T2, T3),
5 => TupleVisitor5 => (T0, T1, T2, T3, T4),
6 => TupleVisitor6 => (T0, T1, T2, T3, T4, T5),
7 => TupleVisitor7 => (T0, T1, T2, T3, T4, T5, T6),
8 => TupleVisitor8 => (T0, T1, T2, T3, T4, T5, T6, T7),
9 => TupleVisitor9 => (T0, T1, T2, T3, T4, T5, T6, T7, T8),
10 => TupleVisitor10 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9),
11 => TupleVisitor11 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10),
12 => TupleVisitor12 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11),
}
///////////////////////////////////////////////////////////////////////////////
@@ -635,11 +691,13 @@ macro_rules! map_impl {
$with_capacity:expr,
$insert:expr
) => {
/// A visitor that produces a map.
pub struct $visitor_name<K, V> {
marker: PhantomData<$ty>,
}
impl<K, V> $visitor_name<K, V> {
/// Construct a `MapVisitor*<T>`.
pub fn new() -> Self {
$visitor_name {
marker: PhantomData,
@@ -683,7 +741,7 @@ macro_rules! map_impl {
fn deserialize<D>(deserializer: &mut D) -> Result<$ty, D::Error>
where D: Deserializer,
{
deserializer.visit_map($visitor_name::new())
deserializer.deserialize_map($visitor_name::new())
}
}
}
@@ -710,58 +768,77 @@ map_impl!(
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "nightly")]
pub struct VecMapVisitor<V> {
marker: PhantomData<VecMap<V>>,
}
#[cfg(feature = "nightly")]
impl<V> VecMapVisitor<V> {
#[inline]
pub fn new() -> Self {
VecMapVisitor {
marker: PhantomData,
}
}
}
#[cfg(feature = "nightly")]
impl<V> Visitor for VecMapVisitor<V>
where V: Deserialize,
{
type Value = VecMap<V>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<VecMap<V>, E>
where E: Error,
{
Ok(VecMap::new())
}
#[inline]
fn visit_map<V_>(&mut self, mut visitor: V_) -> Result<VecMap<V>, V_::Error>
where V_: MapVisitor,
{
let (len, _) = visitor.size_hint();
let mut values = VecMap::with_capacity(len);
while let Some((key, value)) = try!(visitor.visit()) {
values.insert(key, value);
}
try!(visitor.end());
Ok(values)
}
}
#[cfg(feature = "nightly")]
impl<V> Deserialize for VecMap<V>
where V: Deserialize,
{
fn deserialize<D>(deserializer: &mut D) -> Result<VecMap<V>, D::Error>
impl Deserialize for net::IpAddr {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer,
{
deserializer.visit_map(VecMapVisitor::new())
let s = try!(String::deserialize(deserializer));
match s.parse() {
Ok(s) => Ok(s),
Err(err) => Err(D::Error::invalid_value(&err.to_string())),
}
}
}
impl Deserialize for net::Ipv4Addr {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer,
{
let s = try!(String::deserialize(deserializer));
match s.parse() {
Ok(s) => Ok(s),
Err(err) => Err(D::Error::invalid_value(&err.to_string())),
}
}
}
impl Deserialize for net::Ipv6Addr {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer,
{
let s = try!(String::deserialize(deserializer));
match s.parse() {
Ok(s) => Ok(s),
Err(err) => Err(D::Error::invalid_value(&err.to_string())),
}
}
}
///////////////////////////////////////////////////////////////////////////////
impl Deserialize for net::SocketAddr {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer,
{
let s = try!(String::deserialize(deserializer));
match s.parse() {
Ok(s) => Ok(s),
Err(err) => Err(D::Error::invalid_value(&err.to_string())),
}
}
}
impl Deserialize for net::SocketAddrV4 {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer,
{
let s = try!(String::deserialize(deserializer));
match s.parse() {
Ok(s) => Ok(s),
Err(err) => Err(D::Error::invalid_value(&err.to_string())),
}
}
}
impl Deserialize for net::SocketAddrV6 {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer,
{
let s = try!(String::deserialize(deserializer));
match s.parse() {
Ok(s) => Ok(s),
Err(err) => Err(D::Error::invalid_value(&err.to_string())),
}
}
}
@@ -789,7 +866,7 @@ impl Deserialize for path::PathBuf {
fn deserialize<D>(deserializer: &mut D) -> Result<path::PathBuf, D::Error>
where D: Deserializer,
{
deserializer.visit(PathBufVisitor)
deserializer.deserialize_string(PathBufVisitor)
}
}
@@ -839,7 +916,7 @@ impl<T> Deserialize for NonZero<T> where T: Deserialize + PartialEq + Zeroable +
fn deserialize<D>(deserializer: &mut D) -> Result<NonZero<T>, D::Error> where D: Deserializer {
let value = try!(Deserialize::deserialize(deserializer));
if value == Zero::zero() {
return Err(Error::syntax_error())
return Err(Error::invalid_value("expected a non-zero value"))
}
unsafe {
Ok(NonZero::new(value))
@@ -849,126 +926,189 @@ impl<T> Deserialize for NonZero<T> where T: Deserialize + PartialEq + Zeroable +
///////////////////////////////////////////////////////////////////////////////
impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
fn deserialize<D>(deserializer: &mut D) -> Result<Result<T, E>, D::Error>
where D: Deserializer {
enum Field {
Field0,
Field1,
Ok,
Err,
}
impl Deserialize for Field {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<Field, D::Error>
where D: Deserializer {
struct FieldVisitor<D> {
phantom: PhantomData<D>,
}
where D: Deserializer
{
struct FieldVisitor;
impl<D> ::de::Visitor for FieldVisitor<D> where D: Deserializer {
impl ::de::Visitor for FieldVisitor {
type Value = Field;
fn visit_usize<E>(&mut self, value: usize) -> Result<Field, E> where E: Error {
match value {
0 => Ok(Field::Ok),
1 => Ok(Field::Err),
_ => Err(Error::unknown_field(&value.to_string())),
}
}
fn visit_str<E>(&mut self, value: &str) -> Result<Field, E> where E: Error {
match value {
"Ok" => Ok(Field::Field0),
"Err" => Ok(Field::Field1),
_ => Err(Error::unknown_field_error(value)),
"Ok" => Ok(Field::Ok),
"Err" => Ok(Field::Err),
_ => Err(Error::unknown_field(value)),
}
}
fn visit_bytes<E>(&mut self, value: &[u8]) -> Result<Field, E> where E: Error {
match str::from_utf8(value) {
Ok(s) => self.visit_str(s),
_ => Err(Error::syntax_error()),
match value {
b"Ok" => Ok(Field::Ok),
b"Err" => Ok(Field::Err),
_ => {
match str::from_utf8(value) {
Ok(value) => Err(Error::unknown_field(value)),
Err(_) => Err(Error::invalid_type(Type::String)),
}
}
}
}
}
deserializer.visit(FieldVisitor::<D> {
phantom: PhantomData,
})
deserializer.deserialize(FieldVisitor)
}
}
struct Visitor<D, T, E>(PhantomData<D>, PhantomData<T>, PhantomData<E>)
where D: Deserializer, T: Deserialize, E: Deserialize;
struct Visitor<T, E>(PhantomData<Result<T, E>>);
impl<D, T, E> EnumVisitor for Visitor<D, T, E> where D: Deserializer,
T: Deserialize,
E: Deserialize {
impl<T, E> EnumVisitor for Visitor<T, E>
where T: Deserialize,
E: Deserialize
{
type Value = Result<T, E>;
fn visit<V>(&mut self, mut visitor: V) -> Result<Result<T, E>, V::Error>
where V: VariantVisitor {
match match visitor.visit_variant() {
Ok(val) => val,
Err(err) => return Err(From::from(err)),
} {
Field::Field0 => {
struct Visitor<D, T, E>(PhantomData<D>, PhantomData<T>, PhantomData<E>)
where D: Deserializer,
T: Deserialize,
E: Deserialize;
impl <D, T, E> ::de::Visitor for Visitor<D, T, E> where D: Deserializer,
T: Deserialize,
E: Deserialize {
type Value = Result<T, E>;
fn visit_seq<V>(&mut self, mut visitor: V)
-> Result<Result<T, E>, V::Error> where V: SeqVisitor {
let field0 = match match visitor.visit() {
Ok(val) => val,
Err(err) => return Err(From::from(err)),
} {
Some(value) => value,
None => return Err(Error::end_of_stream_error()),
};
match visitor.end() {
Ok(val) => val,
Err(err) => return Err(From::from(err)),
};
Ok(Result::Ok(field0))
}
}
visitor.visit_seq(Visitor::<D, T, E>(PhantomData,
PhantomData,
PhantomData))
where V: VariantVisitor
{
match try!(visitor.visit_variant()) {
Field::Ok => {
let value = try!(visitor.visit_newtype());
Ok(Ok(value))
}
Field::Field1 => {
struct Visitor<D, T, E>(PhantomData<D>, PhantomData<T>, PhantomData<E>)
where D: Deserializer,
T: Deserialize,
E: Deserialize;
impl <D, T, E> ::de::Visitor for Visitor<D, T, E> where D: Deserializer,
T: Deserialize,
E: Deserialize {
type Value = Result<T, E>;
fn visit_seq<V>(&mut self, mut visitor: V)
-> Result<Result<T, E>, V::Error> where V: SeqVisitor {
let field0 = match match visitor.visit() {
Ok(val) => val,
Err(err) => return Err(From::from(err)),
} {
Some(value) => value,
None => return Err(Error::end_of_stream_error()),
};
match visitor.end() {
Ok(val) => val,
Err(err) => return Err(From::from(err)),
};
Ok(Result::Err(field0))
}
}
visitor.visit_seq(Visitor::<D, T, E>(PhantomData,
PhantomData,
PhantomData))
Field::Err => {
let value = try!(visitor.visit_newtype());
Ok(Err(value))
}
}
}
}
deserializer.visit_enum("Result",
Visitor::<D, T, E>(PhantomData, PhantomData, PhantomData))
const VARIANTS: &'static [&'static str] = &["Ok", "Err"];
deserializer.deserialize_enum("Result", VARIANTS, Visitor(PhantomData))
}
}
///////////////////////////////////////////////////////////////////////////////
/// A target for deserializers that want to ignore data. Implements
/// Deserialize and silently eats data given to it.
pub struct IgnoredAny;
impl Deserialize for IgnoredAny {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<IgnoredAny, D::Error>
where D: Deserializer,
{
struct IgnoredAnyVisitor;
impl Visitor for IgnoredAnyVisitor {
type Value = IgnoredAny;
#[inline]
fn visit_bool<E>(&mut self, _: bool) -> Result<IgnoredAny, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_i64<E>(&mut self, _: i64) -> Result<IgnoredAny, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_u64<E>(&mut self, _: u64) -> Result<IgnoredAny, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_f64<E>(&mut self, _: f64) -> Result<IgnoredAny, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_str<E>(&mut self, _: &str) -> Result<IgnoredAny, E>
where E: Error,
{
Ok(IgnoredAny)
}
#[inline]
fn visit_none<E>(&mut self) -> Result<IgnoredAny, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_some<D>(&mut self, _: &mut D) -> Result<IgnoredAny, D::Error>
where D: Deserializer,
{
Ok(IgnoredAny)
}
#[inline]
fn visit_newtype_struct<D>(&mut self, _: &mut D) -> Result<IgnoredAny, D::Error>
where D: Deserializer,
{
Ok(IgnoredAny)
}
#[inline]
fn visit_unit<E>(&mut self) -> Result<IgnoredAny, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<IgnoredAny, V::Error>
where V: SeqVisitor,
{
while let Some(_) = try!(visitor.visit::<IgnoredAny>()) {
// Gobble
}
try!(visitor.end());
Ok(IgnoredAny)
}
#[inline]
fn visit_map<V>(&mut self, mut visitor: V) -> Result<IgnoredAny, V::Error>
where V: MapVisitor,
{
while let Some((_, _)) = try!(visitor.visit::<IgnoredAny, IgnoredAny>()) {
// Gobble
}
try!(visitor.end());
Ok(IgnoredAny)
}
#[inline]
fn visit_bytes<E>(&mut self, _: &[u8]) -> Result<IgnoredAny, E>
where E: Error,
{
Ok(IgnoredAny)
}
}
// TODO maybe not necessary with impl specialization
deserializer.deserialize_ignored_any(IgnoredAnyVisitor)
}
}
+400 -154
View File
@@ -1,23 +1,158 @@
//! Generic deserialization framework.
use std::error;
pub mod impls;
pub mod value;
mod from_primitive;
///////////////////////////////////////////////////////////////////////////////
pub trait Error {
fn syntax_error() -> Self;
/// `Error` is a trait that allows a `Deserialize` to generically create a
/// `Deserializer` error.
pub trait Error: Sized + error::Error {
/// Raised when there is general error when deserializing a type.
fn custom<T: Into<String>>(msg: T) -> Self;
fn end_of_stream_error() -> Self;
/// Raised when a `Deserialize` type unexpectedly hit the end of the stream.
fn end_of_stream() -> Self;
fn unknown_field_error(field: &str) -> Self;
/// Raised when a `Deserialize` was passed an incorrect type.
fn invalid_type(ty: Type) -> Self {
Error::custom(format!("Invalid type. Expected `{:?}`", ty))
}
fn missing_field_error(field: &'static str) -> Self;
/// Raised when a `Deserialize` was passed an incorrect value.
fn invalid_value(msg: &str) -> Self {
Error::custom(format!("Invalid value: {}", msg))
}
/// Raised when a fixed sized sequence or map was passed in the wrong amount of arguments.
fn invalid_length(len: usize) -> Self {
Error::custom(format!("Invalid length: {}", len))
}
/// Raised when a `Deserialize` enum type received an unexpected variant.
fn unknown_variant(field: &str) -> Self {
Error::custom(format!("Unknown variant `{}`", field))
}
/// Raised when a `Deserialize` struct type received an unexpected struct field.
fn unknown_field(field: &str) -> Self {
Error::custom(format!("Unknown field `{}`", field))
}
/// raised when a `deserialize` struct type did not receive a field.
fn missing_field(field: &'static str) -> Self {
Error::custom(format!("Missing field `{}`", field))
}
}
/// `Type` represents all the primitive types that can be deserialized. This is used by
/// `Error::invalid_type`.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Type {
/// Represents a `bool` type.
Bool,
/// Represents a `usize` type.
Usize,
/// Represents a `u8` type.
U8,
/// Represents a `u16` type.
U16,
/// Represents a `u32` type.
U32,
/// Represents a `u64` type.
U64,
/// Represents a `isize` type.
Isize,
/// Represents a `i8` type.
I8,
/// Represents a `i16` type.
I16,
/// Represents a `i32` type.
I32,
/// Represents a `i64` type.
I64,
/// Represents a `f32` type.
F32,
/// Represents a `f64` type.
F64,
/// Represents a `char` type.
Char,
/// Represents a `&str` type.
Str,
/// Represents a `String` type.
String,
/// Represents a `()` type.
Unit,
/// Represents an `Option<T>` type.
Option,
/// Represents a sequence type.
Seq,
/// Represents a map type.
Map,
/// Represents a unit struct type.
UnitStruct,
/// Represents a newtype type.
NewtypeStruct,
/// Represents a tuple struct type.
TupleStruct,
/// Represents a struct type.
Struct,
/// Represents a struct field name.
FieldName,
/// Represents a tuple type.
Tuple,
/// Represents an `enum` type.
Enum,
/// Represents an enum variant name.
VariantName,
/// Represents a struct variant.
StructVariant,
/// Represents a tuple variant.
TupleVariant,
/// Represents a unit variant.
UnitVariant,
/// Represents a `&[u8]` type.
Bytes,
}
///////////////////////////////////////////////////////////////////////////////
pub trait Deserialize {
/// `Deserialize` represents a type that can be deserialized.
pub trait Deserialize: Sized {
/// Deserialize this value given this `Deserializer`.
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer;
@@ -28,335 +163,397 @@ pub trait Deserialize {
/// `Deserializer` is a trait that can deserialize values by threading a `Visitor` trait through a
/// value. It supports two entry point styles which enables different kinds of deserialization.
///
/// 1) The `visit` method. File formats like JSON embed the type of it's construct in it's file
/// 1) The `deserialize` method. File formats like JSON embed the type of its construct in its file
/// format. This allows the `Deserializer` to deserialize into a generic type like
/// `json::Value`, which can represent all JSON types.
///
/// 2) The `visit_*` methods. File formats like bincode do not embed in it's format how to decode
/// it's values. It relies instead on the `Deserialize` type to hint to the `Deserializer` with
/// the `visit_*` methods how it should parse the next value. One downside though to only
/// supporting the `visit_*` types is that it does not allow for deserializing into a generic
/// `json::Value`-esque type.
/// 2) The `deserialize_*` methods. File formats like bincode do not embed in its format how to
/// decode its values. It relies instead on the `Deserialize` type to hint to the `Deserializer`
/// with the `deserialize_*` methods how it should parse the next value. One downside though to
/// only supporting the `deserialize_*` types is that it does not allow for deserializing into a
/// generic `json::Value`-esque type.
pub trait Deserializer {
/// The error type that can be returned if some error occurs during deserialization.
type Error: Error;
/// This method walks a visitor through a value as it is being deserialized.
fn visit<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a `bool` value.
#[inline]
fn visit_bool<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_bool<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `usize` value.
#[inline]
fn visit_usize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_usize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize_u64(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `u8` value.
#[inline]
fn visit_u8<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_u8<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize_u64(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `u16` value.
#[inline]
fn visit_u16<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_u16<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize_u64(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `u32` value.
#[inline]
fn visit_u32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_u32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize_u64(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `u64` value.
#[inline]
fn visit_u64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_u64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `isize` value.
#[inline]
fn visit_isize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_isize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize_i64(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `i8` value.
#[inline]
fn visit_i8<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_i8<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize_i64(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `i16` value.
#[inline]
fn visit_i16<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_i16<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize_i64(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `i32` value.
#[inline]
fn visit_i32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_i32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize_i64(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `i64` value.
#[inline]
fn visit_i64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_i64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a `f32` value.
#[inline]
fn visit_f32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_f32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize_f64(visitor)
}
/// This method hints that the `Deserialize` type is expecting a `f64` value.
#[inline]
fn visit_f64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_f64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a `char` value.
#[inline]
fn visit_char<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_char<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a `&str` value.
#[inline]
fn visit_str<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_str<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a `String` value.
#[inline]
fn visit_string<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_string<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_str(visitor)
self.deserialize_str(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `unit` value.
#[inline]
fn visit_unit<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_unit<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `Option` value. This allows
/// deserializers that encode an optional value as a nullable value to convert the null value
/// into a `None`, and a regular value as `Some(value)`.
#[inline]
fn visit_option<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_option<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a sequence value. This allows
/// deserializers to parse sequences that aren't tagged as sequences.
#[inline]
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_seq<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a map of values. This allows
/// deserializers to parse sequences that aren't tagged as maps.
/// This method hints that the `Deserialize` type is expecting a fixed size array. This allows
/// deserializers to parse arrays that aren't tagged as arrays.
///
/// By default, this deserializes arrays from a sequence.
#[inline]
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_fixed_size_array<V>(&mut self,
_len: usize,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting a named unit. This allows
/// deserializers to a named unit that aren't tagged as a named unit.
#[inline]
fn visit_named_unit<V>(&mut self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting a named sequence.
/// This allows deserializers to parse sequences that aren't tagged as sequences.
#[inline]
fn visit_named_seq<V>(&mut self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_seq(visitor)
}
/// This method hints that the `Deserialize` type is expecting a named map. This allows
/// deserializers to parse sequences that aren't tagged as maps.
#[inline]
fn visit_named_map<V>(&mut self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_map(visitor)
}
/// This method hints that the `Deserialize` type is expecting a tuple value. This allows
/// deserializers that provide a custom tuple serialization to properly deserialize the type.
#[inline]
fn visit_tuple<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting an enum value. This allows
/// deserializers that provide a custom enumeration serialization to properly deserialize the
/// type.
#[inline]
fn visit_enum<V>(&mut self, _enum: &str, _visitor: V) -> Result<V::Value, Self::Error>
where V: EnumVisitor,
{
Err(Error::syntax_error())
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a `Vec<u8>`. This allows
/// deserializers that provide a custom byte vector serialization to properly deserialize the
/// type.
#[inline]
fn visit_bytes<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_bytes<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
self.deserialize_seq(visitor)
}
/// Specify a format string for the deserializer.
///
/// The deserializer format is used to determine which format
/// specific field attributes should be used with the
/// deserializer.
fn format() -> &'static str {
""
/// This method hints that the `Deserialize` type is expecting a map of values. This allows
/// deserializers to parse sequences that aren't tagged as maps.
#[inline]
fn deserialize_map<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a unit struct. This allows
/// deserializers to a unit struct that aren't tagged as a unit struct.
#[inline]
fn deserialize_unit_struct<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_unit(visitor)
}
/// This method hints that the `Deserialize` type is expecting a newtype struct. This allows
/// deserializers to a newtype struct that aren't tagged as a newtype struct.
#[inline]
fn deserialize_newtype_struct<V>(&mut self,
name: &'static str,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_tuple_struct(name, 1, visitor)
}
/// This method hints that the `Deserialize` type is expecting a tuple struct. This allows
/// deserializers to parse sequences that aren't tagged as sequences.
#[inline]
fn deserialize_tuple_struct<V>(&mut self,
_name: &'static str,
len: usize,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_tuple(len, visitor)
}
/// This method hints that the `Deserialize` type is expecting a struct. This allows
/// deserializers to parse sequences that aren't tagged as maps.
#[inline]
fn deserialize_struct<V>(&mut self,
_name: &'static str,
_fields: &'static [&'static str],
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_map(visitor)
}
/// This method hints that the `Deserialize` type is expecting some sort of struct field
/// name. This allows deserializers to choose between &str, usize, or &[u8] to properly
/// deserialize a struct field.
#[inline]
fn deserialize_struct_field<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a tuple value. This allows
/// deserializers that provide a custom tuple serialization to properly deserialize the type.
#[inline]
fn deserialize_tuple<V>(&mut self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_seq(visitor)
}
/// This method hints that the `Deserialize` type is expecting an enum value. This allows
/// deserializers that provide a custom enumeration serialization to properly deserialize the
/// type.
#[inline]
fn deserialize_enum<V>(&mut self,
_enum: &'static str,
_variants: &'static [&'static str],
_visitor: V) -> Result<V::Value, Self::Error>
where V: EnumVisitor,
{
Err(Error::invalid_type(Type::Enum))
}
/// This method hints that the `Deserialize` type needs to deserialize a value whose type
/// doesn't matter because it is ignored.
#[inline]
fn deserialize_ignored_any<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
self.deserialize(visitor)
}
}
///////////////////////////////////////////////////////////////////////////////
/// This trait represents a visitor that walks through a deserializer.
pub trait Visitor {
/// The value produced by this visitor.
type Value: Deserialize;
/// `visit_bool` deserializes a `bool` into a `Value`.
fn visit_bool<E>(&mut self, _v: bool) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
Err(Error::invalid_type(Type::Bool))
}
/// `visit_isize` deserializes a `isize` into a `Value`.
fn visit_isize<E>(&mut self, v: isize) -> Result<Self::Value, E>
where E: Error,
{
self.visit_i64(v as i64)
}
/// `visit_i8` deserializes a `i8` into a `Value`.
fn visit_i8<E>(&mut self, v: i8) -> Result<Self::Value, E>
where E: Error,
{
self.visit_i64(v as i64)
}
/// `visit_i16` deserializes a `i16` into a `Value`.
fn visit_i16<E>(&mut self, v: i16) -> Result<Self::Value, E>
where E: Error,
{
self.visit_i64(v as i64)
}
/// `visit_i32` deserializes a `i32` into a `Value`.
fn visit_i32<E>(&mut self, v: i32) -> Result<Self::Value, E>
where E: Error,
{
self.visit_i64(v as i64)
}
/// `visit_i64` deserializes a `i64` into a `Value`.
fn visit_i64<E>(&mut self, _v: i64) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
Err(Error::invalid_type(Type::I64))
}
/// `visit_usize` deserializes a `usize` into a `Value`.
fn visit_usize<E>(&mut self, v: usize) -> Result<Self::Value, E>
where E: Error,
{
self.visit_u64(v as u64)
}
/// `visit_u8` deserializes a `u8` into a `Value`.
fn visit_u8<E>(&mut self, v: u8) -> Result<Self::Value, E>
where E: Error,
{
self.visit_u64(v as u64)
}
/// `visit_u16` deserializes a `u16` into a `Value`.
fn visit_u16<E>(&mut self, v: u16) -> Result<Self::Value, E>
where E: Error,
{
self.visit_u64(v as u64)
}
/// `visit_u32` deserializes a `u32` into a `Value`.
fn visit_u32<E>(&mut self, v: u32) -> Result<Self::Value, E>
where E: Error,
{
self.visit_u64(v as u64)
}
/// `visit_u64` deserializes a `u64` into a `Value`.
fn visit_u64<E>(&mut self, _v: u64) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
Err(Error::invalid_type(Type::U64))
}
/// `visit_f32` deserializes a `f32` into a `Value`.
fn visit_f32<E>(&mut self, v: f32) -> Result<Self::Value, E>
where E: Error,
{
self.visit_f64(v as f64)
}
/// `visit_f64` deserializes a `f64` into a `Value`.
fn visit_f64<E>(&mut self, _v: f64) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
Err(Error::invalid_type(Type::F64))
}
/// `visit_char` deserializes a `char` into a `Value`.
#[inline]
fn visit_char<E>(&mut self, v: char) -> Result<Self::Value, E>
where E: Error,
@@ -366,12 +563,16 @@ pub trait Visitor {
self.visit_string(v.to_string())
}
/// `visit_str` deserializes a `&str` into a `Value`.
fn visit_str<E>(&mut self, _v: &str) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
Err(Error::invalid_type(Type::Str))
}
/// `visit_string` deserializes a `String` into a `Value`. This allows a deserializer to avoid
/// a copy if it is deserializing a string from a `String` type. By default it passes a `&str`
/// to the `visit_str` method.
#[inline]
fn visit_string<E>(&mut self, v: String) -> Result<Self::Value, E>
where E: Error,
@@ -379,49 +580,64 @@ pub trait Visitor {
self.visit_str(&v)
}
/// `visit_unit` deserializes a `()` into a `Value`.
fn visit_unit<E>(&mut self) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
Err(Error::invalid_type(Type::Unit))
}
/// `visit_unit_struct` deserializes a unit struct into a `Value`.
#[inline]
fn visit_named_unit<E>(&mut self, _name: &str) -> Result<Self::Value, E>
fn visit_unit_struct<E>(&mut self, _name: &'static str) -> Result<Self::Value, E>
where E: Error,
{
self.visit_unit()
}
/// `visit_none` deserializes a none value into a `Value`.
fn visit_none<E>(&mut self) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
Err(Error::invalid_type(Type::Option))
}
/// `visit_some` deserializes a value into a `Value`.
fn visit_some<D>(&mut self, _deserializer: &mut D) -> Result<Self::Value, D::Error>
where D: Deserializer,
{
Err(Error::syntax_error())
Err(Error::invalid_type(Type::Option))
}
/// `visit_newtype_struct` deserializes a value into a `Value`.
fn visit_newtype_struct<D>(&mut self, _deserializer: &mut D) -> Result<Self::Value, D::Error>
where D: Deserializer,
{
Err(Error::invalid_type(Type::NewtypeStruct))
}
/// `visit_bool` deserializes a `SeqVisitor` into a `Value`.
fn visit_seq<V>(&mut self, _visitor: V) -> Result<Self::Value, V::Error>
where V: SeqVisitor,
{
Err(Error::syntax_error())
Err(Error::invalid_type(Type::Seq))
}
/// `visit_map` deserializes a `MapVisitor` into a `Value`.
fn visit_map<V>(&mut self, _visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor,
{
Err(Error::syntax_error())
Err(Error::invalid_type(Type::Map))
}
/// `visit_bytes` deserializes a `&[u8]` into a `Value`.
fn visit_bytes<E>(&mut self, _v: &[u8]) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax_error())
Err(Error::invalid_type(Type::Bytes))
}
/// `visit_byte_buf` deserializes a `Vec<u8>` into a `Value`.
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<Self::Value, E>
where E: Error,
{
@@ -431,14 +647,23 @@ pub trait Visitor {
///////////////////////////////////////////////////////////////////////////////
/// `SeqVisitor` visits each item in a sequence.
///
/// This is a trait that a `Deserializer` passes to a `Visitor` implementation, which deserializes
/// each item in a sequence.
pub trait SeqVisitor {
/// The error type that can be returned if some error occurs during deserialization.
type Error: Error;
/// This returns a `Ok(Some(value))` for the next value in the sequence, or `Ok(None)` if there
/// are no more remaining items.
fn visit<T>(&mut self) -> Result<Option<T>, Self::Error>
where T: Deserialize;
/// This signals to the `SeqVisitor` that the `Visitor` does not expect any more items.
fn end(&mut self) -> Result<(), Self::Error>;
/// Return the lower and upper bound of items remaining in the sequence.
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
@@ -468,9 +693,15 @@ impl<'a, V> SeqVisitor for &'a mut V where V: SeqVisitor {
///////////////////////////////////////////////////////////////////////////////
/// `MapVisitor` visits each item in a sequence.
///
/// This is a trait that a `Deserializer` passes to a `Visitor` implementation.
pub trait MapVisitor {
/// The error type that can be returned if some error occurs during deserialization.
type Error: Error;
/// This returns a `Ok(Some((key, value)))` for the next (key-value) pair in the map, or
/// `Ok(None)` if there are no more remaining items.
#[inline]
fn visit<K, V>(&mut self) -> Result<Option<(K, V)>, Self::Error>
where K: Deserialize,
@@ -485,23 +716,29 @@ pub trait MapVisitor {
}
}
/// This returns a `Ok(Some(key))` for the next key in the map, or `Ok(None)` if there are no
/// more remaining items.
fn visit_key<K>(&mut self) -> Result<Option<K>, Self::Error>
where K: Deserialize;
/// This returns a `Ok(value)` for the next value in the map.
fn visit_value<V>(&mut self) -> Result<V, Self::Error>
where V: Deserialize;
/// This signals to the `MapVisitor` that the `Visitor` does not expect any more items.
fn end(&mut self) -> Result<(), Self::Error>;
/// Return the lower and upper bound of items remaining in the sequence.
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
/// Report that the struct has a field that wasn't deserialized
fn missing_field<V>(&mut self, field: &'static str) -> Result<V, Self::Error>
where V: Deserialize,
{
Err(Error::missing_field_error(field))
Err(Error::missing_field(field))
}
}
@@ -546,8 +783,10 @@ impl<'a, V_> MapVisitor for &'a mut V_ where V_: MapVisitor {
/// `EnumVisitor` is a visitor that is created by the `Deserialize` and passed to the
/// `Deserializer` in order to deserialize enums.
pub trait EnumVisitor {
/// The value produced by this visitor.
type Value;
/// Visit the specific variant with the `VariantVisitor`.
fn visit<V>(&mut self, visitor: V) -> Result<Self::Value, V::Error>
where V: VariantVisitor;
}
@@ -557,6 +796,7 @@ pub trait EnumVisitor {
/// `VariantVisitor` is a visitor that is created by the `Deserializer` and passed to the
/// `Deserialize` in order to deserialize a specific enum variant.
pub trait VariantVisitor {
/// The error type that can be returned if some error occurs during deserialization.
type Error: Error;
/// `visit_variant` is called to identify which variant to deserialize.
@@ -565,21 +805,35 @@ pub trait VariantVisitor {
/// `visit_unit` is called when deserializing a variant with no values.
fn visit_unit(&mut self) -> Result<(), Self::Error> {
Err(Error::syntax_error())
Err(Error::invalid_type(Type::UnitVariant))
}
/// `visit_seq` is called when deserializing a tuple-like variant.
fn visit_seq<V>(&mut self, _visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
/// `visit_newtype` is called when deserializing a variant with a single value. By default this
/// uses the `visit_tuple` method to deserialize the value.
#[inline]
fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
where T: Deserialize,
{
Err(Error::syntax_error())
let (value,) = try!(self.visit_tuple(1, impls::TupleVisitor1::new()));
Ok(value)
}
/// `visit_map` is called when deserializing a struct-like variant.
fn visit_map<V>(&mut self, _visitor: V) -> Result<V::Value, Self::Error>
/// `visit_tuple` is called when deserializing a tuple-like variant.
fn visit_tuple<V>(&mut self,
_len: usize,
_visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
Err(Error::syntax_error())
Err(Error::invalid_type(Type::TupleVariant))
}
/// `visit_struct` is called when deserializing a struct-like variant.
fn visit_struct<V>(&mut self,
_fields: &'static [&'static str],
_visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
Err(Error::invalid_type(Type::StructVariant))
}
}
@@ -596,33 +850,25 @@ impl<'a, T> VariantVisitor for &'a mut T where T: VariantVisitor {
(**self).visit_unit()
}
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, T::Error>
where V: Visitor,
fn visit_newtype<D>(&mut self) -> Result<D, T::Error>
where D: Deserialize,
{
(**self).visit_seq(visitor)
(**self).visit_newtype()
}
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, T::Error>
fn visit_tuple<V>(&mut self,
len: usize,
visitor: V) -> Result<V::Value, T::Error>
where V: Visitor,
{
(**self).visit_map(visitor)
(**self).visit_tuple(len, visitor)
}
fn visit_struct<V>(&mut self,
fields: &'static [&'static str],
visitor: V) -> Result<V::Value, T::Error>
where V: Visitor,
{
(**self).visit_struct(fields, visitor)
}
}
///////////////////////////////////////////////////////////////////////////////
pub trait EnumSeqVisitor {
type Value;
fn visit<V>(&mut self, visitor: V) -> Result<Self::Value, V::Error>
where V: SeqVisitor;
}
///////////////////////////////////////////////////////////////////////////////
pub trait EnumMapVisitor {
type Value;
fn visit<V>(&mut self, visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor;
}
+310 -128
View File
@@ -1,3 +1,5 @@
//! This module supports deserializing from primitives with the `ValueDeserializer` trait.
use std::collections::{
BTreeMap,
BTreeSet,
@@ -9,58 +11,120 @@ use std::collections::{
hash_set,
};
use std::hash::Hash;
use std::error;
use std::fmt;
use std::vec;
use std::marker::PhantomData;
use de;
use bytes;
///////////////////////////////////////////////////////////////////////////////
/// This represents all the possible errors that can occur using the `ValueDeserializer`.
#[derive(Clone, Debug, PartialEq)]
pub enum Error {
SyntaxError,
EndOfStreamError,
UnknownFieldError(String),
MissingFieldError(&'static str),
/// The value had some custom error.
Custom(String),
/// The value had an incorrect type.
InvalidType(de::Type),
/// The value had an invalid length.
InvalidLength(usize),
/// The value is invalid and cannot be deserialized.
InvalidValue(String),
/// EOF while deserializing a value.
EndOfStream,
/// Unknown variant in enum.
UnknownVariant(String),
/// Unknown field in struct.
UnknownField(String),
/// Struct is missing a field.
MissingField(&'static str),
}
impl de::Error for Error {
fn syntax_error() -> Self { Error::SyntaxError }
fn end_of_stream_error() -> Self { Error::EndOfStreamError }
fn unknown_field_error(field: &str) -> Self { Error::UnknownFieldError(field.to_string()) }
fn missing_field_error(field: &'static str) -> Self { Error::MissingFieldError(field) }
fn custom<T: Into<String>>(msg: T) -> Self { Error::Custom(msg.into()) }
fn end_of_stream() -> Self { Error::EndOfStream }
fn invalid_type(ty: de::Type) -> Self { Error::InvalidType(ty) }
fn invalid_value(msg: &str) -> Self { Error::InvalidValue(msg.to_owned()) }
fn invalid_length(len: usize) -> Self { Error::InvalidLength(len) }
fn unknown_variant(variant: &str) -> Self { Error::UnknownVariant(String::from(variant)) }
fn unknown_field(field: &str) -> Self { Error::UnknownField(String::from(field)) }
fn missing_field(field: &'static str) -> Self { Error::MissingField(field) }
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
Error::Custom(ref s) => write!(formatter, "{}", s),
Error::EndOfStream => formatter.write_str("End of stream"),
Error::InvalidType(ty) => write!(formatter, "Invalid type, expected `{:?}`", ty),
Error::InvalidValue(ref value) => write!(formatter, "Invalid value: {}", value),
Error::InvalidLength(len) => write!(formatter, "Invalid length: {}", len),
Error::UnknownVariant(ref variant) => {
write!(formatter, "Unknown variant: {}", variant)
}
Error::UnknownField(ref field) => write!(formatter, "Unknown field: {}", field),
Error::MissingField(ref field) => write!(formatter, "Missing field: {}", field),
}
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Deserialization Error"
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
///////////////////////////////////////////////////////////////////////////////
pub trait ValueDeserializer {
type Deserializer: de::Deserializer<Error=Error>;
/// This trait converts primitive types into a deserializer.
pub trait ValueDeserializer<E: de::Error = Error> {
/// The actual deserializer type.
type Deserializer: de::Deserializer<Error=E>;
/// Convert this value into a deserializer.
fn into_deserializer(self) -> Self::Deserializer;
}
///////////////////////////////////////////////////////////////////////////////
impl ValueDeserializer for () {
type Deserializer = UnitDeserializer;
impl<E> ValueDeserializer<E> for ()
where E: de::Error,
{
type Deserializer = UnitDeserializer<E>;
fn into_deserializer(self) -> UnitDeserializer {
UnitDeserializer
fn into_deserializer(self) -> UnitDeserializer<E> {
UnitDeserializer(PhantomData)
}
}
/// A helper deserializer that deserializes a `()`.
pub struct UnitDeserializer;
pub struct UnitDeserializer<E>(PhantomData<E>);
impl de::Deserializer for UnitDeserializer {
type Error = Error;
impl<E> de::Deserializer for UnitDeserializer<E>
where E: de::Error
{
type Error = E;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
visitor.visit_unit()
}
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
visitor.visit_none()
@@ -71,25 +135,30 @@ impl de::Deserializer for UnitDeserializer {
macro_rules! primitive_deserializer {
($ty:ty, $name:ident, $method:ident) => {
pub struct $name(Option<$ty>);
/// A helper deserializer that deserializes a number.
pub struct $name<E>(Option<$ty>, PhantomData<E>);
impl ValueDeserializer for $ty {
type Deserializer = $name;
impl<E> ValueDeserializer<E> for $ty
where E: de::Error,
{
type Deserializer = $name<E>;
fn into_deserializer(self) -> $name {
$name(Some(self))
fn into_deserializer(self) -> $name<E> {
$name(Some(self), PhantomData)
}
}
impl de::Deserializer for $name {
type Error = Error;
impl<E> de::Deserializer for $name<E>
where E: de::Error,
{
type Error = E;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
match self.0.take() {
Some(v) => visitor.$method(v),
None => Err(de::Error::end_of_stream_error()),
None => Err(de::Error::end_of_stream()),
}
}
}
@@ -114,45 +183,54 @@ primitive_deserializer!(char, CharDeserializer, visit_char);
///////////////////////////////////////////////////////////////////////////////
/// A helper deserializer that deserializes a `&str`.
pub struct StrDeserializer<'a>(Option<&'a str>);
pub struct StrDeserializer<'a, E>(Option<&'a str>, PhantomData<E>);
impl<'a> ValueDeserializer for &'a str {
type Deserializer = StrDeserializer<'a>;
impl<'a, E> ValueDeserializer<E> for &'a str
where E: de::Error,
{
type Deserializer = StrDeserializer<'a, E>;
fn into_deserializer(self) -> StrDeserializer<'a> {
StrDeserializer(Some(self))
fn into_deserializer(self) -> StrDeserializer<'a, E> {
StrDeserializer(Some(self), PhantomData)
}
}
impl<'a> de::Deserializer for StrDeserializer<'a> {
type Error = Error;
impl<'a, E> de::Deserializer for StrDeserializer<'a, E>
where E: de::Error,
{
type Error = E;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
match self.0.take() {
Some(v) => visitor.visit_str(v),
None => Err(de::Error::end_of_stream_error()),
None => Err(de::Error::end_of_stream()),
}
}
fn visit_enum<V>(&mut self, _name: &str, mut visitor: V) -> Result<V::Value, Error>
fn deserialize_enum<V>(&mut self,
_name: &str,
_variants: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::EnumVisitor,
{
visitor.visit(self)
}
}
impl<'a> de::VariantVisitor for StrDeserializer<'a> {
type Error = Error;
impl<'a, E> de::VariantVisitor for StrDeserializer<'a, E>
where E: de::Error,
{
type Error = E;
fn visit_variant<T>(&mut self) -> Result<T, Error>
fn visit_variant<T>(&mut self) -> Result<T, Self::Error>
where T: de::Deserialize,
{
de::Deserialize::deserialize(self)
}
fn visit_unit(&mut self) -> Result<(), Error> {
fn visit_unit(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
@@ -160,85 +238,102 @@ impl<'a> de::VariantVisitor for StrDeserializer<'a> {
///////////////////////////////////////////////////////////////////////////////
/// A helper deserializer that deserializes a `String`.
pub struct StringDeserializer(Option<String>);
pub struct StringDeserializer<E>(Option<String>, PhantomData<E>);
impl ValueDeserializer for String {
type Deserializer = StringDeserializer;
impl<E> ValueDeserializer<E> for String
where E: de::Error,
{
type Deserializer = StringDeserializer<E>;
fn into_deserializer(self) -> StringDeserializer {
StringDeserializer(Some(self))
fn into_deserializer(self) -> StringDeserializer<E> {
StringDeserializer(Some(self), PhantomData)
}
}
impl de::Deserializer for StringDeserializer {
type Error = Error;
impl<E> de::Deserializer for StringDeserializer<E>
where E: de::Error,
{
type Error = E;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
match self.0.take() {
Some(string) => visitor.visit_string(string),
None => Err(de::Error::end_of_stream_error()),
None => Err(de::Error::end_of_stream()),
}
}
fn visit_enum<V>(&mut self, _name: &str, mut visitor: V) -> Result<V::Value, Error>
fn deserialize_enum<V>(&mut self,
_name: &str,
_variants: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::EnumVisitor,
{
visitor.visit(self)
}
}
impl<'a> de::VariantVisitor for StringDeserializer {
type Error = Error;
impl<'a, E> de::VariantVisitor for StringDeserializer<E>
where E: de::Error,
{
type Error = E;
fn visit_variant<T>(&mut self) -> Result<T, Error>
fn visit_variant<T>(&mut self) -> Result<T, Self::Error>
where T: de::Deserialize,
{
de::Deserialize::deserialize(self)
}
fn visit_unit(&mut self) -> Result<(), Error> {
fn visit_unit(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
///////////////////////////////////////////////////////////////////////////////
pub struct SeqDeserializer<I> {
/// A helper deserializer that deserializes a sequence.
pub struct SeqDeserializer<I, E> {
iter: I,
len: usize,
marker: PhantomData<E>,
}
impl<I> SeqDeserializer<I> {
impl<I, E> SeqDeserializer<I, E>
where E: de::Error,
{
/// Construct a new `SeqDeserializer<I>`.
pub fn new(iter: I, len: usize) -> Self {
SeqDeserializer {
iter: iter,
len: len,
marker: PhantomData,
}
}
}
impl<I, T> de::Deserializer for SeqDeserializer<I>
impl<I, T, E> de::Deserializer for SeqDeserializer<I, E>
where I: Iterator<Item=T>,
T: ValueDeserializer,
T: ValueDeserializer<E>,
E: de::Error,
{
type Error = Error;
type Error = E;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
visitor.visit_seq(self)
}
}
impl<I, T> de::SeqVisitor for SeqDeserializer<I>
impl<I, T, E> de::SeqVisitor for SeqDeserializer<I, E>
where I: Iterator<Item=T>,
T: ValueDeserializer,
T: ValueDeserializer<E>,
E: de::Error,
{
type Error = Error;
type Error = E;
fn visit<V>(&mut self) -> Result<Option<V>, Error>
fn visit<V>(&mut self) -> Result<Option<V>, Self::Error>
where V: de::Deserialize
{
match self.iter.next() {
@@ -251,11 +346,11 @@ impl<I, T> de::SeqVisitor for SeqDeserializer<I>
}
}
fn end(&mut self) -> Result<(), Error> {
fn end(&mut self) -> Result<(), Self::Error> {
if self.len == 0 {
Ok(())
} else {
Err(de::Error::end_of_stream_error())
Err(de::Error::invalid_length(self.len))
}
}
@@ -266,34 +361,37 @@ impl<I, T> de::SeqVisitor for SeqDeserializer<I>
///////////////////////////////////////////////////////////////////////////////
impl<T> ValueDeserializer for Vec<T>
where T: ValueDeserializer,
impl<T, E> ValueDeserializer<E> for Vec<T>
where T: ValueDeserializer<E>,
E: de::Error,
{
type Deserializer = SeqDeserializer<vec::IntoIter<T>>;
type Deserializer = SeqDeserializer<vec::IntoIter<T>, E>;
fn into_deserializer(self) -> SeqDeserializer<vec::IntoIter<T>> {
fn into_deserializer(self) -> Self::Deserializer {
let len = self.len();
SeqDeserializer::new(self.into_iter(), len)
}
}
impl<T> ValueDeserializer for BTreeSet<T>
where T: ValueDeserializer + Eq + Ord,
impl<T, E> ValueDeserializer<E> for BTreeSet<T>
where T: ValueDeserializer<E> + Eq + Ord,
E: de::Error,
{
type Deserializer = SeqDeserializer<btree_set::IntoIter<T>>;
type Deserializer = SeqDeserializer<btree_set::IntoIter<T>, E>;
fn into_deserializer(self) -> SeqDeserializer<btree_set::IntoIter<T>> {
fn into_deserializer(self) -> Self::Deserializer {
let len = self.len();
SeqDeserializer::new(self.into_iter(), len)
}
}
impl<T> ValueDeserializer for HashSet<T>
where T: ValueDeserializer + Eq + Hash,
impl<T, E> ValueDeserializer<E> for HashSet<T>
where T: ValueDeserializer<E> + Eq + Hash,
E: de::Error,
{
type Deserializer = SeqDeserializer<hash_set::IntoIter<T>>;
type Deserializer = SeqDeserializer<hash_set::IntoIter<T>, E>;
fn into_deserializer(self) -> SeqDeserializer<hash_set::IntoIter<T>> {
fn into_deserializer(self) -> Self::Deserializer {
let len = self.len();
SeqDeserializer::new(self.into_iter(), len)
}
@@ -301,52 +399,92 @@ impl<T> ValueDeserializer for HashSet<T>
///////////////////////////////////////////////////////////////////////////////
pub struct MapDeserializer<I, K, V>
/// A helper deserializer that deserializes a sequence using a `SeqVisitor`.
pub struct SeqVisitorDeserializer<V_, E> {
visitor: V_,
marker: PhantomData<E>,
}
impl<V_, E> SeqVisitorDeserializer<V_, E>
where V_: de::SeqVisitor<Error = E>,
E: de::Error,
{
/// Construct a new `SeqVisitorDeserializer<V_, E>`.
pub fn new(visitor: V_) -> Self {
SeqVisitorDeserializer{
visitor: visitor,
marker: PhantomData
}
}
}
impl<V_, E> de::Deserializer for SeqVisitorDeserializer<V_, E>
where V_: de::SeqVisitor<Error = E>,
E: de::Error,
{
type Error = E;
fn deserialize<V: de::Visitor>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_seq(&mut self.visitor)
}
}
///////////////////////////////////////////////////////////////////////////////
/// A helper deserializer that deserializes a map.
pub struct MapDeserializer<I, K, V, E>
where I: Iterator<Item=(K, V)>,
K: ValueDeserializer,
V: ValueDeserializer,
K: ValueDeserializer<E>,
V: ValueDeserializer<E>,
E: de::Error,
{
iter: I,
value: Option<V>,
len: usize,
marker: PhantomData<E>,
}
impl<I, K, V> MapDeserializer<I, K, V>
impl<I, K, V, E> MapDeserializer<I, K, V, E>
where I: Iterator<Item=(K, V)>,
K: ValueDeserializer,
V: ValueDeserializer,
K: ValueDeserializer<E>,
V: ValueDeserializer<E>,
E: de::Error,
{
/// Construct a new `MapDeserializer<I, K, V>`.
pub fn new(iter: I, len: usize) -> Self {
MapDeserializer {
iter: iter,
value: None,
len: len,
marker: PhantomData,
}
}
}
impl<I, K, V> de::Deserializer for MapDeserializer<I, K, V>
impl<I, K, V, E> de::Deserializer for MapDeserializer<I, K, V, E>
where I: Iterator<Item=(K, V)>,
K: ValueDeserializer,
V: ValueDeserializer,
K: ValueDeserializer<E>,
V: ValueDeserializer<E>,
E: de::Error,
{
type Error = Error;
type Error = E;
fn visit<V_>(&mut self, mut visitor: V_) -> Result<V_::Value, Error>
fn deserialize<V_>(&mut self, mut visitor: V_) -> Result<V_::Value, Self::Error>
where V_: de::Visitor,
{
visitor.visit_map(self)
}
}
impl<I, K, V> de::MapVisitor for MapDeserializer<I, K, V>
impl<I, K, V, E> de::MapVisitor for MapDeserializer<I, K, V, E>
where I: Iterator<Item=(K, V)>,
K: ValueDeserializer,
V: ValueDeserializer,
K: ValueDeserializer<E>,
V: ValueDeserializer<E>,
E: de::Error,
{
type Error = Error;
type Error = E;
fn visit_key<T>(&mut self) -> Result<Option<T>, Error>
fn visit_key<T>(&mut self) -> Result<Option<T>, Self::Error>
where T: de::Deserialize,
{
match self.iter.next() {
@@ -360,7 +498,7 @@ impl<I, K, V> de::MapVisitor for MapDeserializer<I, K, V>
}
}
fn visit_value<T>(&mut self) -> Result<T, Error>
fn visit_value<T>(&mut self) -> Result<T, Self::Error>
where T: de::Deserialize,
{
match self.value.take() {
@@ -368,15 +506,17 @@ impl<I, K, V> de::MapVisitor for MapDeserializer<I, K, V>
let mut de = value.into_deserializer();
de::Deserialize::deserialize(&mut de)
}
None => Err(de::Error::syntax_error())
None => {
Err(de::Error::end_of_stream())
}
}
}
fn end(&mut self) -> Result<(), Error> {
fn end(&mut self) -> Result<(), Self::Error> {
if self.len == 0 {
Ok(())
} else {
Err(de::Error::end_of_stream_error())
Err(de::Error::invalid_length(self.len))
}
}
@@ -387,25 +527,27 @@ impl<I, K, V> de::MapVisitor for MapDeserializer<I, K, V>
///////////////////////////////////////////////////////////////////////////////
impl<K, V> ValueDeserializer for BTreeMap<K, V>
where K: ValueDeserializer + Eq + Ord,
V: ValueDeserializer,
impl<K, V, E> ValueDeserializer<E> for BTreeMap<K, V>
where K: ValueDeserializer<E> + Eq + Ord,
V: ValueDeserializer<E>,
E: de::Error,
{
type Deserializer = MapDeserializer<btree_map::IntoIter<K, V>, K, V>;
type Deserializer = MapDeserializer<btree_map::IntoIter<K, V>, K, V, E>;
fn into_deserializer(self) -> MapDeserializer<btree_map::IntoIter<K, V>, K, V> {
fn into_deserializer(self) -> Self::Deserializer {
let len = self.len();
MapDeserializer::new(self.into_iter(), len)
}
}
impl<K, V> ValueDeserializer for HashMap<K, V>
where K: ValueDeserializer + Eq + Hash,
V: ValueDeserializer,
impl<K, V, E> ValueDeserializer<E> for HashMap<K, V>
where K: ValueDeserializer<E> + Eq + Hash,
V: ValueDeserializer<E>,
E: de::Error,
{
type Deserializer = MapDeserializer<hash_map::IntoIter<K, V>, K, V>;
type Deserializer = MapDeserializer<hash_map::IntoIter<K, V>, K, V, E>;
fn into_deserializer(self) -> MapDeserializer<hash_map::IntoIter<K, V>, K, V> {
fn into_deserializer(self) -> Self::Deserializer {
let len = self.len();
MapDeserializer::new(self.into_iter(), len)
}
@@ -413,26 +555,62 @@ impl<K, V> ValueDeserializer for HashMap<K, V>
///////////////////////////////////////////////////////////////////////////////
impl<'a> ValueDeserializer for bytes::Bytes<'a>
{
type Deserializer = BytesDeserializer<'a>;
/// A helper deserializer that deserializes a map using a `MapVisitor`.
pub struct MapVisitorDeserializer<V_, E> {
visitor: V_,
marker: PhantomData<E>,
}
fn into_deserializer(self) -> BytesDeserializer<'a> {
BytesDeserializer(Some(self.into()))
impl<V_, E> MapVisitorDeserializer<V_, E>
where V_: de::MapVisitor<Error = E>,
E: de::Error,
{
/// Construct a new `MapVisitorDeserializer<V_, E>`.
pub fn new(visitor: V_) -> Self {
MapVisitorDeserializer{
visitor: visitor,
marker: PhantomData
}
}
}
pub struct BytesDeserializer<'a> (Option<&'a [u8]>);
impl<V_, E> de::Deserializer for MapVisitorDeserializer<V_, E>
where V_: de::MapVisitor<Error = E>,
E: de::Error,
{
type Error = E;
impl<'a> de::Deserializer for BytesDeserializer<'a> {
type Error = Error;
fn deserialize<V: de::Visitor>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_map(&mut self.visitor)
}
}
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
///////////////////////////////////////////////////////////////////////////////
impl<'a, E> ValueDeserializer<E> for bytes::Bytes<'a>
where E: de::Error,
{
type Deserializer = BytesDeserializer<'a, E>;
fn into_deserializer(self) -> BytesDeserializer<'a, E> {
BytesDeserializer(Some(self.into()), PhantomData)
}
}
/// A helper deserializer that deserializes a `&[u8]`.
pub struct BytesDeserializer<'a, E> (Option<&'a [u8]>, PhantomData<E>);
impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
where E: de::Error
{
type Error = E;
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
match self.0.take() {
Some(bytes) => visitor.visit_bytes(bytes),
None => Err(de::Error::end_of_stream_error()),
None => Err(de::Error::end_of_stream()),
}
}
}
@@ -440,26 +618,30 @@ impl<'a> de::Deserializer for BytesDeserializer<'a> {
///////////////////////////////////////////////////////////////////////////////
impl ValueDeserializer for bytes::ByteBuf
impl<E> ValueDeserializer<E> for bytes::ByteBuf
where E: de::Error,
{
type Deserializer = ByteBufDeserializer;
type Deserializer = ByteBufDeserializer<E>;
fn into_deserializer(self) -> Self::Deserializer {
ByteBufDeserializer(Some(self.into()))
ByteBufDeserializer(Some(self.into()), PhantomData)
}
}
pub struct ByteBufDeserializer(Option<Vec<u8>>);
/// A helper deserializer that deserializes a `Vec<u8>`.
pub struct ByteBufDeserializer<E>(Option<Vec<u8>>, PhantomData<E>);
impl de::Deserializer for ByteBufDeserializer {
type Error = Error;
impl<E> de::Deserializer for ByteBufDeserializer<E>
where E: de::Error,
{
type Error = E;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
match self.0.take() {
Some(bytes) => visitor.visit_byte_buf(bytes),
None => Err(de::Error::end_of_stream_error()),
None => Err(de::Error::end_of_stream()),
}
}
}
+4
View File
@@ -1,6 +1,9 @@
//! 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,
@@ -8,6 +11,7 @@ pub struct LineColIterator<Iter: Iterator<Item=io::Result<u8>>> {
}
impl<Iter: Iterator<Item=io::Result<u8>>> LineColIterator<Iter> {
/// Construct a new `LineColIterator<Iter>`.
pub fn new(iter: Iter) -> LineColIterator<Iter> {
LineColIterator {
iter: iter,
-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
}
}
-694
View File
@@ -1,694 +0,0 @@
use std::char;
use std::i32;
use std::io;
use std::str;
use de;
use iter::LineColIterator;
use super::error::{Error, ErrorCode};
pub struct Deserializer<Iter: Iterator<Item=io::Result<u8>>> {
rdr: LineColIterator<Iter>,
ch: Option<u8>,
str_buf: Vec<u8>,
}
macro_rules! try_or_invalid {
($self_:expr, $e:expr) => {
match $e {
Some(v) => v,
None => { return Err($self_.error(ErrorCode::InvalidNumber)); }
}
}
}
impl<Iter> Deserializer<Iter>
where Iter: Iterator<Item=io::Result<u8>>,
{
/// Creates the JSON parser from an `std::iter::Iterator`.
#[inline]
pub fn new(rdr: Iter) -> Result<Deserializer<Iter>, Error> {
let mut deserializer = Deserializer {
rdr: LineColIterator::new(rdr),
ch: None,
str_buf: Vec::with_capacity(128),
};
try!(deserializer.bump());
Ok(deserializer)
}
#[inline]
pub fn end(&mut self) -> Result<(), Error> {
try!(self.parse_whitespace());
if self.eof() {
Ok(())
} else {
Err(self.error(ErrorCode::TrailingCharacters))
}
}
fn eof(&self) -> bool { self.ch.is_none() }
fn ch_or_null(&self) -> u8 { self.ch.unwrap_or(b'\x00') }
fn bump(&mut self) -> Result<(), Error> {
self.ch = match self.rdr.next() {
Some(Err(err)) => { return Err(Error::IoError(err)); }
Some(Ok(ch)) => Some(ch),
None => None,
};
Ok(())
}
fn next_char(&mut self) -> Result<Option<u8>, Error> {
try!(self.bump());
Ok(self.ch)
}
fn ch_is(&self, c: u8) -> bool {
self.ch == Some(c)
}
fn error(&mut self, reason: ErrorCode) -> Error {
Error::SyntaxError(reason, self.rdr.line(), self.rdr.col())
}
fn parse_whitespace(&mut self) -> Result<(), Error> {
while self.ch_is(b' ') ||
self.ch_is(b'\n') ||
self.ch_is(b'\t') ||
self.ch_is(b'\r') { try!(self.bump()); }
Ok(())
}
fn parse_value<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
try!(self.parse_whitespace());
if self.eof() {
return Err(self.error(ErrorCode::EOFWhileParsingValue));
}
let value = match self.ch_or_null() {
b'n' => {
try!(self.parse_ident(b"ull"));
visitor.visit_unit()
}
b't' => {
try!(self.parse_ident(b"rue"));
visitor.visit_bool(true)
}
b'f' => {
try!(self.parse_ident(b"alse"));
visitor.visit_bool(false)
}
b'0' ... b'9' | b'-' => self.parse_number(visitor),
b'"' => {
try!(self.parse_string());
let s = str::from_utf8(&self.str_buf).unwrap();
visitor.visit_str(s)
}
b'[' => {
try!(self.bump());
visitor.visit_seq(SeqVisitor::new(self))
}
b'{' => {
try!(self.bump());
visitor.visit_map(MapVisitor::new(self))
}
_ => {
Err(self.error(ErrorCode::ExpectedSomeValue))
}
};
match value {
Ok(value) => Ok(value),
Err(Error::SyntaxError(code, _, _)) => Err(self.error(code)),
Err(err) => Err(err),
}
}
fn parse_ident(&mut self, ident: &[u8]) -> Result<(), Error> {
for c in ident {
if Some(*c) != try!(self.next_char()) {
return Err(self.error(ErrorCode::ExpectedSomeIdent));
}
}
try!(self.bump());
Ok(())
}
fn parse_number<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
let mut neg = false;
if self.ch_is(b'-') {
try!(self.bump());
neg = true;
}
let res = try!(self.parse_integer());
if self.ch_is(b'.') || self.ch_is(b'e') || self.ch_is(b'E') {
let mut res = res as f64;
if self.ch_is(b'.') {
res = try!(self.parse_decimal(res));
}
if self.ch_is(b'e') || self.ch_is(b'E') {
res = try!(self.parse_exponent(res));
}
if neg {
visitor.visit_f64(-res)
} else {
visitor.visit_f64(res)
}
} else {
if neg {
let res = -(res as i64);
// Make sure we didn't underflow.
if res > 0 {
Err(self.error(ErrorCode::InvalidNumber))
} else {
visitor.visit_i64(res)
}
} else {
visitor.visit_u64(res)
}
}
}
fn parse_integer(&mut self) -> Result<u64, Error> {
let mut accum: u64 = 0;
match self.ch_or_null() {
b'0' => {
try!(self.bump());
// There can be only one leading '0'.
match self.ch_or_null() {
b'0' ... b'9' => {
return Err(self.error(ErrorCode::InvalidNumber));
}
_ => ()
}
},
b'1' ... b'9' => {
while !self.eof() {
match self.ch_or_null() {
c @ b'0' ... b'9' => {
accum = try_or_invalid!(self, accum.checked_mul(10));
accum = try_or_invalid!(self, accum.checked_add((c as u64) - ('0' as u64)));
try!(self.bump());
}
_ => break,
}
}
}
_ => { return Err(self.error(ErrorCode::InvalidNumber)); }
}
Ok(accum)
}
fn parse_decimal(&mut self, res: f64) -> Result<f64, Error> {
try!(self.bump());
// Make sure a digit follows the decimal place.
match self.ch_or_null() {
b'0' ... b'9' => (),
_ => { return Err(self.error(ErrorCode::InvalidNumber)); }
}
let mut res = res;
let mut dec = 1.0;
while !self.eof() {
match self.ch_or_null() {
c @ b'0' ... b'9' => {
dec /= 10.0;
res += (((c as u64) - (b'0' as u64)) as f64) * dec;
try!(self.bump());
}
_ => break,
}
}
Ok(res)
}
fn parse_exponent(&mut self, mut res: f64) -> Result<f64, Error> {
try!(self.bump());
let mut exp: u64 = 0;
let mut neg_exp = false;
if self.ch_is(b'+') {
try!(self.bump());
} else if self.ch_is(b'-') {
try!(self.bump());
neg_exp = true;
}
// Make sure a digit follows the exponent place.
match self.ch_or_null() {
b'0' ... b'9' => (),
_ => { return Err(self.error(ErrorCode::InvalidNumber)); }
}
while !self.eof() {
match self.ch_or_null() {
c @ b'0' ... b'9' => {
exp = try_or_invalid!(self, exp.checked_mul(10));
exp = try_or_invalid!(self, exp.checked_add((c as u64) - (b'0' as u64)));
try!(self.bump());
}
_ => break
}
}
let exp = if exp <= i32::MAX as u64 {
10_f64.powi(exp as i32)
} else {
return Err(self.error(ErrorCode::InvalidNumber));
};
if neg_exp {
res /= exp;
} else {
res *= exp;
}
Ok(res)
}
fn decode_hex_escape(&mut self) -> Result<u16, Error> {
let mut i = 0;
let mut n = 0u16;
while i < 4 && !self.eof() {
try!(self.bump());
n = match self.ch_or_null() {
c @ b'0' ... b'9' => n * 16_u16 + ((c as u16) - (b'0' as u16)),
b'a' | b'A' => n * 16_u16 + 10_u16,
b'b' | b'B' => n * 16_u16 + 11_u16,
b'c' | b'C' => n * 16_u16 + 12_u16,
b'd' | b'D' => n * 16_u16 + 13_u16,
b'e' | b'E' => n * 16_u16 + 14_u16,
b'f' | b'F' => n * 16_u16 + 15_u16,
_ => { return Err(self.error(ErrorCode::InvalidEscape)); }
};
i += 1;
}
// Error out if we didn't parse 4 digits.
if i != 4 {
return Err(self.error(ErrorCode::InvalidEscape));
}
Ok(n)
}
fn parse_string(&mut self) -> Result<(), Error> {
self.str_buf.clear();
loop {
let ch = match try!(self.next_char()) {
Some(ch) => ch,
None => { return Err(self.error(ErrorCode::EOFWhileParsingString)); }
};
match ch {
b'"' => {
try!(self.bump());
return Ok(());
}
b'\\' => {
let ch = match try!(self.next_char()) {
Some(ch) => ch,
None => { return Err(self.error(ErrorCode::EOFWhileParsingString)); }
};
match ch {
b'"' => self.str_buf.push(b'"'),
b'\\' => self.str_buf.push(b'\\'),
b'/' => self.str_buf.push(b'/'),
b'b' => self.str_buf.push(b'\x08'),
b'f' => self.str_buf.push(b'\x0c'),
b'n' => self.str_buf.push(b'\n'),
b'r' => self.str_buf.push(b'\r'),
b't' => self.str_buf.push(b'\t'),
b'u' => {
let c = match try!(self.decode_hex_escape()) {
0xDC00 ... 0xDFFF => {
return Err(self.error(ErrorCode::LoneLeadingSurrogateInHexEscape));
}
// Non-BMP characters are encoded as a sequence of
// two hex escapes, representing UTF-16 surrogates.
n1 @ 0xD800 ... 0xDBFF => {
match (try!(self.next_char()), try!(self.next_char())) {
(Some(b'\\'), Some(b'u')) => (),
_ => {
return Err(self.error(ErrorCode::UnexpectedEndOfHexEscape));
}
}
let n2 = try!(self.decode_hex_escape());
if n2 < 0xDC00 || n2 > 0xDFFF {
return Err(self.error(ErrorCode::LoneLeadingSurrogateInHexEscape));
}
let n = (((n1 - 0xD800) as u32) << 10 |
(n2 - 0xDC00) as u32) + 0x1_0000;
match char::from_u32(n as u32) {
Some(c) => c,
None => {
return Err(self.error(ErrorCode::InvalidUnicodeCodePoint));
}
}
}
n => {
match char::from_u32(n as u32) {
Some(c) => c,
None => {
return Err(self.error(ErrorCode::InvalidUnicodeCodePoint));
}
}
}
};
// FIXME: this allocation is required in order to be compatible with stable
// rust, which doesn't support encoding a `char` into a stack buffer.
let buf = c.to_string();
self.str_buf.extend(buf.bytes());
}
_ => {
return Err(self.error(ErrorCode::InvalidEscape));
}
}
}
ch => {
self.str_buf.push(ch);
}
}
}
}
fn parse_object_colon(&mut self) -> Result<(), Error> {
try!(self.parse_whitespace());
if self.ch_is(b':') {
try!(self.bump());
Ok(())
} else if self.eof() {
Err(self.error(ErrorCode::EOFWhileParsingObject))
} else {
Err(self.error(ErrorCode::ExpectedColon))
}
}
}
impl<Iter> de::Deserializer for Deserializer<Iter>
where Iter: Iterator<Item=io::Result<u8>>,
{
type Error = Error;
#[inline]
fn visit<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
self.parse_value(visitor)
}
#[inline]
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
try!(self.parse_whitespace());
if self.eof() {
return Err(self.error(ErrorCode::EOFWhileParsingValue));
}
if self.ch_is(b'n') {
try!(self.parse_ident(b"ull"));
visitor.visit_none()
} else {
visitor.visit_some(self)
}
}
#[inline]
fn visit_enum<V>(&mut self, _name: &str, mut visitor: V) -> Result<V::Value, Error>
where V: de::EnumVisitor,
{
try!(self.parse_whitespace());
if self.ch_is(b'{') {
try!(self.bump());
try!(self.parse_whitespace());
let value = {
try!(visitor.visit(&mut *self))
};
try!(self.parse_whitespace());
if self.ch_is(b'}') {
try!(self.bump());
Ok(value)
} else {
Err(self.error(ErrorCode::ExpectedSomeValue))
}
} else {
Err(self.error(ErrorCode::ExpectedSomeValue))
}
}
#[inline]
fn format() -> &'static str {
"json"
}
}
struct SeqVisitor<'a, Iter: 'a + Iterator<Item=io::Result<u8>>> {
de: &'a mut Deserializer<Iter>,
first: bool,
}
impl<'a, Iter: Iterator<Item=io::Result<u8>>> SeqVisitor<'a, Iter> {
fn new(de: &'a mut Deserializer<Iter>) -> Self {
SeqVisitor {
de: de,
first: true,
}
}
}
impl<'a, Iter> de::SeqVisitor for SeqVisitor<'a, Iter>
where Iter: Iterator<Item=io::Result<u8>>,
{
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: de::Deserialize,
{
try!(self.de.parse_whitespace());
if self.de.ch_is(b']') {
return Ok(None);
}
if self.first {
self.first = false;
} else {
if self.de.ch_is(b',') {
try!(self.de.bump());
} else if self.de.eof() {
return Err(self.de.error(ErrorCode::EOFWhileParsingList));
} else {
return Err(self.de.error(ErrorCode::ExpectedListCommaOrEnd));
}
}
let value = try!(de::Deserialize::deserialize(self.de));
Ok(Some(value))
}
fn end(&mut self) -> Result<(), Error> {
try!(self.de.parse_whitespace());
if self.de.ch_is(b']') {
self.de.bump()
} else if self.de.eof() {
Err(self.de.error(ErrorCode::EOFWhileParsingList))
} else {
Err(self.de.error(ErrorCode::TrailingCharacters))
}
}
}
struct MapVisitor<'a, Iter: 'a + Iterator<Item=io::Result<u8>>> {
de: &'a mut Deserializer<Iter>,
first: bool,
}
impl<'a, Iter: Iterator<Item=io::Result<u8>>> MapVisitor<'a, Iter> {
fn new(de: &'a mut Deserializer<Iter>) -> Self {
MapVisitor {
de: de,
first: true,
}
}
}
impl<'a, Iter> de::MapVisitor for MapVisitor<'a, Iter>
where Iter: Iterator<Item=io::Result<u8>>
{
type Error = Error;
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
where K: de::Deserialize,
{
try!(self.de.parse_whitespace());
if self.de.ch_is(b'}') {
return Ok(None);
}
if self.first {
self.first = false;
} else {
if self.de.ch_is(b',') {
try!(self.de.bump());
try!(self.de.parse_whitespace());
} else if self.de.eof() {
return Err(self.de.error(ErrorCode::EOFWhileParsingObject));
} else {
return Err(self.de.error(ErrorCode::ExpectedObjectCommaOrEnd));
}
}
if self.de.eof() {
return Err(self.de.error(ErrorCode::EOFWhileParsingValue));
}
if !self.de.ch_is(b'"') {
return Err(self.de.error(ErrorCode::KeyMustBeAString));
}
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
fn visit_value<V>(&mut self) -> Result<V, Error>
where V: de::Deserialize,
{
try!(self.de.parse_object_colon());
Ok(try!(de::Deserialize::deserialize(self.de)))
}
fn end(&mut self) -> Result<(), Error> {
try!(self.de.parse_whitespace());
if self.de.ch_is(b'}') {
try!(self.de.bump());
Ok(())
} else if self.de.eof() {
Err(self.de.error(ErrorCode::EOFWhileParsingObject))
} else {
Err(self.de.error(ErrorCode::TrailingCharacters))
}
}
fn missing_field<V>(&mut self, _field: &'static str) -> Result<V, Error>
where V: de::Deserialize,
{
let mut de = de::value::ValueDeserializer::into_deserializer(());
Ok(try!(de::Deserialize::deserialize(&mut de)))
}
}
impl<Iter> de::VariantVisitor for Deserializer<Iter>
where Iter: Iterator<Item=io::Result<u8>>,
{
type Error = Error;
fn visit_variant<V>(&mut self) -> Result<V, Error>
where V: de::Deserialize
{
de::Deserialize::deserialize(self)
}
fn visit_unit(&mut self) -> Result<(), Error> {
try!(self.parse_object_colon());
de::Deserialize::deserialize(self)
}
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
try!(self.parse_object_colon());
de::Deserializer::visit(self, visitor)
}
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
try!(self.parse_object_colon());
de::Deserializer::visit(self, visitor)
}
}
/// Decodes a json value from a `std::io::Read`.
pub fn from_iter<I, T>(iter: I) -> Result<T, Error>
where I: Iterator<Item=io::Result<u8>>,
T: de::Deserialize,
{
let mut de = try!(Deserializer::new(iter));
let value = try!(de::Deserialize::deserialize(&mut de));
// Make sure the whole stream has been consumed.
try!(de.end());
Ok(value)
}
/// Decodes a json value from a `std::io::Read`.
pub fn from_reader<R, T>(rdr: R) -> Result<T, Error>
where R: io::Read,
T: de::Deserialize,
{
from_iter(rdr.bytes())
}
/// Decodes a json value from a `&str`.
pub fn from_slice<T>(v: &[u8]) -> Result<T, Error>
where T: de::Deserialize
{
from_iter(v.iter().map(|byte| Ok(*byte)))
}
/// Decodes a json value from a `&str`.
pub fn from_str<T>(s: &str) -> Result<T, Error>
where T: de::Deserialize
{
from_slice(s.as_bytes())
}
-185
View File
@@ -1,185 +0,0 @@
use std::error;
use std::fmt;
use std::io;
use de;
/// The errors that can arise while parsing a JSON stream.
#[derive(Clone, PartialEq)]
pub enum ErrorCode {
EOFWhileParsingList,
EOFWhileParsingObject,
EOFWhileParsingString,
EOFWhileParsingValue,
ExpectedColon,
ExpectedConversion,
ExpectedEnumEnd,
ExpectedEnumEndToken,
ExpectedEnumMapStart,
ExpectedEnumToken,
ExpectedEnumVariantString,
ExpectedListCommaOrEnd,
ExpectedName,
ExpectedObjectCommaOrEnd,
ExpectedSomeIdent,
ExpectedSomeValue,
InvalidEscape,
InvalidNumber,
InvalidUnicodeCodePoint,
KeyMustBeAString,
LoneLeadingSurrogateInHexEscape,
UnknownField(String),
MissingField(&'static str),
NotFourDigit,
NotUtf8,
TrailingCharacters,
UnexpectedEndOfHexEscape,
UnknownVariant,
UnrecognizedHex,
}
impl fmt::Debug for ErrorCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use std::fmt::Debug;
match *self {
//ErrorCode::ConversionError(ref token) => write!(f, "failed to convert {}", token),
ErrorCode::EOFWhileParsingList => "EOF While parsing list".fmt(f),
ErrorCode::EOFWhileParsingObject => "EOF While parsing object".fmt(f),
ErrorCode::EOFWhileParsingString => "EOF While parsing string".fmt(f),
ErrorCode::EOFWhileParsingValue => "EOF While parsing value".fmt(f),
ErrorCode::ExpectedColon => "expected `:`".fmt(f),
ErrorCode::ExpectedConversion => "expected conversion".fmt(f),
ErrorCode::ExpectedEnumEnd => "expected enum end".fmt(f),
ErrorCode::ExpectedEnumEndToken => "expected enum map end".fmt(f),
ErrorCode::ExpectedEnumMapStart => "expected enum map start".fmt(f),
ErrorCode::ExpectedEnumToken => "expected enum token".fmt(f),
ErrorCode::ExpectedEnumVariantString => "expected variant".fmt(f),
ErrorCode::ExpectedListCommaOrEnd => "expected `,` or `]`".fmt(f),
ErrorCode::ExpectedName => "expected name".fmt(f),
ErrorCode::ExpectedObjectCommaOrEnd => "expected `,` or `}`".fmt(f),
ErrorCode::ExpectedSomeIdent => "expected ident".fmt(f),
ErrorCode::ExpectedSomeValue => "expected value".fmt(f),
//ErrorCode::ExpectedTokens(ref token, tokens) => write!(f, "expected {}, found {}", tokens, token),
ErrorCode::InvalidEscape => "invalid escape".fmt(f),
ErrorCode::InvalidNumber => "invalid number".fmt(f),
ErrorCode::InvalidUnicodeCodePoint => "invalid unicode code point".fmt(f),
ErrorCode::KeyMustBeAString => "key must be a string".fmt(f),
ErrorCode::LoneLeadingSurrogateInHexEscape => "lone leading surrogate in hex escape".fmt(f),
ErrorCode::UnknownField(ref field) => write!(f, "unknown field \"{}\"", field),
ErrorCode::MissingField(ref field) => write!(f, "missing field \"{}\"", field),
ErrorCode::NotFourDigit => "invalid \\u escape (not four digits)".fmt(f),
ErrorCode::NotUtf8 => "contents not utf-8".fmt(f),
ErrorCode::TrailingCharacters => "trailing characters".fmt(f),
ErrorCode::UnexpectedEndOfHexEscape => "unexpected end of hex escape".fmt(f),
//ErrorCode::UnexpectedName(ref name) => write!(f, "unexpected name {}", name),
ErrorCode::UnknownVariant => "unknown variant".fmt(f),
ErrorCode::UnrecognizedHex => "invalid \\u escape (unrecognized hex)".fmt(f),
}
}
}
#[derive(Debug)]
pub enum Error {
/// msg, line, col
SyntaxError(ErrorCode, usize, usize),
IoError(io::Error),
/*
ExpectedError(String, String),
*/
MissingFieldError(&'static str),
/*
UnknownVariantError(String),
*/
}
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::SyntaxError(..) => "syntax error",
Error::IoError(ref error) => error::Error::description(error),
/*
Error::ExpectedError(ref expected, _) => &expected,
*/
Error::MissingFieldError(_) => "missing field",
/*
Error::UnknownVariantError(_) => "unknown variant",
*/
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
Error::IoError(ref error) => Some(error),
_ => None,
}
}
}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::SyntaxError(ref code, line, col) => {
write!(fmt, "{:?} at line {} column {}", code, line, col)
}
Error::IoError(ref error) => fmt::Display::fmt(error, fmt),
/*
Error::ExpectedError(ref expected, ref found) => {
Some(format!("expected {}, found {}", expected, found))
}
*/
Error::MissingFieldError(ref field) => {
write!(fmt, "missing field {}", field)
}
/*
Error::UnknownVariantError(ref variant) => {
Some(format!("unknown variant {}", variant))
}
*/
}
}
}
impl From<io::Error> for Error {
fn from(error: io::Error) -> Error {
Error::IoError(error)
}
}
impl From<de::value::Error> for Error {
fn from(error: de::value::Error) -> Error {
match error {
de::value::Error::SyntaxError => {
de::Error::syntax_error()
}
de::value::Error::EndOfStreamError => {
de::Error::end_of_stream_error()
}
de::value::Error::UnknownFieldError(field) => {
Error::SyntaxError(ErrorCode::UnknownField(field), 0, 0)
}
de::value::Error::MissingFieldError(field) => {
de::Error::missing_field_error(field)
}
}
}
}
impl de::Error for Error {
fn syntax_error() -> Error {
Error::SyntaxError(ErrorCode::ExpectedSomeValue, 0, 0)
}
fn end_of_stream_error() -> Error {
Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 0, 0)
}
fn unknown_field_error(field: &str) -> Error {
Error::SyntaxError(ErrorCode::UnknownField(field.to_string()), 0, 0)
}
fn missing_field_error(field: &'static str) -> Error {
Error::MissingFieldError(field)
}
}
-113
View File
@@ -1,113 +0,0 @@
//! JSON and serialization
//!
//! # What is JSON?
//!
//! JSON (JavaScript Object Notation) is a way to write data in JavaScript. Like XML, it allows to
//! encode structured data in a text format that can be easily read by humans. Its simple syntax
//! and native compatibility with JavaScript have made it a widely used format.
//!
//! Data types that can be encoded are JavaScript types (see the `serde::json:Value` enum for more
//! details):
//!
//! * `Boolean`: equivalent to rust's `bool`
//! * `I64`: equivalent to rust's `i64`
//! * `U64`: equivalent to rust's `u64`
//! * `F64`: equivalent to rust's `i64`
//! * `String`: equivalent to rust's `String`
//! * `Array`: equivalent to rust's `Vec<T>`, but also allowing objects of different types in the
//! same array
//! * `Object`: equivalent to rust's `BTreeMap<String, serde::json::Value>`
//! * `Null`
//!
//! An object is a series of string keys mapping to values, in `"key": value` format. Arrays are
//! enclosed in square brackets ([ ... ]) and objects in curly brackets ({ ... }). A simple JSON
//! document encoding a person, his/her age, address and phone numbers could look like
//!
//! ```ignore
//! {
//! "FirstName": "John",
//! "LastName": "Doe",
//! "Age": 43,
//! "Address": {
//! "Street": "Downing Street 10",
//! "City": "London",
//! "Country": "Great Britain"
//! },
//! "PhoneNumbers": [
//! "+44 1234567",
//! "+44 2345678"
//! ]
//! }
//! ```
//!
//! # Type-based Serialization and Deserialization
//!
//! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
//! from JSON via the serialization API. To be able to serialize a piece of data, it must implement
//! the `serde::Serialize` trait. To be able to deserialize a piece of data, it must implement the
//! `serde::Deserialize` trait. Serde provides provides an annotation to automatically generate
//! the code for these traits: `#[derive(Serialize, Deserialize)]`.
//!
//! The JSON API also provides an enum `serde::json::Value` and a method `to_value` to serialize
//! objects. A `serde::json::Value` value can be serialized as a string or buffer using the
//! functions described above. You can also use the `json::Serializer` object, which implements the
//! `Serializer` trait.
//!
//! # Examples of use
//!
//! ## Parsing a `str` to `Value` and reading the result
//!
//! ```rust
//! //#![feature(custom_derive, plugin)]
//! //#![plugin(serde_macros)]
//!
//! extern crate serde;
//!
//! use serde::json::{self, Value};
//!
//! fn main() {
//! let data: Value = json::from_str("{\"foo\": 13, \"bar\": \"baz\"}").unwrap();
//! println!("data: {:?}", data);
//! // data: {"bar":"baz","foo":13}
//! println!("object? {}", data.is_object());
//! // object? true
//!
//! let obj = data.as_object().unwrap();
//! let foo = obj.get("foo").unwrap();
//!
//! println!("array? {:?}", foo.as_array());
//! // array? None
//! println!("u64? {:?}", foo.as_u64());
//! // u64? Some(13u64)
//!
//! for (key, value) in obj.iter() {
//! println!("{}: {}", key, match *value {
//! Value::U64(v) => format!("{} (u64)", v),
//! Value::String(ref v) => format!("{} (string)", v),
//! _ => format!("other")
//! });
//! }
//! // bar: baz (string)
//! // foo: 13 (u64)
//! }
//! ```
pub use self::de::{Deserializer, from_str};
pub use self::error::{Error, ErrorCode};
pub use self::ser::{
Serializer,
to_writer,
to_writer_pretty,
to_vec,
to_vec_pretty,
to_string,
to_string_pretty,
escape_str,
};
pub use self::value::{Value, to_value, from_value};
pub mod builder;
pub mod de;
pub mod error;
pub mod ser;
pub mod value;
-524
View File
@@ -1,524 +0,0 @@
use std::io;
use std::num::FpCategory;
use std::string::FromUtf8Error;
use ser;
/// A structure for implementing serialization to JSON.
pub struct Serializer<W, F=CompactFormatter> {
writer: W,
formatter: F,
/// `first` is used to signify if we should print a comma when we are walking through a
/// sequence.
first: bool,
}
impl<W> Serializer<W>
where W: io::Write,
{
/// Creates a new JSON serializer.
#[inline]
pub fn new(writer: W) -> Self {
Serializer::with_formatter(writer, CompactFormatter)
}
}
impl<'a, W> Serializer<W, PrettyFormatter<'a>>
where W: io::Write,
{
/// Creates a new JSON pretty print serializer.
#[inline]
pub fn pretty(writer: W) -> Self {
Serializer::with_formatter(writer, PrettyFormatter::new())
}
}
impl<W, F> Serializer<W, F>
where W: io::Write,
F: Formatter,
{
/// Creates a new JSON visitor whose output will be written to the writer
/// specified.
#[inline]
pub fn with_formatter(writer: W, formatter: F) -> Self {
Serializer {
writer: writer,
formatter: formatter,
first: false,
}
}
/// Unwrap the `Writer` from the `Serializer`.
#[inline]
pub fn into_inner(self) -> W {
self.writer
}
}
impl<W, F> ser::Serializer for Serializer<W, F>
where W: io::Write,
F: Formatter,
{
type Error = io::Error;
#[inline]
fn visit_bool(&mut self, value: bool) -> io::Result<()> {
if value {
self.writer.write_all(b"true")
} else {
self.writer.write_all(b"false")
}
}
#[inline]
fn visit_isize(&mut self, value: isize) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_i8(&mut self, value: i8) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_i16(&mut self, value: i16) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_i32(&mut self, value: i32) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_i64(&mut self, value: i64) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_usize(&mut self, value: usize) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_u8(&mut self, value: u8) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_u16(&mut self, value: u16) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_u32(&mut self, value: u32) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_u64(&mut self, value: u64) -> io::Result<()> {
write!(&mut self.writer, "{}", value)
}
#[inline]
fn visit_f32(&mut self, value: f32) -> io::Result<()> {
fmt_f32_or_null(&mut self.writer, value)
}
#[inline]
fn visit_f64(&mut self, value: f64) -> io::Result<()> {
fmt_f64_or_null(&mut self.writer, value)
}
#[inline]
fn visit_char(&mut self, value: char) -> io::Result<()> {
escape_char(&mut self.writer, value)
}
#[inline]
fn visit_str(&mut self, value: &str) -> io::Result<()> {
escape_str(&mut self.writer, value)
}
#[inline]
fn visit_none(&mut self) -> io::Result<()> {
self.visit_unit()
}
#[inline]
fn visit_some<V>(&mut self, value: V) -> io::Result<()>
where V: ser::Serialize
{
value.serialize(self)
}
#[inline]
fn visit_unit(&mut self) -> io::Result<()> {
self.writer.write_all(b"null")
}
#[inline]
fn visit_enum_unit(&mut self, _name: &str, variant: &str) -> io::Result<()> {
try!(self.formatter.open(&mut self.writer, b'{'));
try!(self.formatter.comma(&mut self.writer, true));
try!(self.visit_str(variant));
try!(self.formatter.colon(&mut self.writer));
try!(self.writer.write_all(b"[]"));
self.formatter.close(&mut self.writer, b'}')
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> io::Result<()>
where V: ser::SeqVisitor,
{
match visitor.len() {
Some(len) if len == 0 => {
self.writer.write_all(b"[]")
}
_ => {
try!(self.formatter.open(&mut self.writer, b'['));
self.first = true;
while let Some(()) = try!(visitor.visit(self)) { }
self.formatter.close(&mut self.writer, b']')
}
}
}
#[inline]
fn visit_enum_seq<V>(&mut self, _name: &str, variant: &str, visitor: V) -> io::Result<()>
where V: ser::SeqVisitor,
{
try!(self.formatter.open(&mut self.writer, b'{'));
try!(self.formatter.comma(&mut self.writer, true));
try!(self.visit_str(variant));
try!(self.formatter.colon(&mut self.writer));
try!(self.visit_seq(visitor));
self.formatter.close(&mut self.writer, b'}')
}
#[inline]
fn visit_seq_elt<T>(&mut self, value: T) -> io::Result<()>
where T: ser::Serialize,
{
try!(self.formatter.comma(&mut self.writer, self.first));
self.first = false;
value.serialize(self)
}
#[inline]
fn visit_map<V>(&mut self, mut visitor: V) -> io::Result<()>
where V: ser::MapVisitor,
{
match visitor.len() {
Some(len) if len == 0 => {
self.writer.write_all(b"{}")
}
_ => {
try!(self.formatter.open(&mut self.writer, b'{'));
self.first = true;
while let Some(()) = try!(visitor.visit(self)) { }
self.formatter.close(&mut self.writer, b'}')
}
}
}
#[inline]
fn visit_enum_map<V>(&mut self, _name: &str, variant: &str, visitor: V) -> io::Result<()>
where V: ser::MapVisitor,
{
try!(self.formatter.open(&mut self.writer, b'{'));
try!(self.formatter.comma(&mut self.writer, true));
try!(self.visit_str(variant));
try!(self.formatter.colon(&mut self.writer));
try!(self.visit_map(visitor));
self.formatter.close(&mut self.writer, b'}')
}
#[inline]
fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> io::Result<()>
where K: ser::Serialize,
V: ser::Serialize,
{
try!(self.formatter.comma(&mut self.writer, self.first));
self.first = false;
try!(key.serialize(self));
try!(self.formatter.colon(&mut self.writer));
value.serialize(self)
}
#[inline]
fn format() -> &'static str {
"json"
}
}
pub trait Formatter {
fn open<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
where W: io::Write;
fn comma<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
where W: io::Write;
fn colon<W>(&mut self, writer: &mut W) -> io::Result<()>
where W: io::Write;
fn close<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
where W: io::Write;
}
pub struct CompactFormatter;
impl Formatter for CompactFormatter {
fn open<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
where W: io::Write,
{
writer.write_all(&[ch])
}
fn comma<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
where W: io::Write,
{
if first {
Ok(())
} else {
writer.write_all(b",")
}
}
fn colon<W>(&mut self, writer: &mut W) -> io::Result<()>
where W: io::Write,
{
writer.write_all(b":")
}
fn close<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
where W: io::Write,
{
writer.write_all(&[ch])
}
}
pub struct PrettyFormatter<'a> {
current_indent: usize,
indent: &'a [u8],
}
impl<'a> PrettyFormatter<'a> {
fn new() -> Self {
PrettyFormatter::with_indent(b" ")
}
fn with_indent(indent: &'a [u8]) -> Self {
PrettyFormatter {
current_indent: 0,
indent: indent,
}
}
}
impl<'a> Formatter for PrettyFormatter<'a> {
fn open<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
where W: io::Write,
{
self.current_indent += 1;
writer.write_all(&[ch])
}
fn comma<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
where W: io::Write,
{
if first {
try!(writer.write_all(b"\n"));
} else {
try!(writer.write_all(b",\n"));
}
indent(writer, self.current_indent, self.indent)
}
fn colon<W>(&mut self, writer: &mut W) -> io::Result<()>
where W: io::Write,
{
writer.write_all(b": ")
}
fn close<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
where W: io::Write,
{
self.current_indent -= 1;
try!(writer.write(b"\n"));
try!(indent(writer, self.current_indent, self.indent));
writer.write_all(&[ch])
}
}
#[inline]
pub fn escape_bytes<W>(wr: &mut W, bytes: &[u8]) -> io::Result<()>
where W: io::Write
{
try!(wr.write_all(b"\""));
let mut start = 0;
for (i, byte) in bytes.iter().enumerate() {
let escaped = match *byte {
b'"' => b"\\\"",
b'\\' => b"\\\\",
b'\x08' => b"\\b",
b'\x0c' => b"\\f",
b'\n' => b"\\n",
b'\r' => b"\\r",
b'\t' => b"\\t",
_ => { continue; }
};
if start < i {
try!(wr.write_all(&bytes[start..i]));
}
try!(wr.write_all(escaped));
start = i + 1;
}
if start != bytes.len() {
try!(wr.write_all(&bytes[start..]));
}
try!(wr.write_all(b"\""));
Ok(())
}
#[inline]
pub fn escape_str<W>(wr: &mut W, value: &str) -> io::Result<()>
where W: io::Write
{
escape_bytes(wr, value.as_bytes())
}
#[inline]
fn escape_char<W>(wr: &mut W, value: char) -> io::Result<()>
where W: io::Write
{
// FIXME: this allocation is required in order to be compatible with stable
// rust, which doesn't support encoding a `char` into a stack buffer.
escape_bytes(wr, value.to_string().as_bytes())
}
fn fmt_f32_or_null<W>(wr: &mut W, value: f32) -> io::Result<()>
where W: io::Write
{
match value.classify() {
FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"),
_ => {
let s = format!("{:?}", value);
try!(wr.write_all(s.as_bytes()));
if !s.contains('.') {
try!(wr.write_all(b".0"))
}
Ok(())
}
}
}
fn fmt_f64_or_null<W>(wr: &mut W, value: f64) -> io::Result<()>
where W: io::Write
{
match value.classify() {
FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"),
_ => {
let s = format!("{:?}", value);
try!(wr.write_all(s.as_bytes()));
if !s.contains('.') {
try!(wr.write_all(b".0"))
}
Ok(())
}
}
}
/// Encode the specified struct into a json `[u8]` writer.
#[inline]
pub fn to_writer<W, T>(writer: &mut W, value: &T) -> io::Result<()>
where W: io::Write,
T: ser::Serialize,
{
let mut ser = Serializer::new(writer);
try!(value.serialize(&mut ser));
Ok(())
}
/// Encode the specified struct into a json `[u8]` writer.
#[inline]
pub fn to_writer_pretty<W, T>(writer: &mut W, value: &T) -> io::Result<()>
where W: io::Write,
T: ser::Serialize,
{
let mut ser = Serializer::pretty(writer);
try!(value.serialize(&mut ser));
Ok(())
}
/// Encode the specified struct into a json `[u8]` buffer.
#[inline]
pub fn to_vec<T>(value: &T) -> Vec<u8>
where T: ser::Serialize,
{
// We are writing to a Vec, which doesn't fail. So we can ignore
// the error.
let mut writer = Vec::with_capacity(128);
to_writer(&mut writer, value).unwrap();
writer
}
/// Encode the specified struct into a json `[u8]` buffer.
#[inline]
pub fn to_vec_pretty<T>(value: &T) -> Vec<u8>
where T: ser::Serialize,
{
// We are writing to a Vec, which doesn't fail. So we can ignore
// the error.
let mut writer = Vec::with_capacity(128);
to_writer_pretty(&mut writer, value).unwrap();
writer
}
/// Encode the specified struct into a json `String` buffer.
#[inline]
pub fn to_string<T>(value: &T) -> Result<String, FromUtf8Error>
where T: ser::Serialize
{
let vec = to_vec(value);
String::from_utf8(vec)
}
/// Encode the specified struct into a json `String` buffer.
#[inline]
pub fn to_string_pretty<T>(value: &T) -> Result<String, FromUtf8Error>
where T: ser::Serialize
{
let vec = to_vec_pretty(value);
String::from_utf8(vec)
}
fn indent<W>(wr: &mut W, n: usize, s: &[u8]) -> io::Result<()>
where W: io::Write,
{
for _ in 0 .. n {
try!(wr.write_all(s));
}
Ok(())
}
-915
View File
@@ -1,915 +0,0 @@
use std::collections::{BTreeMap, btree_map};
use std::fmt;
use std::io;
use std::str;
use std::vec;
use num::NumCast;
use de;
use ser;
use super::error::Error;
#[derive(Clone, PartialEq)]
pub enum Value {
Null,
Bool(bool),
I64(i64),
U64(u64),
F64(f64),
String(String),
Array(Vec<Value>),
Object(BTreeMap<String, Value>),
}
impl Value {
/// If the `Value` is an Object, returns the value associated with the provided key.
/// Otherwise, returns None.
pub fn find<'a>(&'a self, key: &str) -> Option<&'a Value>{
match self {
&Value::Object(ref map) => map.get(key),
_ => None
}
}
/// Attempts to get a nested Value Object for each key in `keys`.
/// If any key is found not to exist, find_path will return None.
/// Otherwise, it will return the `Value` associated with the final key.
pub fn find_path<'a>(&'a self, keys: &[&str]) -> Option<&'a Value>{
let mut target = self;
for key in keys {
match target.find(key) {
Some(t) => { target = t; },
None => return None
}
}
Some(target)
}
/// Looks up a value by path.
///
/// This is a convenience method that splits the path by `'.'`
/// and then feeds the sequence of keys into the `find_path`
/// method.
///
/// ``` ignore
/// let obj: Value = json::from_str(r#"{"x": {"a": 1}}"#).unwrap();
///
/// assert!(obj.lookup("x.a").unwrap() == &Value::U64(1));
/// ```
pub fn lookup<'a>(&'a self, path: &str) -> Option<&'a Value> {
let mut target = self;
for key in path.split('.') {
match target.find(key) {
Some(t) => { target = t; },
None => return None
}
}
Some(target)
}
/// If the `Value` is an Object, performs a depth-first search until
/// a value associated with the provided key is found. If no value is found
/// or the `Value` is not an Object, returns None.
pub fn search<'a>(&'a self, key: &str) -> Option<&'a Value> {
match self {
&Value::Object(ref map) => {
match map.get(key) {
Some(json_value) => Some(json_value),
None => {
for (_, v) in map.iter() {
match v.search(key) {
x if x.is_some() => return x,
_ => ()
}
}
None
}
}
},
_ => None
}
}
/// Returns true if the `Value` is an Object. Returns false otherwise.
pub fn is_object<'a>(&'a self) -> bool {
self.as_object().is_some()
}
/// If the `Value` is an Object, returns the associated BTreeMap.
/// Returns None otherwise.
pub fn as_object<'a>(&'a self) -> Option<&'a BTreeMap<String, Value>> {
match self {
&Value::Object(ref map) => Some(map),
_ => None
}
}
/// If the `Value` is an Object, returns the associated mutable BTreeMap.
/// Returns None otherwise.
pub fn as_object_mut<'a>(&'a mut self) -> Option<&'a mut BTreeMap<String, Value>> {
match self {
&mut Value::Object(ref mut map) => Some(map),
_ => None
}
}
/// Returns true if the `Value` is an Array. Returns false otherwise.
pub fn is_array<'a>(&'a self) -> bool {
self.as_array().is_some()
}
/// If the `Value` is an Array, returns the associated vector.
/// Returns None otherwise.
pub fn as_array<'a>(&'a self) -> Option<&'a Vec<Value>> {
match self {
&Value::Array(ref array) => Some(&*array),
_ => None
}
}
/// If the `Value` is an Array, returns the associated mutable vector.
/// Returns None otherwise.
pub fn as_array_mut<'a>(&'a mut self) -> Option<&'a mut Vec<Value>> {
match self {
&mut Value::Array(ref mut list) => Some(list),
_ => None
}
}
/// Returns true if the `Value` is a String. Returns false otherwise.
pub fn is_string<'a>(&'a self) -> bool {
self.as_string().is_some()
}
/// If the `Value` is a String, returns the associated str.
/// Returns None otherwise.
pub fn as_string<'a>(&'a self) -> Option<&'a str> {
match *self {
Value::String(ref s) => Some(&s),
_ => None
}
}
/// Returns true if the `Value` is a Number. Returns false otherwise.
pub fn is_number(&self) -> bool {
match *self {
Value::I64(_) | Value::U64(_) | Value::F64(_) => true,
_ => false,
}
}
/// Returns true if the `Value` is a i64. Returns false otherwise.
pub fn is_i64(&self) -> bool {
match *self {
Value::I64(_) => true,
_ => false,
}
}
/// Returns true if the `Value` is a u64. Returns false otherwise.
pub fn is_u64(&self) -> bool {
match *self {
Value::U64(_) => true,
_ => false,
}
}
/// Returns true if the `Value` is a f64. Returns false otherwise.
pub fn is_f64(&self) -> bool {
match *self {
Value::F64(_) => true,
_ => false,
}
}
/// If the `Value` is a number, return or cast it to a i64.
/// Returns None otherwise.
pub fn as_i64(&self) -> Option<i64> {
match *self {
Value::I64(n) => Some(n),
Value::U64(n) => NumCast::from(n),
_ => None
}
}
/// If the `Value` is a number, return or cast it to a u64.
/// Returns None otherwise.
pub fn as_u64(&self) -> Option<u64> {
match *self {
Value::I64(n) => NumCast::from(n),
Value::U64(n) => Some(n),
_ => None
}
}
/// If the `Value` is a number, return or cast it to a f64.
/// Returns None otherwise.
pub fn as_f64(&self) -> Option<f64> {
match *self {
Value::I64(n) => NumCast::from(n),
Value::U64(n) => NumCast::from(n),
Value::F64(n) => Some(n),
_ => None
}
}
/// Returns true if the `Value` is a Boolean. Returns false otherwise.
pub fn is_boolean(&self) -> bool {
self.as_boolean().is_some()
}
/// If the `Value` is a Boolean, returns the associated bool.
/// Returns None otherwise.
pub fn as_boolean(&self) -> Option<bool> {
match self {
&Value::Bool(b) => Some(b),
_ => None
}
}
/// Returns true if the `Value` is a Null. Returns false otherwise.
pub fn is_null(&self) -> bool {
self.as_null().is_some()
}
/// If the `Value` is a Null, returns ().
/// Returns None otherwise.
pub fn as_null(&self) -> Option<()> {
match self {
&Value::Null => Some(()),
_ => None
}
}
}
impl ser::Serialize for Value {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: ser::Serializer,
{
match *self {
Value::Null => serializer.visit_unit(),
Value::Bool(v) => serializer.visit_bool(v),
Value::I64(v) => serializer.visit_i64(v),
Value::U64(v) => serializer.visit_u64(v),
Value::F64(v) => serializer.visit_f64(v),
Value::String(ref v) => serializer.visit_str(&v),
Value::Array(ref v) => v.serialize(serializer),
Value::Object(ref v) => v.serialize(serializer),
}
}
}
impl de::Deserialize for Value {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<Value, D::Error>
where D: de::Deserializer,
{
struct ValueVisitor;
impl de::Visitor for ValueVisitor {
type Value = Value;
#[inline]
fn visit_bool<E>(&mut self, value: bool) -> Result<Value, E> {
Ok(Value::Bool(value))
}
#[inline]
fn visit_i64<E>(&mut self, value: i64) -> Result<Value, E> {
if value < 0 {
Ok(Value::I64(value))
} else {
Ok(Value::U64(value as u64))
}
}
#[inline]
fn visit_u64<E>(&mut self, value: u64) -> Result<Value, E> {
Ok(Value::U64(value))
}
#[inline]
fn visit_f64<E>(&mut self, value: f64) -> Result<Value, E> {
Ok(Value::F64(value))
}
#[inline]
fn visit_str<E>(&mut self, value: &str) -> Result<Value, E>
where E: de::Error,
{
self.visit_string(value.to_string())
}
#[inline]
fn visit_string<E>(&mut self, value: String) -> Result<Value, E> {
Ok(Value::String(value))
}
#[inline]
fn visit_none<E>(&mut self) -> Result<Value, E> {
Ok(Value::Null)
}
#[inline]
fn visit_some<D>(&mut self, deserializer: &mut D) -> Result<Value, D::Error>
where D: de::Deserializer,
{
de::Deserialize::deserialize(deserializer)
}
#[inline]
fn visit_unit<E>(&mut self) -> Result<Value, E> {
Ok(Value::Null)
}
#[inline]
fn visit_seq<V>(&mut self, visitor: V) -> Result<Value, V::Error>
where V: de::SeqVisitor,
{
let values = try!(de::impls::VecVisitor::new().visit_seq(visitor));
Ok(Value::Array(values))
}
#[inline]
fn visit_map<V>(&mut self, visitor: V) -> Result<Value, V::Error>
where V: de::MapVisitor,
{
let values = try!(de::impls::BTreeMapVisitor::new().visit_map(visitor));
Ok(Value::Object(values))
}
}
deserializer.visit(ValueVisitor)
}
}
struct WriterFormatter<'a, 'b: 'a> {
inner: &'a mut fmt::Formatter<'b>,
}
impl<'a, 'b> io::Write for WriterFormatter<'a, 'b> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match self.inner.write_str(str::from_utf8(buf).unwrap()) {
Ok(_) => Ok(buf.len()),
Err(_) => Err(io::Error::last_os_error()),
}
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl fmt::Debug for Value {
/// Serializes a json value into a string
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut wr = WriterFormatter { inner: f };
super::ser::to_writer(&mut wr, self).map_err(|_| fmt::Error)
}
}
#[derive(Debug)]
enum State {
Value(Value),
Array(Vec<Value>),
Object(BTreeMap<String, Value>),
}
pub struct Serializer {
state: Vec<State>,
}
impl Serializer {
pub fn new() -> Serializer {
Serializer {
state: Vec::with_capacity(4),
}
}
pub fn unwrap(mut self) -> Value {
match self.state.pop().unwrap() {
State::Value(value) => value,
state => panic!("expected value, found {:?}", state),
}
}
}
impl ser::Serializer for Serializer {
type Error = ();
#[inline]
fn visit_bool(&mut self, value: bool) -> Result<(), ()> {
self.state.push(State::Value(Value::Bool(value)));
Ok(())
}
#[inline]
fn visit_i64(&mut self, value: i64) -> Result<(), ()> {
if value < 0 {
self.state.push(State::Value(Value::I64(value)));
} else {
self.state.push(State::Value(Value::U64(value as u64)));
}
Ok(())
}
#[inline]
fn visit_u64(&mut self, value: u64) -> Result<(), ()> {
self.state.push(State::Value(Value::U64(value)));
Ok(())
}
#[inline]
fn visit_f64(&mut self, value: f64) -> Result<(), ()> {
self.state.push(State::Value(Value::F64(value as f64)));
Ok(())
}
#[inline]
fn visit_char(&mut self, value: char) -> Result<(), ()> {
self.state.push(State::Value(Value::String(value.to_string())));
Ok(())
}
#[inline]
fn visit_str(&mut self, value: &str) -> Result<(), ()> {
self.state.push(State::Value(Value::String(value.to_string())));
Ok(())
}
#[inline]
fn visit_none(&mut self) -> Result<(), ()> {
self.visit_unit()
}
#[inline]
fn visit_some<V>(&mut self, value: V) -> Result<(), ()>
where V: ser::Serialize,
{
value.serialize(self)
}
#[inline]
fn visit_unit(&mut self) -> Result<(), ()> {
self.state.push(State::Value(Value::Null));
Ok(())
}
#[inline]
fn visit_enum_unit(&mut self, _name: &str, variant: &str) -> Result<(), ()> {
let mut values = BTreeMap::new();
values.insert(variant.to_string(), Value::Array(vec![]));
self.state.push(State::Value(Value::Object(values)));
Ok(())
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<(), ()>
where V: ser::SeqVisitor,
{
let len = visitor.len().unwrap_or(0);
let values = Vec::with_capacity(len);
self.state.push(State::Array(values));
while let Some(()) = try!(visitor.visit(self)) { }
let values = match self.state.pop().unwrap() {
State::Array(values) => values,
state => panic!("Expected array, found {:?}", state),
};
self.state.push(State::Value(Value::Array(values)));
Ok(())
}
#[inline]
fn visit_enum_seq<V>(&mut self, _name: &str, variant: &str, visitor: V) -> Result<(), ()>
where V: ser::SeqVisitor,
{
try!(self.visit_seq(visitor));
let value = match self.state.pop().unwrap() {
State::Value(value) => value,
state => panic!("expected value, found {:?}", state),
};
let mut object = BTreeMap::new();
object.insert(variant.to_string(), value);
self.state.push(State::Value(Value::Object(object)));
Ok(())
}
#[inline]
fn visit_seq_elt<T>(&mut self, value: T) -> Result<(), ()>
where T: ser::Serialize,
{
try!(value.serialize(self));
let value = match self.state.pop().unwrap() {
State::Value(value) => value,
state => panic!("expected value, found {:?}", state),
};
match *self.state.last_mut().unwrap() {
State::Array(ref mut values) => { values.push(value); }
ref state => panic!("expected array, found {:?}", state),
}
Ok(())
}
#[inline]
fn visit_map<V>(&mut self, mut visitor: V) -> Result<(), ()>
where V: ser::MapVisitor,
{
let values = BTreeMap::new();
self.state.push(State::Object(values));
while let Some(()) = try!(visitor.visit(self)) { }
let values = match self.state.pop().unwrap() {
State::Object(values) => values,
state => panic!("expected object, found {:?}", state),
};
self.state.push(State::Value(Value::Object(values)));
Ok(())
}
#[inline]
fn visit_enum_map<V>(&mut self, _name: &str, variant: &str, visitor: V) -> Result<(), ()>
where V: ser::MapVisitor,
{
try!(self.visit_map(visitor));
let value = match self.state.pop().unwrap() {
State::Value(value) => value,
state => panic!("expected value, found {:?}", state),
};
let mut object = BTreeMap::new();
object.insert(variant.to_string(), value);
self.state.push(State::Value(Value::Object(object)));
Ok(())
}
#[inline]
fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), ()>
where K: ser::Serialize,
V: ser::Serialize,
{
try!(key.serialize(self));
let key = match self.state.pop().unwrap() {
State::Value(Value::String(value)) => value,
state => panic!("expected key, found {:?}", state),
};
try!(value.serialize(self));
let value = match self.state.pop().unwrap() {
State::Value(value) => value,
state => panic!("expected value, found {:?}", state),
};
match *self.state.last_mut().unwrap() {
State::Object(ref mut values) => { values.insert(key, value); }
ref state => panic!("expected object, found {:?}", state),
}
Ok(())
}
#[inline]
fn format() -> &'static str {
"json"
}
}
pub struct Deserializer {
value: Option<Value>,
}
impl Deserializer {
/// Creates a new deserializer instance for deserializing the specified JSON value.
pub fn new(value: Value) -> Deserializer {
Deserializer {
value: Some(value),
}
}
}
impl de::Deserializer for Deserializer {
type Error = Error;
#[inline]
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
let value = match self.value.take() {
Some(value) => value,
None => { return Err(de::Error::end_of_stream_error()); }
};
match value {
Value::Null => visitor.visit_unit(),
Value::Bool(v) => visitor.visit_bool(v),
Value::I64(v) => visitor.visit_i64(v),
Value::U64(v) => visitor.visit_u64(v),
Value::F64(v) => visitor.visit_f64(v),
Value::String(v) => visitor.visit_string(v),
Value::Array(v) => {
let len = v.len();
visitor.visit_seq(SeqDeserializer {
de: self,
iter: v.into_iter(),
len: len,
})
}
Value::Object(v) => {
let len = v.len();
visitor.visit_map(MapDeserializer {
de: self,
iter: v.into_iter(),
value: None,
len: len,
})
}
}
}
#[inline]
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.value {
Some(Value::Null) => visitor.visit_none(),
Some(_) => visitor.visit_some(self),
None => Err(de::Error::end_of_stream_error()),
}
}
#[inline]
fn visit_enum<V>(&mut self, _name: &str, mut visitor: V) -> Result<V::Value, Error>
where V: de::EnumVisitor,
{
let value = match self.value.take() {
Some(Value::Object(value)) => value,
Some(_) => { return Err(de::Error::syntax_error()); }
None => { return Err(de::Error::end_of_stream_error()); }
};
let mut iter = value.into_iter();
let value = match iter.next() {
Some((variant, Value::Array(fields))) => {
self.value = Some(Value::String(variant));
let len = fields.len();
try!(visitor.visit(SeqDeserializer {
de: self,
iter: fields.into_iter(),
len: len,
}))
}
Some((variant, Value::Object(fields))) => {
let len = fields.len();
try!(visitor.visit(MapDeserializer {
de: self,
iter: fields.into_iter(),
value: Some(Value::String(variant)),
len: len,
}))
}
Some(_) => { return Err(de::Error::syntax_error()); }
None => { return Err(de::Error::syntax_error()); }
};
match iter.next() {
Some(_) => Err(de::Error::syntax_error()),
None => Ok(value)
}
}
#[inline]
fn format() -> &'static str {
"json"
}
}
struct SeqDeserializer<'a> {
de: &'a mut Deserializer,
iter: vec::IntoIter<Value>,
len: usize,
}
impl<'a> de::Deserializer for SeqDeserializer<'a> {
type Error = Error;
#[inline]
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
if self.len == 0 {
visitor.visit_unit()
} else {
visitor.visit_seq(self)
}
}
}
impl<'a> de::SeqVisitor for SeqDeserializer<'a> {
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: de::Deserialize
{
match self.iter.next() {
Some(value) => {
self.len -= 1;
self.de.value = Some(value);
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
None => Ok(None),
}
}
fn end(&mut self) -> Result<(), Error> {
if self.len == 0 {
Ok(())
} else {
Err(de::Error::end_of_stream_error())
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl<'a> de::VariantVisitor for SeqDeserializer<'a> {
type Error = Error;
fn visit_variant<V>(&mut self) -> Result<V, Error>
where V: de::Deserialize,
{
de::Deserialize::deserialize(self.de)
}
fn visit_unit(&mut self) -> Result<(), Error>
{
de::Deserialize::deserialize(self)
}
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
de::Deserializer::visit(self, visitor)
}
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
de::Deserializer::visit(self, visitor)
}
}
struct MapDeserializer<'a> {
de: &'a mut Deserializer,
iter: btree_map::IntoIter<String, Value>,
value: Option<Value>,
len: usize,
}
impl<'a> de::MapVisitor for MapDeserializer<'a> {
type Error = Error;
fn visit_key<T>(&mut self) -> Result<Option<T>, Error>
where T: de::Deserialize
{
match self.iter.next() {
Some((key, value)) => {
self.len -= 1;
self.value = Some(value);
self.de.value = Some(Value::String(key));
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
None => Ok(None),
}
}
fn visit_value<T>(&mut self) -> Result<T, Error>
where T: de::Deserialize
{
let value = self.value.take().unwrap();
self.de.value = Some(value);
Ok(try!(de::Deserialize::deserialize(self.de)))
}
fn end(&mut self) -> Result<(), Error> {
if self.len == 0 {
Ok(())
} else {
Err(de::Error::end_of_stream_error())
}
}
fn missing_field<V>(&mut self, _field: &'static str) -> Result<V, Error>
where V: de::Deserialize,
{
// See if the type can deserialize from a unit.
struct UnitDeserializer;
impl de::Deserializer for UnitDeserializer {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_unit()
}
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_none()
}
}
Ok(try!(de::Deserialize::deserialize(&mut UnitDeserializer)))
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl<'a> de::Deserializer for MapDeserializer<'a> {
type Error = Error;
#[inline]
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
println!("MapDeserializer!");
visitor.visit_map(self)
}
}
impl<'a> de::VariantVisitor for MapDeserializer<'a> {
type Error = Error;
fn visit_variant<V>(&mut self) -> Result<V, Error>
where V: de::Deserialize,
{
self.de.value = self.value.take();
de::Deserialize::deserialize(self.de)
}
fn visit_unit(&mut self) -> Result<(), Error> {
de::Deserialize::deserialize(self)
}
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
de::Deserializer::visit(self, visitor)
}
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
de::Deserializer::visit(self, visitor)
}
}
/// Shortcut function to encode a `T` into a JSON `Value`
pub fn to_value<T>(value: &T) -> Value
where T: ser::Serialize
{
let mut ser = Serializer::new();
value.serialize(&mut ser).ok().unwrap();
ser.unwrap()
}
/// Shortcut function to decode a JSON `Value` into a `T`
pub fn from_value<T>(value: Value) -> Result<T, Error>
where T: de::Deserialize
{
let mut de = Deserializer::new(value);
de::Deserialize::deserialize(&mut de)
}
+10 -4
View File
@@ -5,10 +5,17 @@
//! handshake protocol between serializers and serializees can be completely optimized away,
//! leaving serde to perform roughly the same speed as a hand written serializer for a specific
//! type.
#![doc(html_root_url="http://erickt.github.io/rust-serde")]
#![cfg_attr(feature = "nightly", feature(collections, core, enumset, nonzero, step_trait, vecmap, zero_one))]
//!
//! For a detailed tutorial on the different ways to use serde please check out the
//! [github repository](https://github.com/serde-rs/serde)
extern crate num;
#![doc(html_root_url="https://serde-rs.github.io/serde/serde")]
#![cfg_attr(feature = "nightly", feature(collections, enumset, nonzero, plugin, step_trait,
zero_one))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", allow(linkedlist))]
#![deny(missing_docs)]
#[cfg(feature = "nightly")]
extern crate collections;
@@ -22,5 +29,4 @@ pub use de::{Deserialize, Deserializer, Error};
pub mod bytes;
pub mod de;
pub mod iter;
pub mod json;
pub mod ser;
+189 -130
View File
@@ -1,3 +1,5 @@
//! Implementations for all of Rust's builtin types.
use std::borrow::Cow;
use std::collections::{
BinaryHeap,
@@ -10,12 +12,10 @@ use std::collections::{
};
#[cfg(feature = "nightly")]
use collections::enum_set::{CLike, EnumSet};
#[cfg(feature = "nightly")]
use std::collections::vec_map::VecMap;
use std::hash::Hash;
#[cfg(feature = "nightly")]
use std::iter;
use std::marker::PhantomData;
use std::net;
#[cfg(feature = "nightly")]
use std::num;
#[cfg(feature = "nightly")]
@@ -23,11 +23,13 @@ use std::ops;
use std::path;
use std::rc::Rc;
use std::sync::Arc;
use std::marker::PhantomData;
#[cfg(feature = "nightly")]
use core::nonzero::{NonZero, Zeroable};
use super::{
Error,
Serialize,
Serializer,
SeqVisitor,
@@ -49,20 +51,20 @@ macro_rules! impl_visit {
}
}
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_visit!(bool, serialize_bool);
impl_visit!(isize, serialize_isize);
impl_visit!(i8, serialize_i8);
impl_visit!(i16, serialize_i16);
impl_visit!(i32, serialize_i32);
impl_visit!(i64, serialize_i64);
impl_visit!(usize, serialize_usize);
impl_visit!(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);
///////////////////////////////////////////////////////////////////////////////
@@ -71,7 +73,7 @@ impl Serialize for str {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_str(self)
serializer.serialize_str(self)
}
}
@@ -92,14 +94,66 @@ impl<T> Serialize for Option<T> where T: Serialize {
where S: Serializer,
{
match *self {
Some(ref value) => serializer.visit_some(value),
None => serializer.visit_none(),
Some(ref value) => serializer.serialize_some(value),
None => serializer.serialize_none(),
}
}
}
impl<T> SeqVisitor for Option<T> where T: Serialize {
#[inline]
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer,
{
match self.take() {
Some(value) => {
try!(serializer.serialize_seq_elt(value));
Ok(Some(()))
}
None => Ok(None),
}
}
#[inline]
fn len(&self) -> Option<usize> {
Some(if self.is_some() { 1 } else { 0 })
}
}
///////////////////////////////////////////////////////////////////////////////
impl<T> Serialize for PhantomData<T> {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_unit_struct("PhantomData")
}
}
///////////////////////////////////////////////////////////////////////////////
/// A `serde::Visitor` for sequence iterators.
///
/// # Examples
///
/// ```
/// use serde::{Serialize, Serializer};
/// use serde::ser::impls::SeqIteratorVisitor;
///
/// struct Seq(Vec<u32>);
///
/// impl Serialize for Seq {
/// fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
/// where S: Serializer,
/// {
/// ser.serialize_seq(SeqIteratorVisitor::new(
/// self.0.iter(),
/// Some(self.0.len()),
/// ))
/// }
/// }
/// ```
pub struct SeqIteratorVisitor<Iter> {
iter: Iter,
len: Option<usize>,
@@ -108,6 +162,7 @@ pub struct SeqIteratorVisitor<Iter> {
impl<T, Iter> SeqIteratorVisitor<Iter>
where Iter: Iterator<Item=T>
{
/// Construct a new `SeqIteratorVisitor<Iter>`.
#[inline]
pub fn new(iter: Iter, len: Option<usize>) -> SeqIteratorVisitor<Iter> {
SeqIteratorVisitor {
@@ -127,8 +182,8 @@ impl<T, Iter> SeqVisitor for SeqIteratorVisitor<Iter>
{
match self.iter.next() {
Some(value) => {
let value = try!(serializer.visit_seq_elt(value));
Ok(Some(value))
try!(serializer.serialize_seq_elt(value));
Ok(Some(()))
}
None => Ok(None),
}
@@ -149,10 +204,12 @@ impl<T> Serialize for [T]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! array_impls {
($len:expr) => {
impl<T> Serialize for [T; $len] where T: Serialize {
@@ -160,7 +217,8 @@ macro_rules! array_impls {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some($len)))
let visitor = SeqIteratorVisitor::new(self.iter(), Some($len));
serializer.serialize_fixed_size_array(visitor)
}
}
}
@@ -209,7 +267,7 @@ impl<T> Serialize for BinaryHeap<T>
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
@@ -220,7 +278,7 @@ impl<T> Serialize for BTreeSet<T>
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
@@ -232,7 +290,7 @@ impl<T> Serialize for EnumSet<T>
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
@@ -243,7 +301,7 @@ impl<T> Serialize for HashSet<T>
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
@@ -254,7 +312,7 @@ impl<T> Serialize for LinkedList<T>
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
@@ -268,7 +326,7 @@ impl<A> Serialize for ops::Range<A>
where S: Serializer,
{
let len = iter::Step::steps_between(&self.start, &self.end, &A::one());
serializer.visit_seq(SeqIteratorVisitor::new(self.clone(), len))
serializer.serialize_seq(SeqIteratorVisitor::new(self.clone(), len))
}
}
@@ -286,7 +344,7 @@ impl<T> Serialize for VecDeque<T> where T: Serialize {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
@@ -297,7 +355,7 @@ impl Serialize for () {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_unit()
serializer.serialize_unit()
}
}
@@ -315,12 +373,14 @@ macro_rules! tuple_impls {
}
)+) => {
$(
/// A tuple visitor.
pub struct $TupleVisitor<'a, $($T: 'a),+> {
tuple: &'a ($($T,)+),
state: u8,
}
impl<'a, $($T: 'a),+> $TupleVisitor<'a, $($T),+> {
/// Construct a new, empty `TupleVisitor`.
pub fn new(tuple: &'a ($($T,)+)) -> $TupleVisitor<'a, $($T),+> {
$TupleVisitor {
tuple: tuple,
@@ -339,7 +399,7 @@ macro_rules! tuple_impls {
$(
$state => {
self.state += 1;
Ok(Some(try!(serializer.visit_tuple_elt(&e!(self.tuple.$idx)))))
Ok(Some(try!(serializer.serialize_tuple_elt(&e!(self.tuple.$idx)))))
}
)+
_ => {
@@ -358,7 +418,7 @@ macro_rules! tuple_impls {
{
#[inline]
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
serializer.visit_tuple($TupleVisitor::new(self))
serializer.serialize_tuple($TupleVisitor::new(self))
}
}
)+
@@ -472,6 +532,28 @@ tuple_impls! {
///////////////////////////////////////////////////////////////////////////////
/// A `serde::Visitor` for (key, value) map iterators.
///
/// # Examples
///
/// ```
/// use std::collections::HashMap;
/// use serde::{Serialize, Serializer};
/// use serde::ser::impls::MapIteratorVisitor;
///
/// struct Map(HashMap<u32, u32>);
///
/// impl Serialize for Map {
/// fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
/// where S: Serializer,
/// {
/// ser.serialize_map(MapIteratorVisitor::new(
/// self.0.iter(),
/// Some(self.0.len()),
/// ))
/// }
/// }
/// ```
pub struct MapIteratorVisitor<Iter> {
iter: Iter,
len: Option<usize>,
@@ -480,6 +562,7 @@ pub struct MapIteratorVisitor<Iter> {
impl<K, V, Iter> MapIteratorVisitor<Iter>
where Iter: Iterator<Item=(K, V)>
{
/// Construct a new `MapIteratorVisitor<Iter>`.
#[inline]
pub fn new(iter: Iter, len: Option<usize>) -> MapIteratorVisitor<Iter> {
MapIteratorVisitor {
@@ -500,8 +583,8 @@ impl<K, V, I> MapVisitor for MapIteratorVisitor<I>
{
match self.iter.next() {
Some((key, value)) => {
let value = try!(serializer.visit_map_elt(key, value));
Ok(Some(value))
try!(serializer.serialize_map_elt(key, value));
Ok(Some(()))
}
None => Ok(None)
}
@@ -523,7 +606,7 @@ impl<K, V> Serialize for BTreeMap<K, V>
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
@@ -535,19 +618,7 @@ impl<K, V> Serialize for HashMap<K, V>
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
#[cfg(feature = "nightly")]
impl<V> Serialize for VecMap<V>
where V: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
serializer.serialize_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
@@ -612,85 +683,11 @@ impl<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned, {
impl<T, E> Serialize for Result<T, E> where T: Serialize, E: Serialize {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
match *self {
Result::Ok(ref field0) => {
struct Visitor<'a, T, E> where T: Serialize + 'a, E: Serialize + 'a {
state: usize,
value: (&'a T,),
_structure_ty: PhantomData<&'a Result<T, E>>,
}
impl<'a, T, E> SeqVisitor for Visitor<'a, T, E> where T: Serialize + 'a,
E: Serialize + 'a {
#[inline]
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer {
match self.state {
0 => {
self.state += 1;
let v = match serializer.visit_seq_elt(&self.value.0) {
Ok(val) => val,
Err(err) => return Err(From::from(err)),
};
Ok(Some(v))
}
_ => Ok(None),
}
}
#[inline]
fn len(&self) -> Option<usize> {
Some(1)
}
}
let field0: &T = field0;
let data: PhantomData<&Result<&T,E>> = PhantomData;
let visitor = Visitor {
value: (&field0,),
state: 0,
_structure_ty: data
};
serializer.visit_enum_seq("Result", "Ok", visitor)
Result::Ok(ref value) => {
serializer.serialize_newtype_variant("Result", 0, "Ok", value)
}
Result::Err(ref field0) => {
struct Visitor<'a, T, E> where T: Serialize + 'a, E: Serialize + 'a {
state: usize,
value: (&'a E,),
_structure_ty: PhantomData<&'a Result<T, E>>,
}
impl<'a, T, E> SeqVisitor for Visitor<'a, T, E> where T: Serialize + 'a,
E: Serialize + 'a {
#[inline]
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer {
match self.state {
0 => {
self.state += 1;
let v = match serializer.visit_seq_elt(&self.value.0) {
Ok(val) => val,
Err(err) => return Err(From::from(err)),
};
Ok(Some(v))
}
_ => Ok(None),
}
}
#[inline]
fn len(&self) -> Option<usize> {
Some(1)
}
}
let field0: &E = field0;
let data: PhantomData<&Result<T,&E>> = PhantomData;
let visitor = Visitor {
value: (&field0,),
state: 0,
_structure_ty: data
};
serializer.visit_enum_seq("Result", "Err", visitor)
Result::Err(ref value) => {
serializer.serialize_newtype_variant("Result", 1, "Err", value)
}
}
}
@@ -698,11 +695,73 @@ impl<T, E> Serialize for Result<T, E> where T: Serialize, E: Serialize {
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "nightly")]
impl Serialize for net::IpAddr {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
match *self {
net::IpAddr::V4(ref addr) => addr.serialize(serializer),
net::IpAddr::V6(ref addr) => addr.serialize(serializer),
}
}
}
impl Serialize for net::Ipv4Addr {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
self.to_string().serialize(serializer)
}
}
impl Serialize for net::Ipv6Addr {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
self.to_string().serialize(serializer)
}
}
///////////////////////////////////////////////////////////////////////////////
impl Serialize for net::SocketAddr {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
match *self {
net::SocketAddr::V4(ref addr) => addr.serialize(serializer),
net::SocketAddr::V6(ref addr) => addr.serialize(serializer),
}
}
}
impl Serialize for net::SocketAddrV4 {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
self.to_string().serialize(serializer)
}
}
impl Serialize for net::SocketAddrV6 {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
self.to_string().serialize(serializer)
}
}
///////////////////////////////////////////////////////////////////////////////
impl Serialize for path::Path {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
self.to_str().unwrap().serialize(serializer)
match self.to_str() {
Some(s) => s.serialize(serializer),
None => Err(Error::invalid_value("Path contains invalid UTF-8 characters")),
}
}
}
@@ -710,7 +769,7 @@ impl Serialize for path::PathBuf {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
self.to_str().unwrap().serialize(serializer)
self.as_path().serialize(serializer)
}
}
+246 -128
View File
@@ -1,239 +1,351 @@
//! Generic serialization framework.
use std::error;
pub mod impls;
///////////////////////////////////////////////////////////////////////////////
/// `Error` is a trait that allows a `Serialize` to generically create a
/// `Serializer` error.
pub trait Error: Sized + error::Error {
/// Raised when there is general error when deserializing a type.
fn custom<T: Into<String>>(msg: T) -> Self;
/// Raised when a `Serialize` was passed an incorrect value.
fn invalid_value(msg: &str) -> Self {
Error::custom(format!("invalid value: {}", msg))
}
}
///////////////////////////////////////////////////////////////////////////////
/// A trait that describes a type that can be serialized by a `Serializer`.
pub trait Serialize {
/// Serializes this value into this serializer.
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer;
}
///////////////////////////////////////////////////////////////////////////////
/// A trait that describes a type that can serialize a stream of values into the underlying format.
pub trait Serializer {
type Error;
/// The error type that can be returned if some error occurs during serialization.
type Error: Error;
/// `visit_bool` serializes a `bool` value.
fn visit_bool(&mut self, v: bool) -> Result<(), Self::Error>;
/// Serializes a `bool` value.
fn serialize_bool(&mut self, v: bool) -> Result<(), Self::Error>;
/// `visit_isize` serializes a `isize` value. By default it casts the value to a `i64` and
/// passes it to the `visit_i64` method.
/// Serializes a `isize` value. By default it casts the value to a `i64` and
/// passes it to the `serialize_i64` method.
#[inline]
fn visit_isize(&mut self, v: isize) -> Result<(), Self::Error> {
self.visit_i64(v as i64)
fn serialize_isize(&mut self, v: isize) -> Result<(), Self::Error> {
self.serialize_i64(v as i64)
}
/// `visit_i8` serializes a `i8` value. By default it casts the value to a `i64` and
/// passes it to the `visit_i64` method.
/// Serializes a `i8` value. By default it casts the value to a `i64` and
/// passes it to the `serialize_i64` method.
#[inline]
fn visit_i8(&mut self, v: i8) -> Result<(), Self::Error> {
self.visit_i64(v as i64)
fn serialize_i8(&mut self, v: i8) -> Result<(), Self::Error> {
self.serialize_i64(v as i64)
}
/// `visit_i16` serializes a `i16` value. By default it casts the value to a `i64` and
/// passes it to the `visit_i64` method.
/// Serializes a `i16` value. By default it casts the value to a `i64` and
/// passes it to the `serialize_i64` method.
#[inline]
fn visit_i16(&mut self, v: i16) -> Result<(), Self::Error> {
self.visit_i64(v as i64)
fn serialize_i16(&mut self, v: i16) -> Result<(), Self::Error> {
self.serialize_i64(v as i64)
}
/// `visit_i32` serializes a `i32` value. By default it casts the value to a `i64` and
/// passes it to the `visit_i64` method.
/// Serializes a `i32` value. By default it casts the value to a `i64` and
/// passes it to the `serialize_i64` method.
#[inline]
fn visit_i32(&mut self, v: i32) -> Result<(), Self::Error> {
self.visit_i64(v as i64)
fn serialize_i32(&mut self, v: i32) -> Result<(), Self::Error> {
self.serialize_i64(v as i64)
}
/// `visit_i64` serializes a `i64` value.
/// Serializes a `i64` value.
#[inline]
fn visit_i64(&mut self, v: i64) -> Result<(), Self::Error>;
fn serialize_i64(&mut self, v: i64) -> Result<(), Self::Error>;
/// `visit_usize` serializes a `usize` value. By default it casts the value to a `u64` and
/// passes it to the `visit_u64` method.
/// Serializes a `usize` value. By default it casts the value to a `u64` and
/// passes it to the `serialize_u64` method.
#[inline]
fn visit_usize(&mut self, v: usize) -> Result<(), Self::Error> {
self.visit_u64(v as u64)
fn serialize_usize(&mut self, v: usize) -> Result<(), Self::Error> {
self.serialize_u64(v as u64)
}
/// `visit_u8` serializes a `u8` value. By default it casts the value to a `u64` and passes
/// it to the `visit_u64` method.
/// Serializes a `u8` value. By default it casts the value to a `u64` and passes
/// it to the `serialize_u64` method.
#[inline]
fn visit_u8(&mut self, v: u8) -> Result<(), Self::Error> {
self.visit_u64(v as u64)
fn serialize_u8(&mut self, v: u8) -> Result<(), Self::Error> {
self.serialize_u64(v as u64)
}
/// `visit_u32` serializes a `u32` value. By default it casts the value to a `u64` and passes
/// it to the `visit_u64` method.
/// Serializes a `u32` value. By default it casts the value to a `u64` and passes
/// it to the `serialize_u64` method.
#[inline]
fn visit_u16(&mut self, v: u16) -> Result<(), Self::Error> {
self.visit_u64(v as u64)
fn serialize_u16(&mut self, v: u16) -> Result<(), Self::Error> {
self.serialize_u64(v as u64)
}
/// `visit_u32` serializes a `u32` value. By default it casts the value to a `u64` and passes
/// it to the `visit_u64` method.
/// Serializes a `u32` value. By default it casts the value to a `u64` and passes
/// it to the `serialize_u64` method.
#[inline]
fn visit_u32(&mut self, v: u32) -> Result<(), Self::Error> {
self.visit_u64(v as u64)
fn serialize_u32(&mut self, v: u32) -> Result<(), Self::Error> {
self.serialize_u64(v as u64)
}
/// `visit_u64` serializes a `u64` value.
/// `Serializes a `u64` value.
#[inline]
fn visit_u64(&mut self, v: u64) -> Result<(), Self::Error>;
fn serialize_u64(&mut self, v: u64) -> Result<(), Self::Error>;
/// `visit_f32` serializes a `f32` value. By default it casts the value to a `f64` and passes
/// it to the `visit_f64` method.
/// Serializes a `f32` value. By default it casts the value to a `f64` and passes
/// it to the `serialize_f64` method.
#[inline]
fn visit_f32(&mut self, v: f32) -> Result<(), Self::Error> {
self.visit_f64(v as f64)
fn serialize_f32(&mut self, v: f32) -> Result<(), Self::Error> {
self.serialize_f64(v as f64)
}
/// `visit_f64` serializes a `f64` value.
fn visit_f64(&mut self, v: f64) -> Result<(), Self::Error>;
/// Serializes a `f64` value.
fn serialize_f64(&mut self, v: f64) -> Result<(), Self::Error>;
/// `visit_char` serializes a character. By default it serializes it as a `&str` containing a
/// Serializes a character. By default it serializes it as a `&str` containing a
/// single character.
#[inline]
fn visit_char(&mut self, v: char) -> Result<(), Self::Error> {
fn serialize_char(&mut self, v: char) -> Result<(), Self::Error> {
// FIXME: this allocation is required in order to be compatible with stable rust, which
// doesn't support encoding a `char` into a stack buffer.
self.visit_str(&v.to_string())
self.serialize_str(&v.to_string())
}
/// `visit_str` serializes a `&str`.
fn visit_str(&mut self, value: &str) -> Result<(), Self::Error>;
/// Serializes a `&str`.
fn serialize_str(&mut self, value: &str) -> Result<(), Self::Error>;
/// `visit_bytes` is a hook that enables those serialization formats that support serializing
/// Enables those serialization formats that support serializing
/// byte slices separately from generic arrays. By default it serializes as a regular array.
#[inline]
fn visit_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error> {
self.visit_seq(impls::SeqIteratorVisitor::new(value.iter(), Some(value.len())))
fn serialize_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error> {
self.serialize_seq(impls::SeqIteratorVisitor::new(value.iter(), Some(value.len())))
}
fn visit_unit(&mut self) -> Result<(), Self::Error>;
/// Serializes a `()` value.
fn serialize_unit(&mut self) -> Result<(), Self::Error>;
/// Serializes a unit struct value.
///
/// By default, unit structs are serialized as a `()`.
#[inline]
fn visit_named_unit(&mut self, _name: &str) -> Result<(), Self::Error> {
self.visit_unit()
fn serialize_unit_struct(&mut self, _name: &'static str) -> Result<(), Self::Error> {
self.serialize_unit()
}
/// Serializes a unit variant, otherwise known as a variant with no arguments.
///
/// By default, unit variants are serialized as a `()`.
#[inline]
fn visit_enum_unit(&mut self,
_name: &str,
_variant: &str) -> Result<(), Self::Error> {
self.visit_unit()
fn serialize_unit_variant(&mut self,
_name: &'static str,
_variant_index: usize,
_variant: &'static str) -> Result<(), Self::Error> {
self.serialize_unit()
}
fn visit_none(&mut self) -> Result<(), Self::Error>;
/// Allows a tuple struct with a single element, also known as a
/// newtyped value, to be more efficiently serialized than a tuple struct with multiple items.
/// By default it just serializes the value as a tuple struct sequence.
#[inline]
fn serialize_newtype_struct<T>(&mut self,
name: &'static str,
value: T) -> Result<(), Self::Error>
where T: Serialize,
{
self.serialize_tuple_struct(name, Some(value))
}
fn visit_some<V>(&mut self, value: V) -> Result<(), Self::Error>
/// Allows a variant with a single item to be more efficiently
/// serialized than a variant with multiple items. By default it just serializes the value as a
/// tuple variant sequence.
#[inline]
fn serialize_newtype_variant<T>(&mut self,
name: &'static str,
variant_index: usize,
variant: &'static str,
value: T) -> Result<(), Self::Error>
where T: Serialize,
{
self.serialize_tuple_variant(
name,
variant_index,
variant,
Some(value))
}
/// Serializes a `None` value..serialize
fn serialize_none(&mut self) -> Result<(), Self::Error>;
/// Serializes a `Some(...)` value.
fn serialize_some<V>(&mut self, value: V) -> Result<(), Self::Error>
where V: Serialize;
fn visit_seq<V>(&mut self, visitor: V) -> Result<(), Self::Error>
/// Serializes a sequence.
///
/// Callees of this method need to construct a `SeqVisitor`, which iterates through each item
/// in the sequence.
fn serialize_seq<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor;
fn visit_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
/// Serializes a sequence element.
fn serialize_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize;
/// Serializes a tuple.
///
/// By default this serializes a tuple as a sequence.
#[inline]
fn visit_tuple<V>(&mut self, visitor: V) -> Result<(), Self::Error>
fn serialize_tuple<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.visit_seq(visitor)
self.serialize_seq(visitor)
}
/// Serializes a tuple element.
///
/// By default, tuples are serialized as a sequence.
#[inline]
fn visit_tuple_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
fn serialize_tuple_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize
{
self.visit_seq_elt(value)
self.serialize_seq_elt(value)
}
/// Serializes a fixed-size array.
///
/// By default this serializes an array as a sequence.
#[inline]
fn visit_named_seq<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<(), Self::Error>
fn serialize_fixed_size_array<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.visit_tuple(visitor)
self.serialize_seq(visitor)
}
/// Serializes a tuple struct.
///
/// By default, tuple structs are serialized as a tuple.
#[inline]
fn visit_named_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize
{
self.visit_tuple_elt(value)
}
#[inline]
fn visit_enum_seq<V>(&mut self,
_name: &'static str,
_variant: &'static str,
visitor: V) -> Result<(), Self::Error>
fn serialize_tuple_struct<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.visit_tuple(visitor)
self.serialize_tuple(visitor)
}
/// Serializes a tuple struct element.
///
/// By default, tuple struct elements are serialized as a tuple element.
#[inline]
fn visit_enum_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
fn serialize_tuple_struct_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize
{
self.visit_tuple_elt(value)
self.serialize_tuple_elt(value)
}
fn visit_map<V>(&mut self, visitor: V) -> Result<(), Self::Error>
/// Serializes a tuple variant.
///
/// By default, tuple variants are serialized as a tuple struct.
#[inline]
fn serialize_tuple_variant<V>(&mut self,
_name: &'static str,
_variant_index: usize,
variant: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.serialize_tuple_struct(variant, visitor)
}
/// Serializes a tuple element.
///
/// By default, tuples are serialized as a sequence.
#[inline]
fn serialize_tuple_variant_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize
{
self.serialize_tuple_struct_elt(value)
}
/// Serializes a map.
///
/// Callees of this method need to construct a `MapVisitor`, which iterates through each item
/// in the map.
fn serialize_map<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: MapVisitor;
fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
/// Serializes a map element (key-value pair).
fn serialize_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
where K: Serialize,
V: Serialize;
#[inline]
fn visit_named_map<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: MapVisitor,
{
self.visit_map(visitor)
}
#[inline]
fn visit_named_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
where K: Serialize,
V: Serialize,
{
self.visit_map_elt(key, value)
}
#[inline]
fn visit_enum_map<V>(&mut self,
_name: &'static str,
variant: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: MapVisitor,
{
self.visit_named_map(variant, visitor)
}
#[inline]
fn visit_enum_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
where K: Serialize,
V: Serialize,
{
self.visit_named_map_elt(key, value)
}
/// Specify a format string for the serializer.
/// Serializes a struct.
///
/// The serializer format is used to determine which format
/// specific field attributes should be used with the serializer.
fn format() -> &'static str {
""
/// By default, structs are serialized as a map with the field name as the key.
#[inline]
fn serialize_struct<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: MapVisitor,
{
self.serialize_map(visitor)
}
/// Serializes an element of a struct.
///
/// By default, struct elements are serialized as a map element with the field name as the key.
#[inline]
fn serialize_struct_elt<V>(&mut self,
key: &'static str,
value: V) -> Result<(), Self::Error>
where V: Serialize,
{
self.serialize_map_elt(key, value)
}
/// Serializes a struct variant.
///
/// By default, struct variants are serialized as a struct.
#[inline]
fn serialize_struct_variant<V>(&mut self,
_name: &'static str,
_variant_index: usize,
variant: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: MapVisitor,
{
self.serialize_struct(variant, visitor)
}
/// Serializes an element of a struct variant.
///
/// By default, struct variant elements are serialized as a struct element.
#[inline]
fn serialize_struct_variant_elt<V>(&mut self,
key: &'static str,
value: V) -> Result<(), Self::Error>
where V: Serialize,
{
self.serialize_struct_elt(key, value)
}
}
/// A trait that is used by a `Serialize` to iterate through a sequence.
#[cfg_attr(feature = "nightly-testing", allow(len_without_is_empty))]
pub trait SeqVisitor {
/// Serializes a sequence item in the serializer.
///
/// This returns `Ok(Some(()))` when there are more items to serialize, or `Ok(None)` when
/// complete.
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer;
@@ -244,7 +356,13 @@ pub trait SeqVisitor {
}
}
/// A trait that is used by a `Serialize` to iterate through a map.
#[cfg_attr(feature = "nightly-testing", allow(len_without_is_empty))]
pub trait MapVisitor {
/// Serializes a map item in the serializer.
///
/// This returns `Ok(Some(()))` when there are more items to serialize, or `Ok(None)` when
/// complete.
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer;
+14 -10
View File
@@ -1,24 +1,28 @@
[package]
name = "serde_codegen"
version = "0.4.3"
version = "0.7.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
repository = "https://github.com/erickt/rust-serde"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde-rs.github.io/serde/serde_codegen/serde_codegen/index.html"
build = "build.rs"
keywords = ["serde", "serialization"]
[features]
default = ["with-syntex"]
nightly = ["quasi_macros"]
with-syntex = ["quasi/with-syntex", "quasi_codegen/with-syntex", "syntex", "syntex_syntax"]
nightly-testing = ["clippy"]
with-syntex = ["quasi/with-syntex", "quasi_codegen", "quasi_codegen/with-syntex", "syntex", "syntex_syntax"]
[build-dependencies]
quasi_codegen = { verision = "*", optional = true }
syntex = { version = "*", optional = true }
quasi_codegen = { version = "^0.7.0", optional = true }
syntex = { version = "^0.29.0", optional = true }
[dependencies]
aster = { version = "*", default-features = false }
quasi = { verision = "*", default-features = false }
quasi_macros = { version = "*", optional = true }
syntex = { version = "*", optional = true }
syntex_syntax = { version = "*", optional = true }
aster = { version = "^0.13.1", default-features = false }
clippy = { version = "^0.*", optional = true }
quasi = { version = "^0.7.0", default-features = false }
quasi_macros = { version = "^0.7.0", optional = true }
syntex = { version = "^0.29.0", optional = true }
syntex_syntax = { version = "^0.29.0", optional = true }
+613 -88
View File
@@ -1,108 +1,633 @@
use std::collections::HashMap;
use std::collections::HashSet;
use syntax::ast;
use std::rc::Rc;
use syntax::ast::{self, TokenTree};
use syntax::attr;
use syntax::codemap::Span;
use syntax::ext::base::ExtCtxt;
use syntax::fold::Folder;
use syntax::parse::parser::PathParsingMode;
use syntax::parse::token::{self, InternedString};
use syntax::parse;
use syntax::print::pprust::{lit_to_string, meta_item_to_string};
use syntax::ptr::P;
/// Represents field name information
pub enum FieldNames {
Global(P<ast::Expr>),
Format{
formats: HashMap<P<ast::Expr>, P<ast::Expr>>,
default: P<ast::Expr>,
use aster::AstBuilder;
use error::Error;
#[derive(Debug)]
pub struct Name {
ident: ast::Ident,
serialize_name: Option<InternedString>,
deserialize_name: Option<InternedString>,
}
impl Name {
fn new(ident: ast::Ident) -> Self {
Name {
ident: ident,
serialize_name: None,
deserialize_name: None,
}
}
/// Return the string expression of the field ident.
pub fn ident_expr(&self) -> P<ast::Expr> {
AstBuilder::new().expr().str(self.ident)
}
/// Return the container name for the container when serializing.
pub fn serialize_name(&self) -> InternedString {
match self.serialize_name {
Some(ref name) => name.clone(),
None => self.ident.name.as_str(),
}
}
/// Return the container name expression for the container when deserializing.
pub fn serialize_name_expr(&self) -> P<ast::Expr> {
AstBuilder::new().expr().str(self.serialize_name())
}
/// Return the container name for the container when deserializing.
pub fn deserialize_name(&self) -> InternedString {
match self.deserialize_name {
Some(ref name) => name.clone(),
None => self.ident.name.as_str(),
}
}
/// Return the container name expression for the container when deserializing.
pub fn deserialize_name_expr(&self) -> P<ast::Expr> {
AstBuilder::new().expr().str(self.deserialize_name())
}
}
/// Represents container (e.g. struct) attribute information
#[derive(Debug)]
pub struct ContainerAttrs {
name: Name,
deny_unknown_fields: bool,
}
impl ContainerAttrs {
/// Extract out the `#[serde(...)]` attributes from an item.
pub fn from_item(cx: &ExtCtxt, item: &ast::Item) -> Result<Self, Error> {
let mut container_attrs = ContainerAttrs {
name: Name::new(item.ident),
deny_unknown_fields: false,
};
for meta_items in item.attrs().iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
match meta_item.node {
// Parse `#[serde(rename="foo")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"rename" => {
let s = try!(get_str_from_lit(cx, name, lit));
container_attrs.name.serialize_name = Some(s.clone());
container_attrs.name.deserialize_name = Some(s);
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"rename" => {
let (ser_name, de_name) = try!(get_renames(cx, meta_items));
container_attrs.name.serialize_name = ser_name;
container_attrs.name.deserialize_name = de_name;
}
// Parse `#[serde(deny_unknown_fields)]`
ast::MetaItemKind::Word(ref name) if name == &"deny_unknown_fields" => {
container_attrs.deny_unknown_fields = true;
}
_ => {
cx.span_err(
meta_item.span,
&format!("unknown serde container attribute `{}`",
meta_item_to_string(meta_item)));
return Err(Error);
}
}
}
}
Ok(container_attrs)
}
pub fn name(&self) -> &Name {
&self.name
}
pub fn deny_unknown_fields(&self) -> bool {
self.deny_unknown_fields
}
}
/// Represents variant attribute information
#[derive(Debug)]
pub struct VariantAttrs {
name: Name,
}
impl VariantAttrs {
pub fn from_variant(cx: &ExtCtxt, variant: &ast::Variant) -> Result<Self, Error> {
let mut variant_attrs = VariantAttrs {
name: Name::new(variant.node.name),
};
for meta_items in variant.node.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
match meta_item.node {
// Parse `#[serde(rename="foo")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"rename" => {
let s = try!(get_str_from_lit(cx, name, lit));
variant_attrs.name.serialize_name = Some(s.clone());
variant_attrs.name.deserialize_name = Some(s);
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"rename" => {
let (ser_name, de_name) = try!(get_renames(cx, meta_items));
variant_attrs.name.serialize_name = ser_name;
variant_attrs.name.deserialize_name = de_name;
}
_ => {
cx.span_err(
meta_item.span,
&format!("unknown serde variant attribute `{}`",
meta_item_to_string(meta_item)));
return Err(Error);
}
}
}
}
Ok(variant_attrs)
}
pub fn name(&self) -> &Name {
&self.name
}
}
/// Represents field attribute information
#[derive(Debug)]
pub struct FieldAttrs {
names: FieldNames,
use_default: bool,
name: Name,
skip_serializing_field: bool,
skip_serializing_field_if: Option<P<ast::Expr>>,
default_expr_if_missing: Option<P<ast::Expr>>,
serialize_with: Option<P<ast::Expr>>,
deserialize_with: Option<P<ast::Expr>>,
}
impl FieldAttrs {
/// Extract out the `#[serde(...)]` attributes from a struct field.
pub fn from_field(cx: &ExtCtxt,
container_ty: &P<ast::Ty>,
generics: &ast::Generics,
field: &ast::StructField,
is_enum: bool) -> Result<Self, Error> {
let builder = AstBuilder::new();
/// Create a FieldAttr with a single default field name
pub fn new(default_value: bool, name: P<ast::Expr>) -> FieldAttrs {
FieldAttrs {
names: FieldNames::Global(name),
use_default: default_value,
let field_ident = match field.node.ident() {
Some(ident) => ident,
None => { cx.span_bug(field.span, "struct field has no name?") }
};
let mut field_attrs = FieldAttrs {
name: Name::new(field_ident),
skip_serializing_field: false,
skip_serializing_field_if: None,
default_expr_if_missing: None,
serialize_with: None,
deserialize_with: None,
};
for meta_items in field.node.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
match meta_item.node {
// Parse `#[serde(rename="foo")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"rename" => {
let s = try!(get_str_from_lit(cx, name, lit));
field_attrs.name.serialize_name = Some(s.clone());
field_attrs.name.deserialize_name = Some(s);
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"rename" => {
let (ser_name, de_name) = try!(get_renames(cx, meta_items));
field_attrs.name.serialize_name = ser_name;
field_attrs.name.deserialize_name = de_name;
}
// Parse `#[serde(default)]`
ast::MetaItemKind::Word(ref name) if name == &"default" => {
let default_expr = builder.expr().default();
field_attrs.default_expr_if_missing = Some(default_expr);
}
// Parse `#[serde(default="...")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"default" => {
let wrapped_expr = wrap_default(
try!(parse_lit_into_path(cx, name, lit)),
);
field_attrs.default_expr_if_missing = Some(wrapped_expr);
}
// Parse `#[serde(skip_serializing)]`
ast::MetaItemKind::Word(ref name) if name == &"skip_serializing" => {
field_attrs.skip_serializing_field = true;
}
// Parse `#[serde(skip_serializing_if="...")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"skip_serializing_if" => {
let expr = wrap_skip_serializing(
field_ident,
try!(parse_lit_into_path(cx, name, lit)),
is_enum,
);
field_attrs.skip_serializing_field_if = Some(expr);
}
// Parse `#[serde(serialize_with="...")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"serialize_with" => {
let expr = wrap_serialize_with(
cx,
container_ty,
generics,
field_ident,
try!(parse_lit_into_path(cx, name, lit)),
is_enum,
);
field_attrs.serialize_with = Some(expr);
}
// Parse `#[serde(deserialize_with="...")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"deserialize_with" => {
let expr = wrap_deserialize_with(
cx,
&field.node.ty,
generics,
try!(parse_lit_into_path(cx, name, lit)),
);
field_attrs.deserialize_with = Some(expr);
}
_ => {
cx.span_err(
meta_item.span,
&format!("unknown serde field attribute `{}`",
meta_item_to_string(meta_item)));
return Err(Error);
}
}
}
}
Ok(field_attrs)
}
/// Create a FieldAttr with format specific field names
pub fn new_with_formats(
default_value: bool,
default_name: P<ast::Expr>,
formats: HashMap<P<ast::Expr>, P<ast::Expr>>,
) -> FieldAttrs {
FieldAttrs {
names: FieldNames::Format {
formats: formats,
default: default_name,
},
use_default: default_value,
}
}
/// Return a set of formats that the field has attributes for.
pub fn formats(&self) -> HashSet<P<ast::Expr>> {
match self.names {
FieldNames::Format{ref formats, default: _} => {
let mut set = HashSet::new();
for (fmt, _) in formats.iter() {
set.insert(fmt.clone());
};
set
},
_ => HashSet::new()
}
}
/// Return an expression for the field key name for serialisation.
///
/// The resulting expression assumes that `S` refers to a type
/// that implements `Serializer`.
pub fn serializer_key_expr(self, cx: &ExtCtxt) -> P<ast::Expr> {
match self.names {
FieldNames::Global(x) => x,
FieldNames::Format{formats, default} => {
let arms = formats.iter()
.map(|(fmt, lit)| {
quote_arm!(cx, $fmt => { $lit })
})
.collect::<Vec<_>>();
quote_expr!(cx,
{
match S::format() {
$arms
_ => { $default }
}
})
},
}
}
/// Return the default field name for the field.
pub fn default_key_expr(&self) -> &P<ast::Expr> {
match self.names {
FieldNames::Global(ref expr) => expr,
FieldNames::Format{formats: _, ref default} => default
}
}
/// Return the field name for the field in the specified format.
pub fn key_expr(&self, format: &P<ast::Expr>) -> &P<ast::Expr> {
match self.names {
FieldNames::Global(ref expr) =>
expr,
FieldNames::Format{ref formats, ref default} =>
formats.get(format).unwrap_or(default)
}
pub fn name(&self) -> &Name {
&self.name
}
/// Predicate for using a field's default value
pub fn use_default(&self) -> bool {
self.use_default
pub fn expr_is_missing(&self) -> P<ast::Expr> {
match self.default_expr_if_missing {
Some(ref expr) => expr.clone(),
None => {
let name = self.name.ident_expr();
AstBuilder::new().expr()
.try()
.method_call("missing_field").id("visitor")
.with_arg(name)
.build()
}
}
}
/// Predicate for ignoring a field when serializing a value
pub fn skip_serializing_field(&self) -> bool {
self.skip_serializing_field
}
pub fn skip_serializing_field_if(&self) -> Option<&P<ast::Expr>> {
self.skip_serializing_field_if.as_ref()
}
pub fn serialize_with(&self) -> Option<&P<ast::Expr>> {
self.serialize_with.as_ref()
}
pub fn deserialize_with(&self) -> Option<&P<ast::Expr>> {
self.deserialize_with.as_ref()
}
}
/// Extract out the `#[serde(...)]` attributes from a struct field.
pub fn get_struct_field_attrs(cx: &ExtCtxt,
container_ty: &P<ast::Ty>,
generics: &ast::Generics,
fields: &[ast::StructField],
is_enum: bool) -> Result<Vec<FieldAttrs>, Error> {
fields.iter()
.map(|field| FieldAttrs::from_field(cx, container_ty, generics, field, is_enum))
.collect()
}
fn get_renames(cx: &ExtCtxt,
items: &[P<ast::MetaItem>],
)-> Result<(Option<InternedString>, Option<InternedString>), Error> {
let mut ser_name = None;
let mut de_name = None;
for item in items {
match item.node {
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"serialize" => {
let s = try!(get_str_from_lit(cx, name, lit));
ser_name = Some(s);
}
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"deserialize" => {
let s = try!(get_str_from_lit(cx, name, lit));
de_name = Some(s);
}
_ => {
cx.span_err(
item.span,
&format!("unknown rename attribute `{}`",
meta_item_to_string(item)));
return Err(Error);
}
}
}
Ok((ser_name, de_name))
}
fn get_serde_meta_items(attr: &ast::Attribute) -> Option<&[P<ast::MetaItem>]> {
match attr.node.value.node {
ast::MetaItemKind::List(ref name, ref items) if name == &"serde" => {
attr::mark_used(&attr);
Some(items)
}
_ => None
}
}
/// This syntax folder rewrites tokens to say their spans are coming from a macro context.
struct Respanner<'a, 'b: 'a> {
cx: &'a ExtCtxt<'b>,
}
impl<'a, 'b> Folder for Respanner<'a, 'b> {
fn fold_tt(&mut self, tt: &TokenTree) -> TokenTree {
match *tt {
TokenTree::Token(span, ref tok) => {
TokenTree::Token(
self.new_span(span),
self.fold_token(tok.clone())
)
}
TokenTree::Delimited(span, ref delimed) => {
TokenTree::Delimited(
self.new_span(span),
Rc::new(ast::Delimited {
delim: delimed.delim,
open_span: delimed.open_span,
tts: self.fold_tts(&delimed.tts),
close_span: delimed.close_span,
})
)
}
TokenTree::Sequence(span, ref seq) => {
TokenTree::Sequence(
self.new_span(span),
Rc::new(ast::SequenceRepetition {
tts: self.fold_tts(&seq.tts),
separator: seq.separator.clone().map(|tok| self.fold_token(tok)),
..**seq
})
)
}
}
}
fn new_span(&mut self, span: Span) -> Span {
Span {
lo: span.lo,
hi: span.hi,
expn_id: self.cx.backtrace(),
}
}
}
fn get_str_from_lit(cx: &ExtCtxt, name: &str, lit: &ast::Lit) -> Result<InternedString, Error> {
match lit.node {
ast::LitKind::Str(ref s, _) => Ok(s.clone()),
_ => {
cx.span_err(
lit.span,
&format!("serde annotation `{}` must be a string, not `{}`",
name,
lit_to_string(lit)));
return Err(Error);
}
}
}
fn parse_lit_into_path(cx: &ExtCtxt, name: &str, lit: &ast::Lit) -> Result<ast::Path, Error> {
let source = try!(get_str_from_lit(cx, name, lit));
// If we just parse the string into an expression, any syntax errors in the source will only
// have spans that point inside the string, and not back to the attribute. So to have better
// error reporting, we'll first parse the string into a token tree. Then we'll update those
// spans to say they're coming from a macro context that originally came from the attribute,
// and then finally parse them into an expression.
let tts = parse::parse_tts_from_source_str(
format!("<serde {} expansion>", name),
(*source).to_owned(),
cx.cfg(),
cx.parse_sess());
// Respan the spans to say they are all coming from this macro.
let tts = Respanner { cx: cx }.fold_tts(&tts);
let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts);
let path = match parser.parse_path(PathParsingMode::LifetimeAndTypesWithoutColons) {
Ok(path) => path,
Err(mut e) => {
e.emit();
return Err(Error);
}
};
// Make sure to error out if there are trailing characters in the stream.
match parser.expect(&token::Eof) {
Ok(()) => { }
Err(mut e) => {
e.emit();
return Err(Error);
}
}
Ok(path)
}
/// This function wraps the expression in `#[serde(default="...")]` in a function to prevent it
/// from accessing the internal `Deserialize` state.
fn wrap_default(path: ast::Path) -> P<ast::Expr> {
AstBuilder::new().expr().call()
.build_path(path)
.build()
}
/// This function wraps the expression in `#[serde(skip_serializing_if="...")]` in a trait to
/// prevent it from accessing the internal `Serialize` state.
fn wrap_skip_serializing(field_ident: ast::Ident,
path: ast::Path,
is_enum: bool) -> P<ast::Expr> {
let builder = AstBuilder::new();
let expr = builder.expr()
.field(field_ident)
.field("value")
.self_();
let expr = if is_enum {
expr
} else {
builder.expr().ref_().build(expr)
};
builder.expr().call()
.build_path(path)
.arg().build(expr)
.build()
}
/// This function wraps the expression in `#[serde(serialize_with="...")]` in a trait to
/// prevent it from accessing the internal `Serialize` state.
fn wrap_serialize_with(cx: &ExtCtxt,
container_ty: &P<ast::Ty>,
generics: &ast::Generics,
field_ident: ast::Ident,
path: ast::Path,
is_enum: bool) -> P<ast::Expr> {
let builder = AstBuilder::new();
let expr = builder.expr()
.field(field_ident)
.self_();
let expr = if is_enum {
expr
} else {
builder.expr().ref_().build(expr)
};
let expr = builder.expr().call()
.build_path(path)
.arg().build(expr)
.arg()
.id("serializer")
.build();
let where_clause = &generics.where_clause;
quote_expr!(cx, {
trait __SerdeSerializeWith {
fn __serde_serialize_with<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: ::serde::ser::Serializer;
}
impl<'a, T> __SerdeSerializeWith for &'a T
where T: 'a + __SerdeSerializeWith,
{
fn __serde_serialize_with<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: ::serde::ser::Serializer
{
(**self).__serde_serialize_with(serializer)
}
}
impl $generics __SerdeSerializeWith for $container_ty $where_clause {
fn __serde_serialize_with<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: ::serde::ser::Serializer
{
$expr
}
}
struct __SerdeSerializeWithStruct<'a, T: 'a> {
value: &'a T,
}
impl<'a, T> ::serde::ser::Serialize for __SerdeSerializeWithStruct<'a, T>
where T: 'a + __SerdeSerializeWith
{
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: ::serde::ser::Serializer
{
self.value.__serde_serialize_with(serializer)
}
}
__SerdeSerializeWithStruct {
value: &self.value,
}
})
}
/// This function wraps the expression in `#[serde(deserialize_with="...")]` in a trait to prevent
/// it from accessing the internal `Deserialize` state.
fn wrap_deserialize_with(cx: &ExtCtxt,
field_ty: &P<ast::Ty>,
generics: &ast::Generics,
path: ast::Path) -> P<ast::Expr> {
// Quasi-quoting doesn't do a great job of expanding generics into paths, so manually build it.
let ty_path = AstBuilder::new().path()
.segment("__SerdeDeserializeWithStruct")
.with_generics(generics.clone())
.build()
.build();
let where_clause = &generics.where_clause;
quote_expr!(cx, {
struct __SerdeDeserializeWithStruct $generics $where_clause {
value: $field_ty,
}
impl $generics ::serde::de::Deserialize for $ty_path $where_clause {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: ::serde::de::Deserializer
{
let value = try!($path(deserializer));
Ok(__SerdeDeserializeWithStruct { value: value })
}
}
let value: $ty_path = try!(visitor.visit_value());
Ok(value.value)
})
}
+579 -283
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -0,0 +1,2 @@
/// Error returned if failed to parse attribute.
pub struct Error;
-133
View File
@@ -1,133 +0,0 @@
use std::collections::HashMap;
use aster;
use syntax::ast;
use syntax::attr;
use syntax::ext::base::ExtCtxt;
use syntax::ptr::P;
use attr::FieldAttrs;
enum Rename<'a> {
None,
Global(&'a ast::Lit),
Format(HashMap<P<ast::Expr>, &'a ast::Lit>)
}
fn rename<'a>(
builder: &aster::AstBuilder,
mi: &'a ast::MetaItem,
) -> Option<Rename<'a>>
{
match mi.node {
ast::MetaNameValue(ref n, ref lit) => {
if n == &"rename" {
Some(Rename::Global(lit))
} else {
None
}
},
ast::MetaList(ref n, ref items) => {
if n == &"rename" {
let mut m = HashMap::new();
m.extend(
items.iter()
.filter_map(
|item|
match item.node {
ast::MetaNameValue(ref n, ref lit) =>
Some((builder.expr().str(n),
lit)),
_ => None
}));
Some(Rename::Format(m))
} else {
None
}
},
_ => None
}
}
fn default_value(mi: &ast::MetaItem) -> bool {
if let ast::MetaItem_::MetaWord(ref n) = mi.node {
n == &"default"
} else {
false
}
}
fn field_attrs<'a>(
builder: &aster::AstBuilder,
field: &'a ast::StructField,
) -> (Rename<'a>, bool) {
field.node.attrs.iter()
.find(|sa| {
if let ast::MetaList(ref n, _) = sa.node.value.node {
n == &"serde"
} else {
false
}
})
.and_then(|sa| {
if let ast::MetaList(_, ref vals) = sa.node.value.node {
attr::mark_used(&sa);
Some((vals.iter()
.fold(None, |v, mi| v.or(rename(builder, mi)))
.unwrap_or(Rename::None),
vals.iter().any(|mi| default_value(mi))))
} else {
Some((Rename::None, false))
}
})
.unwrap_or((Rename::None, false))
}
pub fn struct_field_attrs(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
struct_def: &ast::StructDef,
) -> Vec<FieldAttrs> {
struct_def.fields.iter()
.map(|field| {
match field_attrs(builder, field) {
(Rename::Global(rename), default_value) =>
FieldAttrs::new(
default_value,
builder.expr().build_lit(P(rename.clone()))),
(Rename::Format(renames), default_value) => {
let mut res = HashMap::new();
res.extend(
renames.into_iter()
.map(|(k,v)|
(k, builder.expr().build_lit(P(v.clone())))));
FieldAttrs::new_with_formats(
default_value,
default_field_name(cx, builder, field.node.kind),
res)
},
(Rename::None, default_value) => {
FieldAttrs::new(
default_value,
default_field_name(cx, builder, field.node.kind))
}
}
})
.collect()
}
fn default_field_name(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
kind: ast::StructFieldKind,
) -> P<ast::Expr> {
match kind {
ast::NamedField(name, _) => {
builder.expr().str(name)
}
ast::UnnamedField(_) => {
cx.bug("struct has named and unnamed fields")
}
}
}
+19 -11
View File
@@ -1,3 +1,6 @@
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(feature = "nightly-testing", allow(used_underscore_binding))]
#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private, plugin))]
#![cfg_attr(not(feature = "with-syntex"), plugin(quasi_macros))]
@@ -14,7 +17,10 @@ extern crate syntex_syntax as syntax;
extern crate syntax;
#[cfg(not(feature = "with-syntex"))]
extern crate rustc;
extern crate rustc_plugin;
#[cfg(not(feature = "with-syntex"))]
use syntax::feature_gate::AttributeType;
#[cfg(feature = "with-syntex")]
include!(concat!(env!("OUT_DIR"), "/lib.rs"));
@@ -26,14 +32,6 @@ include!("lib.rs.in");
pub fn register(reg: &mut syntex::Registry) {
use syntax::{ast, fold};
reg.add_attr("feature(custom_derive)");
reg.add_attr("feature(custom_attribute)");
reg.add_decorator("derive_Serialize", ser::expand_derive_serialize);
reg.add_decorator("derive_Deserialize", de::expand_derive_deserialize);
reg.add_post_expansion_pass(strip_attributes);
/// Strip the serde attributes from the crate.
#[cfg(feature = "with-syntex")]
fn strip_attributes(krate: ast::Crate) -> ast::Crate {
@@ -43,7 +41,7 @@ pub fn register(reg: &mut syntex::Registry) {
impl fold::Folder for StripAttributeFolder {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
match attr.node.value.node {
ast::MetaList(ref n, _) if n == &"serde" => { return None; }
ast::MetaItemKind::List(ref n, _) if n == &"serde" => { return None; }
_ => {}
}
@@ -57,10 +55,18 @@ pub fn register(reg: &mut syntex::Registry) {
fold::Folder::fold_crate(&mut StripAttributeFolder, krate)
}
reg.add_attr("feature(custom_derive)");
reg.add_attr("feature(custom_attribute)");
reg.add_decorator("derive_Serialize", ser::expand_derive_serialize);
reg.add_decorator("derive_Deserialize", de::expand_derive_deserialize);
reg.add_post_expansion_pass(strip_attributes);
}
#[cfg(not(feature = "with-syntex"))]
pub fn register(reg: &mut rustc::plugin::Registry) {
pub fn register(reg: &mut rustc_plugin::Registry) {
reg.register_syntax_extension(
syntax::parse::token::intern("derive_Serialize"),
syntax::ext::base::MultiDecorator(
@@ -70,4 +76,6 @@ pub fn register(reg: &mut rustc::plugin::Registry) {
syntax::parse::token::intern("derive_Deserialize"),
syntax::ext::base::MultiDecorator(
Box::new(de::expand_derive_deserialize)));
reg.register_attribute("serde".to_owned(), AttributeType::Normal);
}
+1 -1
View File
@@ -1,4 +1,4 @@
mod attr;
mod de;
mod field;
mod error;
mod ser;
+368 -245
View File
@@ -4,8 +4,6 @@ use syntax::ast::{
Ident,
MetaItem,
Item,
Expr,
StructDef,
};
use syntax::ast;
use syntax::codemap::Span;
@@ -13,7 +11,8 @@ use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;
use field::struct_field_attrs;
use attr;
use error::Error;
pub fn expand_derive_serialize(
cx: &mut ExtCtxt,
@@ -27,17 +26,38 @@ pub fn expand_derive_serialize(
_ => {
cx.span_err(
meta_item.span,
"`derive` may only be applied to structs and enums");
"`#[derive(Serialize)]` may only be applied to structs and enums");
return;
}
};
let builder = aster::AstBuilder::new().span(span);
let impl_item = match serialize_item(cx, &builder, &item) {
Ok(item) => item,
Err(Error) => {
// An error occured, but it should have been reported already.
return;
}
};
push(Annotatable::Item(impl_item))
}
fn serialize_item(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
item: &Item,
) -> Result<P<ast::Item>, Error> {
let generics = match item.node {
ast::ItemStruct(_, ref generics) => generics,
ast::ItemEnum(_, ref generics) => generics,
_ => cx.bug("expected ItemStruct or ItemEnum in #[derive(Serialize)]")
ast::ItemKind::Struct(_, ref generics) => generics,
ast::ItemKind::Enum(_, ref generics) => generics,
_ => {
cx.span_err(
item.span,
"`#[derive(Serialize)]` may only be applied to structs and enums");
return Err(Error);
}
};
let impl_generics = builder.from_generics(generics.clone())
@@ -50,21 +70,15 @@ pub fn expand_derive_serialize(
.segment(item.ident).with_generics(impl_generics.clone()).build()
.build();
let body = serialize_body(
cx,
&builder,
&item,
&impl_generics,
builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(ty.clone()),
);
let body = try!(serialize_body(cx,
&builder,
&item,
&impl_generics,
ty.clone()));
let where_clause = &impl_generics.where_clause;
let impl_item = quote_item!(cx,
#[automatically_derived]
Ok(quote_item!(cx,
impl $impl_generics ::serde::ser::Serialize for $ty $where_clause {
fn serialize<__S>(&self, serializer: &mut __S) -> ::std::result::Result<(), __S::Error>
where __S: ::serde::ser::Serializer,
@@ -72,9 +86,7 @@ pub fn expand_derive_serialize(
$body
}
}
).unwrap();
push(Annotatable::Item(impl_item))
).unwrap())
}
fn serialize_body(
@@ -83,19 +95,22 @@ fn serialize_body(
item: &Item,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, Error> {
let container_attrs = try!(attr::ContainerAttrs::from_item(cx, item));
match item.node {
ast::ItemStruct(ref struct_def, _) => {
ast::ItemKind::Struct(ref variant_data, _) => {
serialize_item_struct(
cx,
builder,
item,
impl_generics,
ty,
struct_def,
item.span,
variant_data,
&container_attrs,
)
}
ast::ItemEnum(ref enum_def, _) => {
ast::ItemKind::Enum(ref enum_def, _) => {
serialize_item_enum(
cx,
builder,
@@ -103,135 +118,158 @@ fn serialize_body(
impl_generics,
ty,
enum_def,
&container_attrs,
)
}
_ => cx.bug("expected ItemStruct or ItemEnum in #[derive(Serialize)]")
_ => {
cx.span_bug(item.span,
"expected ItemStruct or ItemEnum in #[derive(Serialize)]");
}
}
}
fn serialize_item_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
item: &Item,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
struct_def: &ast::StructDef,
) -> P<ast::Expr> {
let mut named_fields = vec![];
let mut unnamed_fields = 0;
for field in struct_def.fields.iter() {
match field.node.kind {
ast::NamedField(name, _) => { named_fields.push(name); }
ast::UnnamedField(_) => { unnamed_fields += 1; }
}
}
match (named_fields.is_empty(), unnamed_fields == 0) {
(true, true) => {
span: Span,
variant_data: &ast::VariantData,
container_attrs: &attr::ContainerAttrs,
) -> Result<P<ast::Expr>, Error> {
match *variant_data {
ast::VariantData::Unit(_) => {
serialize_unit_struct(
cx,
&builder,
item.ident,
container_attrs,
)
}
(true, false) => {
ast::VariantData::Tuple(ref fields, _) if fields.len() == 1 => {
serialize_newtype_struct(
cx,
container_attrs,
)
}
ast::VariantData::Tuple(ref fields, _) => {
if fields.iter().any(|field| !field.node.kind.is_unnamed()) {
cx.span_bug(span, "tuple struct has named fields")
}
serialize_tuple_struct(
cx,
&builder,
item.ident,
impl_generics,
ty,
unnamed_fields,
fields.len(),
container_attrs,
)
}
(false, true) => {
ast::VariantData::Struct(ref fields, _) => {
if fields.iter().any(|field| field.node.kind.is_unnamed()) {
cx.span_bug(span, "struct has unnamed fields")
}
serialize_struct(
cx,
&builder,
item.ident,
impl_generics,
ty,
struct_def,
named_fields,
fields,
container_attrs,
)
}
(false, false) => {
cx.bug("struct has named and unnamed fields")
}
}
}
fn serialize_unit_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident
) -> P<ast::Expr> {
let type_name = builder.expr().str(type_ident);
container_attrs: &attr::ContainerAttrs,
) -> Result<P<ast::Expr>, Error> {
let type_name = container_attrs.name().serialize_name_expr();
quote_expr!(cx, serializer.visit_named_unit($type_name))
Ok(quote_expr!(cx,
serializer.serialize_unit_struct($type_name)
))
}
fn serialize_newtype_struct(
cx: &ExtCtxt,
container_attrs: &attr::ContainerAttrs,
) -> Result<P<ast::Expr>, Error> {
let type_name = container_attrs.name().serialize_name_expr();
Ok(quote_expr!(cx,
serializer.serialize_newtype_struct($type_name, &self.0)
))
}
fn serialize_tuple_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
fields: usize,
) -> P<ast::Expr> {
container_attrs: &attr::ContainerAttrs,
) -> Result<P<ast::Expr>, Error> {
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
cx,
builder,
ty.clone(),
ty,
builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(ty.clone()),
builder.id("serialize_tuple_struct_elt"),
fields,
impl_generics,
);
let type_name = builder.expr().str(type_ident);
let type_name = container_attrs.name().serialize_name_expr();
quote_expr!(cx, {
Ok(quote_expr!(cx, {
$visitor_struct
$visitor_impl
serializer.visit_named_seq($type_name, Visitor {
serializer.serialize_tuple_struct($type_name, Visitor {
value: self,
state: 0,
_structure_ty: ::std::marker::PhantomData,
_structure_ty: ::std::marker::PhantomData::<&$ty>,
})
})
}))
}
fn serialize_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
struct_def: &StructDef,
fields: Vec<Ident>,
) -> P<ast::Expr> {
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
fields: &[ast::StructField],
container_attrs: &attr::ContainerAttrs,
) -> Result<P<ast::Expr>, Error> {
let (visitor_struct, visitor_impl) = try!(serialize_struct_visitor(
cx,
builder,
ty.clone(),
ty,
struct_def,
builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(ty.clone()),
builder.id("serialize_struct_elt"),
fields,
impl_generics,
fields.iter().map(|field| quote_expr!(cx, &self.value.$field)),
);
false,
));
let type_name = builder.expr().str(type_ident);
let type_name = container_attrs.name().serialize_name_expr();
quote_expr!(cx, {
Ok(quote_expr!(cx, {
$visitor_struct
$visitor_impl
serializer.visit_named_map($type_name, Visitor {
serializer.serialize_struct($type_name, Visitor {
value: self,
state: 0,
_structure_ty: ::std::marker::PhantomData,
_structure_ty: ::std::marker::PhantomData::<&$ty>,
})
})
}))
}
fn serialize_item_enum(
@@ -241,25 +279,31 @@ fn serialize_item_enum(
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
enum_def: &ast::EnumDef,
) -> P<ast::Expr> {
let arms: Vec<ast::Arm> = enum_def.variants.iter()
.map(|variant| {
serialize_variant(
cx,
builder,
type_ident,
impl_generics,
ty.clone(),
variant,
)
})
.collect();
container_attrs: &attr::ContainerAttrs,
) -> Result<P<ast::Expr>, Error> {
let arms: Vec<_> = try!(
enum_def.variants.iter()
.enumerate()
.map(|(variant_index, variant)| {
serialize_variant(
cx,
builder,
type_ident,
impl_generics,
ty.clone(),
variant,
variant_index,
container_attrs,
)
})
.collect()
);
quote_expr!(cx,
Ok(quote_expr!(cx,
match *self {
$arms
}
)
))
}
fn serialize_variant(
@@ -269,65 +313,96 @@ fn serialize_variant(
generics: &ast::Generics,
ty: P<ast::Ty>,
variant: &ast::Variant,
) -> ast::Arm {
let type_name = builder.expr().str(type_ident);
let variant_ident = variant.node.name;
let variant_name = builder.expr().str(variant_ident);
variant_index: usize,
container_attrs: &attr::ContainerAttrs,
) -> Result<ast::Arm, Error> {
let type_name = container_attrs.name().serialize_name_expr();
match variant.node.kind {
ast::TupleVariantKind(ref args) if args.is_empty() => {
let pat = builder.pat().enum_()
.id(type_ident).id(variant_ident).build()
let variant_ident = variant.node.name;
let variant_attrs = try!(attr::VariantAttrs::from_variant(cx, variant));
let variant_name = variant_attrs.name().serialize_name_expr();
match variant.node.data {
ast::VariantData::Unit(_) => {
let pat = builder.pat().path()
.id(type_ident).id(variant_ident)
.build();
quote_arm!(cx,
Ok(quote_arm!(cx,
$pat => {
::serde::ser::Serializer::visit_enum_unit(
::serde::ser::Serializer::serialize_unit_variant(
serializer,
$type_name,
$variant_index,
$variant_name,
)
}
)
}
ast::TupleVariantKind(ref args) => {
let fields: Vec<ast::Ident> = (0 .. args.len())
))
},
ast::VariantData::Tuple(ref fields, _) if fields.len() == 1 => {
let field = builder.id("__simple_value");
let field = builder.pat().ref_id(field);
let pat = builder.pat().enum_()
.id(type_ident).id(variant_ident).build()
.with_pats(Some(field).into_iter())
.build();
Ok(quote_arm!(cx,
$pat => {
::serde::ser::Serializer::serialize_newtype_variant(
serializer,
$type_name,
$variant_index,
$variant_name,
__simple_value,
)
}
))
},
ast::VariantData::Tuple(ref fields, _) => {
let field_names: Vec<ast::Ident> = (0 .. fields.len())
.map(|i| builder.id(format!("__field{}", i)))
.collect();
let pat = builder.pat().enum_()
.id(type_ident).id(variant_ident).build()
.with_pats(fields.iter().map(|field| builder.pat().ref_id(field)))
.with_pats(
field_names.iter()
.map(|field| builder.pat().ref_id(field))
)
.build();
let expr = serialize_tuple_variant(
cx,
builder,
type_name,
variant_index,
variant_name,
generics,
ty,
args,
fields,
field_names,
);
quote_arm!(cx, $pat => { $expr })
Ok(quote_arm!(cx,
$pat => { $expr }
))
}
ast::StructVariantKind(ref struct_def) => {
let fields: Vec<_> = (0 .. struct_def.fields.len())
ast::VariantData::Struct(ref fields, _) => {
let field_names: Vec<_> = (0 .. fields.len())
.map(|i| builder.id(format!("__field{}", i)))
.collect();
let pat = builder.pat().struct_()
.id(type_ident).id(variant_ident).build()
.with_pats(
fields.iter()
.zip(struct_def.fields.iter())
field_names.iter()
.zip(fields.iter())
.map(|(id, field)| {
let name = match field.node.kind {
ast::NamedField(name, _) => name,
ast::UnnamedField(_) => {
cx.bug("struct variant has unnamed fields")
cx.span_bug(field.span, "struct variant has unnamed fields")
}
};
@@ -336,18 +411,21 @@ fn serialize_variant(
)
.build();
let expr = serialize_struct_variant(
let expr = try!(serialize_struct_variant(
cx,
builder,
type_name,
variant_index,
variant_name,
generics,
ty,
struct_def,
fields,
);
field_names,
container_attrs,
));
quote_arm!(cx, $pat => { $expr })
Ok(quote_arm!(cx,
$pat => { $expr }
))
}
}
}
@@ -356,66 +434,16 @@ fn serialize_tuple_variant(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_name: P<ast::Expr>,
variant_index: usize,
variant_name: P<ast::Expr>,
generics: &ast::Generics,
structure_ty: P<ast::Ty>,
args: &[ast::VariantArg],
fields: Vec<Ident>,
fields: &[ast::StructField],
field_names: Vec<Ident>,
) -> P<ast::Expr> {
let variant_ty = builder.ty().tuple()
.with_tys(
args.iter().map(|arg| {
builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(arg.ty.clone())
})
)
.build();
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
cx,
builder,
structure_ty,
variant_ty,
args.len(),
generics,
);
let value_expr = builder.expr().tuple()
.with_exprs(
fields.iter().map(|field| {
builder.expr()
.addr_of()
.id(field)
})
)
.build();
quote_expr!(cx, {
$visitor_struct
$visitor_impl
serializer.visit_enum_seq($type_name, $variant_name, Visitor {
value: $value_expr,
state: 0,
_structure_ty: ::std::marker::PhantomData,
})
})
}
fn serialize_struct_variant(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_name: P<ast::Expr>,
variant_name: P<ast::Expr>,
generics: &ast::Generics,
structure_ty: P<ast::Ty>,
struct_def: &ast::StructDef,
fields: Vec<Ident>,
) -> P<ast::Expr> {
let value_ty = builder.ty().tuple()
.with_tys(
struct_def.fields.iter().map(|field| {
builder.ty()
.ref_()
.lifetime("'__a")
@@ -424,60 +452,144 @@ fn serialize_struct_variant(
)
.build();
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
cx,
builder,
structure_ty.clone(),
variant_ty,
builder.id("serialize_tuple_variant_elt"),
fields.len(),
generics,
);
let value_expr = builder.expr().tuple()
.with_exprs(
fields.iter().map(|field| {
builder.expr()
.addr_of()
.id(field)
field_names.iter().map(|field| {
builder.expr().id(field)
})
)
.build();
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
cx,
builder,
structure_ty,
value_ty,
struct_def,
generics,
(0 .. fields.len()).map(|i| {
builder.expr()
.tup_field(i)
.field("value").self_()
})
);
quote_expr!(cx, {
$visitor_struct
$visitor_impl
serializer.visit_enum_map($type_name, $variant_name, Visitor {
serializer.serialize_tuple_variant($type_name, $variant_index, $variant_name, Visitor {
value: $value_expr,
state: 0,
_structure_ty: ::std::marker::PhantomData,
_structure_ty: ::std::marker::PhantomData::<&$structure_ty>,
})
})
}
fn serialize_struct_variant(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
variant_index: usize,
variant_name: P<ast::Expr>,
generics: &ast::Generics,
ty: P<ast::Ty>,
fields: &[ast::StructField],
field_names: Vec<Ident>,
container_attrs: &attr::ContainerAttrs,
) -> Result<P<ast::Expr>, Error> {
let variant_generics = builder.generics()
.with(generics.clone())
.add_lifetime_bound("'__serde_variant")
.lifetime_name("'__serde_variant")
.build();
let variant_struct = builder.item().struct_("__VariantStruct")
.with_generics(variant_generics.clone())
.with_fields(
fields.iter().map(|field| {
builder.struct_field(field.node.ident().expect("struct has unnamed fields"))
.with_attrs(field.node.attrs.iter().cloned())
.ty()
.ref_()
.lifetime("'__serde_variant")
.build_ty(field.node.ty.clone())
})
)
.field("__serde_container_ty")
.ty().phantom_data().build(ty.clone())
.build();
let variant_expr = builder.expr().struct_id("__VariantStruct")
.with_id_exprs(
fields.iter()
.zip(field_names.iter())
.map(|(field, field_name)| {
(
field.node.ident().expect("struct has unnamed fields"),
builder.expr().id(field_name),
)
})
)
.field("__serde_container_ty").path()
.global()
.id("std").id("marker")
.segment("PhantomData")
.with_ty(ty.clone())
.build()
.build()
.build();
let variant_ty = builder.ty().path()
.segment("__VariantStruct")
.with_generics(variant_generics.clone())
.build()
.build();
let (visitor_struct, visitor_impl) = try!(serialize_struct_visitor(
cx,
builder,
variant_ty.clone(),
variant_ty.clone(),
builder.id("serialize_struct_variant_elt"),
fields,
&variant_generics,
true,
));
let container_name = container_attrs.name().serialize_name_expr();
Ok(quote_expr!(cx, {
$variant_struct
$visitor_struct
$visitor_impl
serializer.serialize_struct_variant(
$container_name,
$variant_index,
$variant_name,
Visitor {
value: $variant_expr,
state: 0,
_structure_ty: ::std::marker::PhantomData,
},
)
}))
}
fn serialize_tuple_struct_visitor(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
structure_ty: P<ast::Ty>,
variant_ty: P<ast::Ty>,
serializer_method: ast::Ident,
fields: usize,
generics: &ast::Generics
) -> (P<ast::Item>, P<ast::Item>) {
let arms: Vec<ast::Arm> = (0 .. fields)
.map(|i| {
let expr = builder.expr()
.tup_field(i)
.field("value").self_();
let expr = builder.expr().method_call(serializer_method)
.id("serializer")
.arg().ref_().tup_field(i).field("value").self_()
.build();
quote_arm!(cx,
$i => {
self.state += 1;
let v = try!(serializer.visit_named_seq_elt(&$expr));
Ok(Some(v))
Ok(Some(try!($expr)))
}
)
})
@@ -494,19 +606,12 @@ fn serialize_tuple_struct_visitor(
.strip_bounds()
.build();
// Variants don't necessarily reference all generic lifetimes and type parameters,
// so to avoid a compilation failure, we'll just add a phantom type to capture these
// unused values.
let structure_ty = builder.ty()
.phantom_data()
.build(structure_ty);
(
quote_item!(cx,
struct Visitor $visitor_impl_generics $where_clause {
state: usize,
value: $variant_ty,
_structure_ty: $structure_ty,
_structure_ty: ::std::marker::PhantomData<&'__a $structure_ty>,
}
).unwrap(),
@@ -533,39 +638,48 @@ fn serialize_tuple_struct_visitor(
)
}
fn serialize_struct_visitor<I>(
fn serialize_struct_visitor(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
structure_ty: P<ast::Ty>,
variant_ty: P<ast::Ty>,
struct_def: &StructDef,
serializer_method: ast::Ident,
fields: &[ast::StructField],
generics: &ast::Generics,
value_exprs: I,
) -> (P<ast::Item>, P<ast::Item>)
where I: Iterator<Item=P<ast::Expr>>,
{
let len = struct_def.fields.len();
is_enum: bool,
) -> Result<(P<ast::Item>, P<ast::Item>), Error> {
let field_attrs = try!(
attr::get_struct_field_attrs(cx, &structure_ty, generics, fields, is_enum)
);
let field_attrs = struct_field_attrs(cx, builder, struct_def);
let arms: Vec<ast::Arm> = field_attrs.into_iter()
.zip(value_exprs)
let arms: Vec<ast::Arm> = fields.iter().zip(field_attrs.iter())
.filter(|&(_, ref field_attr)| !field_attr.skip_serializing_field())
.enumerate()
.map(|(i, (field, value_expr))| {
let key_expr = field.serializer_key_expr(cx);
.map(|(i, (ref field, ref field_attr))| {
let name = field.node.ident().expect("struct has unnamed field");
let key_expr = field_attr.name().serialize_name_expr();
let stmt = if let Some(expr) = field_attr.skip_serializing_field_if() {
Some(quote_stmt!(cx, if $expr { continue; }))
} else {
None
};
let field_expr = match field_attr.serialize_with() {
Some(expr) => expr.clone(),
None => quote_expr!(cx, &self.value.$name),
};
let expr = quote_expr!(cx,
serializer.$serializer_method($key_expr, $field_expr)
);
quote_arm!(cx,
$i => {
self.state += 1;
Ok(
Some(
try!(
serializer.visit_named_map_elt(
$key_expr,
$value_expr,
)
)
)
)
$stmt
return Ok(Some(try!($expr)));
}
)
})
@@ -582,19 +696,26 @@ fn serialize_struct_visitor<I>(
.strip_bounds()
.build();
// Variants don't necessarily reference all generic lifetimes and type parameters,
// so to avoid a compilation failure, we'll just add a phantom type to capture these
// unused values.
let structure_ty = builder.ty()
.phantom_data()
.build(structure_ty);
let len = field_attrs.iter()
.filter(|field_attr| !field_attr.skip_serializing_field())
.map(|field_attr| {
match field_attr.skip_serializing_field_if() {
Some(expr) => {
quote_expr!(cx, if $expr { 0 } else { 1 })
}
None => {
quote_expr!(cx, 1)
}
}
})
.fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr));
(
Ok((
quote_item!(cx,
struct Visitor $visitor_impl_generics $where_clause {
state: usize,
value: $variant_ty,
_structure_ty: $structure_ty,
_structure_ty: ::std::marker::PhantomData<&'__a $structure_ty>,
}
).unwrap(),
@@ -607,9 +728,11 @@ fn serialize_struct_visitor<I>(
fn visit<S>(&mut self, serializer: &mut S) -> ::std::result::Result<Option<()>, S::Error>
where S: ::serde::ser::Serializer,
{
match self.state {
$arms
_ => Ok(None)
loop {
match self.state {
$arms
_ => { return Ok(None); }
}
}
}
@@ -619,5 +742,5 @@ fn serialize_struct_visitor<I>(
}
}
).unwrap(),
)
))
}
+20 -6
View File
@@ -1,19 +1,33 @@
[package]
name = "serde_macros"
version = "0.4.4"
version = "0.7.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
repository = "https://github.com/erickt/rust-serde"
repository = "https://github.com/serde-rs/serde"
documentation = "https://github.com/serde-rs/serde"
keywords = ["serde", "serialization"]
[lib]
name = "serde_macros"
plugin = true
[features]
nightly-testing = ["clippy", "serde/nightly-testing", "serde_codegen/nightly-testing"]
[dependencies]
serde_codegen = { version = "*", path = "../serde_codegen", default-features = false, features = ["nightly"] }
clippy = { version = "^0.*", optional = true }
serde_codegen = { version = "^0.7.0", path = "../serde_codegen", default-features = false, features = ["nightly"] }
[dev-dependencies]
num = "*"
rustc-serialize = "*"
serde = { version = "*", path = "../serde", features = ["nightly"] }
compiletest_rs = "^0.0.11"
rustc-serialize = "^0.3.16"
serde = { version = "^0.7.0", path = "../serde" }
[[test]]
name = "test"
path = "tests/test.rs"
[[bench]]
name = "bench"
path = "benches/bench.rs"
+1 -1
View File
@@ -1,7 +1,7 @@
#![feature(custom_attribute, custom_derive, plugin, test)]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![plugin(serde_macros)]
extern crate num;
extern crate rustc_serialize;
extern crate serde;
extern crate test;
-64
View File
@@ -1,64 +0,0 @@
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
use std::collections::BTreeMap;
use serde::json;
// Creating serializable types with serde is quite simple with `serde_macros`. It implements a
// syntax extension that automatically generates the necessary serde trait implementations.
#[derive(Debug, Serialize, Deserialize)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 5, y: 6 };
// Serializing to JSON is pretty simple by using the `to_string` method:
let serialized_point = json::to_string(&point).unwrap();
println!("{}", serialized_point);
// prints:
//
// {"x":5,"y":6}
// There is also support for pretty printing using `to_string_pretty`:
let serialized_point = json::to_string_pretty(&point).unwrap();
println!("{}", serialized_point);
// prints:
//
// {
// "x":5,
// "y":6
// }
// Values can also be deserialized with the same style using `from_str`:
let deserialized_point: Point = json::from_str(&serialized_point).unwrap();
println!("{:?}", deserialized_point);
// prints:
//
// Point { x: 5, y: 6 }
// `Point`s aren't the only type that can be serialized to. Because `Point` members have the
// same type, they can be also serialized into a map. Also,
let deserialized_map: BTreeMap<String, i64> = json::from_str(&serialized_point).unwrap();
println!("{:?}", deserialized_map);
// prints:
//
// {"x": 5, "y": 6}
// If you need to accept arbitrary data, you can also deserialize into `json::Value`, which
// can represent all JSON values.
let deserialized_value: json::Value = json::from_str(&serialized_point).unwrap();
println!("{:?}", deserialized_value);
// prints:
//
// {"x":5,"y":6}
}
+4 -2
View File
@@ -1,10 +1,12 @@
#![feature(plugin_registrar, rustc_private)]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
extern crate serde_codegen;
extern crate rustc;
extern crate rustc_plugin;
#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut rustc::plugin::Registry) {
pub fn plugin_registrar(reg: &mut rustc_plugin::Registry) {
serde_codegen::register(reg);
}
@@ -0,0 +1,30 @@
#![feature(custom_attribute, custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
#[derive(Serialize)]
#[serde(abc="xyz")] //~ unknown serde container attribute `abc = "xyz"`
struct Foo {
x: u32,
}
#[derive(Deserialize)]
#[serde(abc="xyz")] //~ unknown serde container attribute `abc = "xyz"`
struct Foo {
x: u32,
}
#[derive(Serialize)]
struct Foo {
#[serde(abc="xyz")] //~ unknown serde field attribute `abc = "xyz"`
x: u32,
}
#[derive(Deserialize)]
struct Foo {
#[serde(abc="xyz")] //~ unknown serde field attribute `abc = "xyz"`
x: u32,
}
fn main() { }
+25
View File
@@ -0,0 +1,25 @@
extern crate compiletest_rs as compiletest;
use std::path::PathBuf;
use std::env::var;
fn run_mode(mode: &'static str) {
let mut config = compiletest::default_config();
let cfg_mode = mode.parse().ok().expect("Invalid mode");
config.target_rustcflags = Some("-L target/debug/ -L target/debug/deps/".to_owned());
if let Ok(name) = var::<&str>("TESTNAME") {
let s : String = name.to_owned();
config.filter = Some(s)
}
config.mode = cfg_mode;
config.src_base = PathBuf::from(format!("tests/{}", mode));
compiletest::run_tests(&config);
}
#[test]
fn compile_test() {
run_mode("compile-fail");
}
+2
View File
@@ -5,3 +5,5 @@ extern crate serde;
extern crate test;
include!("../../serde_tests/tests/test.rs.in");
mod compile_tests;
+11 -6
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_tests"
version = "0.4.3"
version = "0.6.3"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
@@ -10,16 +10,21 @@ readme = "README.md"
keywords = ["serialization"]
build = "build.rs"
[features]
nightly-testing = ["clippy", "serde/nightly-testing", "serde_codegen/nightly-testing"]
[build-dependencies]
syntex = { version = "*", optional = true }
syntex_syntax = { version = "*" }
syntex = { version = "^0.29.0" }
syntex_syntax = { version = "^0.29.0" }
serde_codegen = { version = "*", path = "../serde_codegen", features = ["with-syntex"] }
[dev-dependencies]
num = "*"
rustc-serialize = "*"
rustc-serialize = "^0.3.16"
serde = { version = "*", path = "../serde" }
syntex = "*"
syntex = "^0.29.0"
[dependencies]
clippy = { version = "^0.*", optional = true }
[[test]]
name = "test"
+2 -1
View File
@@ -1,6 +1,7 @@
#![feature(test)]
#![cfg_attr(feature = "nightly", feature(plugin))]
#![cfg_attr(feature = "nightly", plugin(clippy))]
extern crate num;
extern crate rustc_serialize;
extern crate serde;
extern crate test;
-1
View File
@@ -1,5 +1,4 @@
mod bench_enum;
mod bench_log;
mod bench_map;
mod bench_struct;
mod bench_vec;
+98 -76
View File
@@ -1,4 +1,6 @@
use test::Bencher;
use std::error;
use std::fmt;
use rustc_serialize::{Decoder, Decodable};
use serde;
use serde::de::{Deserializer, Deserialize};
@@ -15,18 +17,34 @@ pub enum Animal {
#[derive(Debug)]
pub enum Error {
EndOfStreamError,
SyntaxError,
EndOfStream,
Syntax,
}
impl serde::de::Error for Error {
fn syntax_error() -> Error { Error::SyntaxError }
fn custom<T: Into<String>>(_: T) -> Error { Error::Syntax }
fn end_of_stream_error() -> Error { Error::EndOfStreamError }
fn end_of_stream() -> Error { Error::EndOfStream }
fn unknown_field_error(_: &str) -> Error { Error::SyntaxError }
fn unknown_field(_: &str) -> Error { Error::Syntax }
fn missing_field_error(_: &'static str) -> Error { Error::SyntaxError }
fn missing_field(_: &'static str) -> Error { Error::Syntax }
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(format!("{:?}", self).as_ref())
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Deserialization Error"
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
//////////////////////////////////////////////////////////////////////////////
@@ -36,12 +54,11 @@ mod decoder {
use super::{Animal, Error};
use super::Animal::{Dog, Frog};
use self::State::{AnimalState, IsizeState, StringState};
enum State {
AnimalState(Animal),
IsizeState(isize),
StringState(String),
Animal(Animal),
Isize(isize),
String(String),
}
pub struct AnimalDecoder {
@@ -53,7 +70,7 @@ mod decoder {
#[inline]
pub fn new(animal: Animal) -> AnimalDecoder {
AnimalDecoder {
stack: vec!(AnimalState(animal)),
stack: vec!(State::Animal(animal)),
}
}
}
@@ -61,35 +78,35 @@ mod decoder {
impl Decoder for AnimalDecoder {
type Error = Error;
fn error(&mut self, _: &str) -> Error { Error::SyntaxError }
fn error(&mut self, _: &str) -> Error { Error::Syntax }
// 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) }
fn read_nil(&mut self) -> Result<(), Error> { Err(Error::Syntax) }
fn read_usize(&mut self) -> Result<usize, Error> { Err(Error::Syntax) }
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::Syntax) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::Syntax) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::Syntax) }
fn read_u8(&mut self) -> Result<u8, Error> { Err(Error::Syntax) }
#[inline]
fn read_isize(&mut self) -> Result<isize, Error> {
match self.stack.pop() {
Some(IsizeState(x)) => Ok(x),
_ => Err(Error::SyntaxError),
Some(State::Isize(x)) => Ok(x),
_ => Err(Error::Syntax),
}
}
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_i64(&mut self) -> Result<i64, Error> { Err(Error::Syntax) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::Syntax) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::Syntax) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::Syntax) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::Syntax) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::Syntax) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::Syntax) }
fn read_char(&mut self) -> Result<char, Error> { Err(Error::Syntax) }
#[inline]
fn read_str(&mut self) -> Result<String, Error> {
match self.stack.pop() {
Some(StringState(x)) => Ok(x),
_ => Err(Error::SyntaxError),
Some(State::String(x)) => Ok(x),
_ => Err(Error::Syntax),
}
}
@@ -99,15 +116,15 @@ mod decoder {
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
match self.stack.pop() {
Some(AnimalState(animal)) => {
self.stack.push(AnimalState(animal));
Some(State::Animal(animal)) => {
self.stack.push(State::Animal(animal));
if name == "Animal" {
f(self)
} else {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
_ => Err(Error::SyntaxError)
_ => Err(Error::Syntax)
}
}
@@ -116,18 +133,18 @@ mod decoder {
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));
Some(State::Animal(Dog)) => "Dog",
Some(State::Animal(Frog(x0, x1))) => {
self.stack.push(State::Isize(x1));
self.stack.push(State::String(x0));
"Frog"
}
_ => { return Err(Error::SyntaxError); }
_ => { return Err(Error::Syntax); }
};
let idx = match names.iter().position(|n| *n == name) {
Some(idx) => idx,
None => { return Err(Error::SyntaxError); }
None => { return Err(Error::Syntax); }
};
f(self, idx)
@@ -143,56 +160,56 @@ mod decoder {
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)
Err(Error::Syntax)
}
fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_struct_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple<T, F>(&mut self, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
// Specialized types:
fn read_option<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder, bool) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
#[inline]
@@ -212,19 +229,19 @@ mod decoder {
fn read_map<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_map_elt_key<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_map_elt_val<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut AnimalDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
}
@@ -238,10 +255,10 @@ mod deserializer {
#[derive(Debug)]
enum State {
AnimalState(Animal),
IsizeState(isize),
StrState(&'static str),
StringState(String),
Animal(Animal),
Isize(isize),
Str(&'static str),
String(String),
UnitState,
}
@@ -253,7 +270,7 @@ mod deserializer {
#[inline]
pub fn new(animal: Animal) -> AnimalDeserializer {
AnimalDeserializer {
stack: vec!(State::AnimalState(animal)),
stack: vec!(State::Animal(animal)),
}
}
}
@@ -262,57 +279,60 @@ mod deserializer {
type Error = Error;
#[inline]
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.stack.pop() {
Some(State::IsizeState(value)) => {
Some(State::Isize(value)) => {
visitor.visit_isize(value)
}
Some(State::StringState(value)) => {
Some(State::String(value)) => {
visitor.visit_string(value)
}
Some(State::StrState(value)) => {
Some(State::Str(value)) => {
visitor.visit_str(value)
}
Some(State::UnitState) => {
visitor.visit_unit()
}
Some(_) => {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
None => {
Err(Error::EndOfStreamError)
Err(Error::EndOfStream)
}
}
}
#[inline]
fn visit_enum<V>(&mut self, _name: &str, mut visitor: V) -> Result<V::Value, Error>
fn deserialize_enum<V>(&mut self,
_name: &str,
_variants: &[&str],
mut visitor: V) -> Result<V::Value, Error>
where V: de::EnumVisitor,
{
match self.stack.pop() {
Some(State::AnimalState(Animal::Dog)) => {
Some(State::Animal(Animal::Dog)) => {
self.stack.push(State::UnitState);
self.stack.push(State::StrState("Dog"));
self.stack.push(State::Str("Dog"));
visitor.visit(DogVisitor {
de: self,
})
}
Some(State::AnimalState(Animal::Frog(x0, x1))) => {
self.stack.push(State::IsizeState(x1));
self.stack.push(State::StringState(x0));
self.stack.push(State::StrState("Frog"));
Some(State::Animal(Animal::Frog(x0, x1))) => {
self.stack.push(State::Isize(x1));
self.stack.push(State::String(x0));
self.stack.push(State::Str("Frog"));
visitor.visit(FrogVisitor {
de: self,
state: 0,
})
}
Some(_) => {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
None => {
Err(Error::EndOfStreamError)
Err(Error::EndOfStream)
}
}
}
@@ -350,7 +370,9 @@ mod deserializer {
de::Deserialize::deserialize(self.de)
}
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn visit_tuple<V>(&mut self,
_len: usize,
mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_seq(self)
@@ -382,7 +404,7 @@ mod deserializer {
if self.state == 2 {
Ok(())
} else {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
@@ -410,7 +432,7 @@ fn bench_decoder_dog(b: &mut Bencher) {
#[bench]
fn bench_decoder_frog(b: &mut Bencher) {
b.iter(|| {
let animal = Animal::Frog("Henry".to_string(), 349);
let animal = Animal::Frog("Henry".to_owned(), 349);
let mut d = decoder::AnimalDecoder::new(animal.clone());
let value: Animal = Decodable::decode(&mut d).unwrap();
@@ -434,7 +456,7 @@ fn bench_deserializer_dog(b: &mut Bencher) {
#[bench]
fn bench_deserializer_frog(b: &mut Bencher) {
b.iter(|| {
let animal = Animal::Frog("Henry".to_string(), 349);
let animal = Animal::Frog("Henry".to_owned(), 349);
let mut d = deserializer::AnimalDeserializer::new(animal.clone());
let value: Animal = Deserialize::deserialize(&mut d).unwrap();
File diff suppressed because it is too large Load Diff
+90 -74
View File
@@ -1,4 +1,6 @@
use std::fmt::Debug;
use std::fmt;
use std::error;
use std::collections::HashMap;
use test::Bencher;
@@ -12,22 +14,37 @@ use serde::de::{Deserializer, Deserialize};
#[derive(PartialEq, Debug)]
pub enum Error {
EndOfStream,
SyntaxError,
Syntax,
MissingField,
}
impl serde::de::Error for Error {
fn syntax_error() -> Error { Error::SyntaxError }
fn custom<T: Into<String>>(_: T) -> Error { Error::Syntax }
fn end_of_stream_error() -> Error { Error::EndOfStream }
fn end_of_stream() -> Error { Error::EndOfStream }
fn unknown_field_error(_: &str) -> Error { Error::SyntaxError }
fn unknown_field(_: &str) -> Error { Error::Syntax }
fn missing_field_error(_: &'static str) -> Error {
fn missing_field(_: &'static str) -> Error {
Error::MissingField
}
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(format!("{:?}", self).as_ref())
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Deserialization Error"
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
//////////////////////////////////////////////////////////////////////////////
mod decoder {
@@ -36,11 +53,10 @@ mod decoder {
use rustc_serialize;
use super::Error;
use self::Value::{StringValue, IsizeValue};
enum Value {
StringValue(String),
IsizeValue(isize),
String(String),
Isize(isize),
}
pub struct IsizeDecoder {
@@ -64,37 +80,37 @@ mod decoder {
type Error = Error;
fn error(&mut self, _msg: &str) -> Error {
Error::SyntaxError
Error::Syntax
}
// 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) }
fn read_nil(&mut self) -> Result<(), Error> { Err(Error::Syntax) }
fn read_usize(&mut self) -> Result<usize, Error> { Err(Error::Syntax) }
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::Syntax) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::Syntax) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::Syntax) }
fn read_u8(&mut self) -> Result<u8, Error> { Err(Error::Syntax) }
#[inline]
fn read_isize(&mut self) -> Result<isize, Error> {
match self.stack.pop() {
Some(IsizeValue(x)) => Ok(x),
Some(_) => Err(Error::SyntaxError),
Some(Value::Isize(x)) => Ok(x),
Some(_) => Err(Error::Syntax),
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) }
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::Syntax) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::Syntax) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::Syntax) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::Syntax) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::Syntax) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::Syntax) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::Syntax) }
fn read_char(&mut self) -> Result<char, Error> { Err(Error::Syntax) }
#[inline]
fn read_str(&mut self) -> Result<String, Error> {
match self.stack.pop() {
Some(StringValue(x)) => Ok(x),
Some(_) => Err(Error::SyntaxError),
Some(Value::String(x)) => Ok(x),
Some(_) => Err(Error::Syntax),
None => Err(Error::EndOfStream),
}
}
@@ -103,86 +119,86 @@ mod decoder {
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)
Err(Error::Syntax)
}
fn read_enum_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_struct_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_struct_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple<T, F>(&mut self, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
// Specialized types:
fn read_option<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder, bool) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_seq<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_seq_elt<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut IsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
#[inline]
@@ -198,12 +214,12 @@ mod decoder {
{
match self.iter.next() {
Some((key, value)) => {
self.stack.push(IsizeValue(value));
self.stack.push(StringValue(key));
self.stack.push(Value::Isize(value));
self.stack.push(Value::String(key));
f(self)
}
None => {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
}
@@ -230,8 +246,8 @@ mod deserializer {
#[derive(PartialEq, Debug)]
enum State {
StartState,
KeyState(String),
ValueState(isize),
Key(String),
Value(isize),
}
pub struct IsizeDeserializer {
@@ -252,17 +268,17 @@ mod deserializer {
impl de::Deserializer for IsizeDeserializer {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.stack.pop() {
Some(State::StartState) => {
visitor.visit_map(self)
}
Some(State::KeyState(key)) => {
Some(State::Key(key)) => {
visitor.visit_string(key)
}
Some(State::ValueState(value)) => {
Some(State::Value(value)) => {
visitor.visit_isize(value)
}
None => {
@@ -280,8 +296,8 @@ mod deserializer {
{
match self.iter.next() {
Some((key, value)) => {
self.stack.push(State::ValueState(value));
self.stack.push(State::KeyState(key));
self.stack.push(State::Value(value));
self.stack.push(State::Key(key));
Ok(Some(try!(de::Deserialize::deserialize(self))))
}
None => {
@@ -298,7 +314,7 @@ mod deserializer {
fn end(&mut self) -> Result<(), Error> {
match self.iter.next() {
Some(_) => Err(Error::SyntaxError),
Some(_) => Err(Error::Syntax),
None => Ok(()),
}
}
@@ -315,14 +331,14 @@ mod deserializer {
#[inline]
fn next(&mut self) -> Option<Result<de::Token, Error>> {
match self.stack.pop() {
Some(StartState) => {
Some(State::StartState) => {
self.stack.push(KeyOrEndState);
Some(Ok(de::Token::MapStart(self.len)))
}
Some(KeyOrEndState) => {
Some(State::KeyOrEndState) => {
match self.iter.next() {
Some((key, value)) => {
self.stack.push(ValueState(value));
self.stack.push(Value(value));
Some(Ok(de::Token::String(key)))
}
None => {
@@ -331,7 +347,7 @@ mod deserializer {
}
}
}
Some(ValueState(x)) => {
Some(State::Value(x)) => {
self.stack.push(KeyOrEndState);
Some(Ok(de::Token::Isize(x)))
}
@@ -347,30 +363,30 @@ mod deserializer {
impl de::Deserializer<Error> for IsizeDeserializer {
#[inline]
fn end_of_stream_error(&mut self) -> Error {
fn end_of_stream(&mut self) -> Error {
EndOfStream
}
#[inline]
fn syntax_error(&mut self, _token: de::Token, _expected: &[de::TokenKind]) -> Error {
SyntaxError
fn syntax(&mut self, _token: de::Token, _expected: &[de::TokenKind]) -> Error {
Syntax
}
#[inline]
fn unexpected_name_error(&mut self, _token: de::Token) -> Error {
SyntaxError
fn unexpected_name(&mut self, _token: de::Token) -> Error {
Syntax
}
#[inline]
fn conversion_error(&mut self, _token: de::Token) -> Error {
SyntaxError
Syntax
}
#[inline]
fn missing_field<
T: de::Deserialize<IsizeDeserializer, Error>
>(&mut self, _field: &'static str) -> Result<T, Error> {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
*/
@@ -399,7 +415,7 @@ fn bench_decoder_000(b: &mut Bencher) {
fn bench_decoder_003(b: &mut Bencher) {
b.iter(|| {
let mut m: HashMap<String, isize> = HashMap::new();
for i in (0 .. 3) {
for i in 0 .. 3 {
m.insert(i.to_string(), i);
}
run_decoder(decoder::IsizeDecoder::new(m.clone()), m)
@@ -410,21 +426,21 @@ fn bench_decoder_003(b: &mut Bencher) {
fn bench_decoder_100(b: &mut Bencher) {
b.iter(|| {
let mut m: HashMap<String, isize> = HashMap::new();
for i in (0 .. 100) {
for i in 0 .. 100 {
m.insert(i.to_string(), i);
}
run_decoder(decoder::IsizeDecoder::new(m.clone()), m)
})
}
fn run_deserializer<
D: Deserializer<Error=E>,
E: Debug,
T: Clone + PartialEq + Debug + Deserialize
>(mut d: D, value: T) {
let v: T = Deserialize::deserialize(&mut d).unwrap();
fn run_deserializer<D, T>(mut d: D, value: T)
where D: Deserializer,
D::Error: Debug + PartialEq,
T: Clone + PartialEq + Debug + Deserialize
{
let v = T::deserialize(&mut d);
assert_eq!(value, v);
assert_eq!(Ok(value), v);
}
#[bench]
@@ -439,7 +455,7 @@ fn bench_deserializer_000(b: &mut Bencher) {
fn bench_deserializer_003(b: &mut Bencher) {
b.iter(|| {
let mut m: HashMap<String, isize> = HashMap::new();
for i in (0 .. 3) {
for i in 0 .. 3 {
m.insert(i.to_string(), i);
}
run_deserializer(deserializer::IsizeDeserializer::new(m.clone()), m)
@@ -450,7 +466,7 @@ fn bench_deserializer_003(b: &mut Bencher) {
fn bench_deserializer_100(b: &mut Bencher) {
b.iter(|| {
let mut m: HashMap<String, isize> = HashMap::new();
for i in (0 .. 100) {
for i in 0 .. 100 {
m.insert(i.to_string(), i);
}
run_deserializer(deserializer::IsizeDeserializer::new(m.clone()), m)
+150 -142
View File
@@ -1,5 +1,7 @@
use std::collections::HashMap;
use test::Bencher;
use std::fmt;
use std::error;
use rustc_serialize::{Decoder, Decodable};
@@ -27,54 +29,57 @@ pub struct Outer {
#[derive(Debug, PartialEq)]
pub enum Error {
EndOfStream,
SyntaxError,
Syntax,
MissingField,
OtherError,
}
impl serde::de::Error for Error {
fn syntax_error() -> Error { Error::SyntaxError }
fn custom<T: Into<String>>(_: T) -> Error { Error::Syntax }
fn end_of_stream_error() -> Error { Error::EndOfStream }
fn end_of_stream() -> Error { Error::EndOfStream }
fn unknown_field_error(_: &str) -> Error { Error::SyntaxError }
fn unknown_field(_: &str) -> Error { Error::Syntax }
fn missing_field_error(_: &'static str) -> Error {
fn missing_field(_: &'static str) -> Error {
Error::MissingField
}
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(format!("{:?}", self).as_ref())
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Deserialization Error"
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
mod decoder {
use std::collections::HashMap;
use rustc_serialize::Decoder;
use super::{Outer, Inner, Error};
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),
Outer(Outer),
Inner(Inner),
Null,
Usize(usize),
Char(char),
String(String),
Field(&'static str),
Vec(Vec<Inner>),
Map(HashMap<String, Option<char>>),
Option(bool),
}
pub struct OuterDecoder {
@@ -86,7 +91,7 @@ mod decoder {
#[inline]
pub fn new(animal: Outer) -> OuterDecoder {
OuterDecoder {
stack: vec!(OuterState(animal)),
stack: vec!(State::Outer(animal)),
}
}
}
@@ -102,41 +107,41 @@ mod decoder {
#[inline]
fn read_nil(&mut self) -> Result<(), Error> {
match self.stack.pop() {
Some(NullState) => Ok(()),
_ => Err(Error::SyntaxError),
Some(State::Null) => Ok(()),
_ => Err(Error::Syntax),
}
}
#[inline]
fn read_usize(&mut self) -> Result<usize, Error> {
match self.stack.pop() {
Some(UsizeState(value)) => Ok(value),
_ => Err(Error::SyntaxError),
Some(State::Usize(value)) => Ok(value),
_ => Err(Error::Syntax),
}
}
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_u64(&mut self) -> Result<u64, Error> { Err(Error::Syntax) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::Syntax) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::Syntax) }
fn read_u8(&mut self) -> Result<u8, Error> { Err(Error::Syntax) }
fn read_isize(&mut self) -> Result<isize, Error> { Err(Error::Syntax) }
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::Syntax) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::Syntax) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::Syntax) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::Syntax) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::Syntax) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::Syntax) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::Syntax) }
#[inline]
fn read_char(&mut self) -> Result<char, Error> {
match self.stack.pop() {
Some(CharState(c)) => Ok(c),
_ => Err(Error::SyntaxError),
Some(State::Char(c)) => Ok(c),
_ => Err(Error::Syntax),
}
}
#[inline]
fn read_str(&mut self) -> Result<String, Error> {
match self.stack.pop() {
Some(StringState(value)) => Ok(value),
_ => Err(Error::SyntaxError),
Some(State::String(value)) => Ok(value),
_ => Err(Error::Syntax),
}
}
@@ -144,31 +149,31 @@ mod decoder {
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)
Err(Error::Syntax)
}
fn read_enum_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_struct_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
#[inline]
@@ -176,31 +181,31 @@ mod decoder {
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
match self.stack.pop() {
Some(OuterState(Outer { inner })) => {
Some(State::Outer(Outer { inner })) => {
if s_name == "Outer" {
self.stack.push(VecState(inner));
self.stack.push(FieldState("inner"));
self.stack.push(State::Vec(inner));
self.stack.push(State::Field("inner"));
f(self)
} else {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
Some(InnerState(Inner { a: (), b, c })) => {
Some(State::Inner(Inner { a: (), b, c })) => {
if s_name == "Inner" {
self.stack.push(MapState(c));
self.stack.push(FieldState("c"));
self.stack.push(State::Map(c));
self.stack.push(State::Field("c"));
self.stack.push(UsizeState(b));
self.stack.push(FieldState("b"));
self.stack.push(State::Usize(b));
self.stack.push(State::Field("b"));
self.stack.push(NullState);
self.stack.push(FieldState("a"));
self.stack.push(State::Null);
self.stack.push(State::Field("a"));
f(self)
} else {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
_ => Err(Error::SyntaxError),
_ => Err(Error::Syntax),
}
}
#[inline]
@@ -208,39 +213,39 @@ mod decoder {
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
match self.stack.pop() {
Some(FieldState(name)) => {
Some(State::Field(name)) => {
if f_name == name {
f(self)
} else {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
_ => Err(Error::SyntaxError)
_ => Err(Error::Syntax)
}
}
fn read_tuple<T, F>(&mut self, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut OuterDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
// Specialized types:
@@ -249,8 +254,8 @@ mod decoder {
F: FnOnce(&mut OuterDecoder, bool) -> Result<T, Error>,
{
match self.stack.pop() {
Some(OptionState(b)) => f(self, b),
_ => Err(Error::SyntaxError),
Some(State::Option(b)) => f(self, b),
_ => Err(Error::Syntax),
}
}
@@ -259,14 +264,14 @@ mod decoder {
F: FnOnce(&mut OuterDecoder, usize) -> Result<T, Error>,
{
match self.stack.pop() {
Some(VecState(value)) => {
Some(State::Vec(value)) => {
let len = value.len();
for inner in value.into_iter().rev() {
self.stack.push(InnerState(inner));
self.stack.push(State::Inner(inner));
}
f(self, len)
}
_ => Err(Error::SyntaxError)
_ => Err(Error::Syntax)
}
}
#[inline]
@@ -281,23 +286,23 @@ mod decoder {
F: FnOnce(&mut OuterDecoder, usize) -> Result<T, Error>,
{
match self.stack.pop() {
Some(MapState(map)) => {
Some(State::Map(map)) => {
let len = map.len();
for (key, value) in map {
match value {
Some(c) => {
self.stack.push(CharState(c));
self.stack.push(OptionState(true));
self.stack.push(State::Char(c));
self.stack.push(State::Option(true));
}
None => {
self.stack.push(OptionState(false));
self.stack.push(State::Option(false));
}
}
self.stack.push(StringState(key));
self.stack.push(State::String(key));
}
f(self, len)
}
_ => Err(Error::SyntaxError),
_ => Err(Error::Syntax),
}
}
#[inline]
@@ -328,16 +333,16 @@ mod deserializer {
#[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>>),
Outer(Outer),
Inner(Inner),
Str(&'static str),
Null,
Usize(usize),
Char(char),
String(String),
Option(bool),
Vec(Vec<Inner>),
Map(HashMap<String, Option<char>>),
}
pub struct OuterDeserializer {
@@ -348,7 +353,7 @@ mod deserializer {
#[inline]
pub fn new(outer: Outer) -> OuterDeserializer {
OuterDeserializer {
stack: vec!(State::OuterState(outer)),
stack: vec!(State::Outer(outer)),
}
}
}
@@ -356,78 +361,81 @@ mod deserializer {
impl de::Deserializer for OuterDeserializer {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.stack.pop() {
Some(State::VecState(value)) => {
Some(State::Vec(value)) => {
visitor.visit_seq(OuterSeqVisitor {
de: self,
iter: value.into_iter(),
})
}
Some(State::MapState(value)) => {
Some(State::Map(value)) => {
visitor.visit_map(MapVisitor {
de: self,
iter: value.into_iter(),
})
}
Some(State::NullState) => {
Some(State::Null) => {
visitor.visit_unit()
}
Some(State::UsizeState(x)) => {
Some(State::Usize(x)) => {
visitor.visit_usize(x)
}
Some(State::CharState(x)) => {
Some(State::Char(x)) => {
visitor.visit_char(x)
}
Some(State::StrState(x)) => {
Some(State::Str(x)) => {
visitor.visit_str(x)
}
Some(State::StringState(x)) => {
Some(State::String(x)) => {
visitor.visit_string(x)
}
Some(State::OptionState(false)) => {
Some(State::Option(false)) => {
visitor.visit_none()
}
Some(State::OptionState(true)) => {
Some(State::Option(true)) => {
visitor.visit_some(self)
}
Some(_) => Err(Error::SyntaxError),
Some(_) => Err(Error::Syntax),
None => Err(Error::EndOfStream),
}
}
fn visit_named_map<V>(&mut self, name: &str, mut visitor: V) -> Result<V::Value, Error>
fn deserialize_struct<V>(&mut self,
name: &str,
_fields: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.stack.pop() {
Some(State::OuterState(Outer { inner })) => {
Some(State::Outer(Outer { inner })) => {
if name != "Outer" {
return Err(Error::SyntaxError);
return Err(Error::Syntax);
}
self.stack.push(State::VecState(inner));
self.stack.push(State::StrState("inner"));
self.stack.push(State::Vec(inner));
self.stack.push(State::Str("inner"));
visitor.visit_map(OuterMapVisitor {
de: self,
state: 0,
})
}
Some(State::InnerState(Inner { a: (), b, c })) => {
Some(State::Inner(Inner { a: (), b, c })) => {
if name != "Inner" {
return Err(Error::SyntaxError);
return Err(Error::Syntax);
}
self.stack.push(State::MapState(c));
self.stack.push(State::StrState("c"));
self.stack.push(State::Map(c));
self.stack.push(State::Str("c"));
self.stack.push(State::UsizeState(b));
self.stack.push(State::StrState("b"));
self.stack.push(State::Usize(b));
self.stack.push(State::Str("b"));
self.stack.push(State::NullState);
self.stack.push(State::StrState("a"));
self.stack.push(State::Null);
self.stack.push(State::Str("a"));
visitor.visit_map(InnerMapVisitor {
de: self,
@@ -435,7 +443,7 @@ mod deserializer {
})
}
_ => {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
}
@@ -473,7 +481,7 @@ mod deserializer {
if self.state == 1 {
Ok(())
} else {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
@@ -496,7 +504,7 @@ mod deserializer {
{
match self.iter.next() {
Some(value) => {
self.de.stack.push(State::InnerState(value));
self.de.stack.push(State::Inner(value));
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
None => {
@@ -507,7 +515,7 @@ mod deserializer {
fn end(&mut self) -> Result<(), Error> {
match self.iter.next() {
Some(_) => Err(Error::SyntaxError),
Some(_) => Err(Error::Syntax),
None => Ok(()),
}
}
@@ -549,7 +557,7 @@ mod deserializer {
if self.state == 3 {
Ok(())
} else {
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
@@ -572,14 +580,14 @@ mod deserializer {
{
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));
self.de.stack.push(State::Char(value));
self.de.stack.push(State::Option(true));
self.de.stack.push(State::String(key));
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
Some((key, None)) => {
self.de.stack.push(State::OptionState(false));
self.de.stack.push(State::StringState(key));
self.de.stack.push(State::Option(false));
self.de.stack.push(State::String(key));
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
None => {
@@ -596,7 +604,7 @@ mod deserializer {
fn end(&mut self) -> Result<(), Error> {
match self.iter.next() {
Some(_) => Err(Error::SyntaxError),
Some(_) => Err(Error::Syntax),
None => Ok(()),
}
}
@@ -611,7 +619,7 @@ mod deserializer {
fn bench_decoder_0_0(b: &mut Bencher) {
b.iter(|| {
let mut map = HashMap::new();
map.insert("abc".to_string(), Some('c'));
map.insert("abc".to_owned(), Some('c'));
let outer = Outer {
inner: vec!(),
@@ -650,11 +658,11 @@ fn bench_decoder_1_0(b: &mut Bencher) {
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'));
map.insert("1".to_owned(), Some('a'));
map.insert("2".to_owned(), None);
map.insert("3".to_owned(), Some('b'));
map.insert("4".to_owned(), None);
map.insert("5".to_owned(), Some('c'));
let outer = Outer {
inner: vec!(
@@ -713,11 +721,11 @@ fn bench_deserializer_1_0(b: &mut Bencher) {
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'));
map.insert("1".to_owned(), Some('a'));
map.insert("2".to_owned(), None);
map.insert("3".to_owned(), Some('b'));
map.insert("4".to_owned(), None);
map.insert("5".to_owned(), Some('c'));
let outer = Outer {
inner: vec!(
+116 -99
View File
@@ -1,4 +1,6 @@
use std::fmt::Debug;
use std::fmt;
use std::error;
use test::Bencher;
use rustc_serialize::{Decoder, Decodable};
@@ -10,20 +12,35 @@ use serde::de::{Deserializer, Deserialize};
#[derive(PartialEq, Debug)]
pub enum Error {
EndOfStreamError,
SyntaxError,
EndOfStream,
Syntax,
}
impl serde::de::Error for Error {
fn syntax_error() -> Error { Error::SyntaxError }
fn custom<T: Into<String>>(_: T) -> Error { Error::Syntax }
fn end_of_stream_error() -> Error { Error::EndOfStreamError }
fn end_of_stream() -> Error { Error::EndOfStream }
fn unknown_field_error(_: &str) -> Error { Error::SyntaxError }
fn unknown_field(_: &str) -> Error { Error::Syntax }
fn missing_field_error(_: &'static str) -> Error { Error::SyntaxError }
fn missing_field(_: &'static str) -> Error { Error::Syntax }
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(format!("{:?}", self).as_ref())
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Deserialization Error"
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
//////////////////////////////////////////////////////////////////////////////
mod decoder {
@@ -50,104 +67,104 @@ mod decoder {
impl rustc_serialize::Decoder for UsizeDecoder {
type Error = Error;
fn error(&mut self, _: &str) -> Error { Error::SyntaxError }
fn error(&mut self, _: &str) -> Error { Error::Syntax }
// Primitive types:
fn read_nil(&mut self) -> Result<(), Error> { Err(Error::SyntaxError) }
fn read_nil(&mut self) -> Result<(), Error> { Err(Error::Syntax) }
#[inline]
fn read_usize(&mut self) -> Result<usize, Error> {
match self.iter.next() {
Some(value) => Ok(value),
None => Err(Error::EndOfStreamError),
None => Err(Error::EndOfStream),
}
}
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) }
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::Syntax) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::Syntax) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::Syntax) }
fn read_u8(&mut self) -> Result<u8, Error> { Err(Error::Syntax) }
fn read_isize(&mut self) -> Result<isize, Error> { Err(Error::Syntax) }
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::Syntax) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::Syntax) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::Syntax) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::Syntax) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::Syntax) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::Syntax) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::Syntax) }
fn read_char(&mut self) -> Result<char, Error> { Err(Error::Syntax) }
fn read_str(&mut self) -> Result<String, Error> { Err(Error::Syntax) }
// Compound types:
fn read_enum<T, F>(&mut self, _name: &str, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_struct_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_struct_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple<T, F>(&mut self, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
// Specialized types:
fn read_option<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder, bool) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
#[inline]
@@ -167,19 +184,19 @@ mod decoder {
fn read_map<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_map_elt_key<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_map_elt_val<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut UsizeDecoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
@@ -202,105 +219,105 @@ mod decoder {
impl rustc_serialize::Decoder for U8Decoder {
type Error = Error;
fn error(&mut self, _: &str) -> Error { Error::SyntaxError }
fn error(&mut self, _: &str) -> Error { Error::Syntax }
// 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_nil(&mut self) -> Result<(), Error> { Err(Error::Syntax) }
fn read_usize(&mut self) -> Result<usize, Error> { Err(Error::Syntax) }
fn read_u64(&mut self) -> Result<u64, Error> { Err(Error::Syntax) }
fn read_u32(&mut self) -> Result<u32, Error> { Err(Error::Syntax) }
fn read_u16(&mut self) -> Result<u16, Error> { Err(Error::Syntax) }
#[inline]
fn read_u8(&mut self) -> Result<u8, Error> {
match self.iter.next() {
Some(value) => Ok(value),
None => Err(Error::EndOfStreamError),
None => Err(Error::EndOfStream),
}
}
#[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) }
fn read_isize(&mut self) -> Result<isize, Error> { Err(Error::Syntax) }
fn read_i64(&mut self) -> Result<i64, Error> { Err(Error::Syntax) }
fn read_i32(&mut self) -> Result<i32, Error> { Err(Error::Syntax) }
fn read_i16(&mut self) -> Result<i16, Error> { Err(Error::Syntax) }
fn read_i8(&mut self) -> Result<i8, Error> { Err(Error::Syntax) }
fn read_bool(&mut self) -> Result<bool, Error> { Err(Error::Syntax) }
fn read_f64(&mut self) -> Result<f64, Error> { Err(Error::Syntax) }
fn read_f32(&mut self) -> Result<f32, Error> { Err(Error::Syntax) }
fn read_char(&mut self) -> Result<char, Error> { Err(Error::Syntax) }
fn read_str(&mut self) -> Result<String, Error> { Err(Error::Syntax) }
// Compound types:
fn read_enum<T, F>(&mut self, _name: &str, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_struct_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_struct_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple<T, F>(&mut self, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
// Specialized types:
fn read_option<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder, bool) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
#[inline]
@@ -320,19 +337,19 @@ mod decoder {
fn read_map<T, F>(&mut self, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder, usize) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_map_elt_key<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
fn read_map_elt_val<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Error> where
F: FnOnce(&mut U8Decoder) -> Result<T, Error>,
{
Err(Error::SyntaxError)
Err(Error::Syntax)
}
}
}
@@ -349,9 +366,9 @@ mod deserializer {
#[derive(PartialEq, Debug)]
enum State {
StartState,
SepOrEndState,
EndState,
Start,
SepOrEnd,
End,
}
pub struct Deserializer<A> {
@@ -366,7 +383,7 @@ mod deserializer {
pub fn new(values: Vec<A>) -> Deserializer<A> {
let len = values.len();
Deserializer {
state: State::StartState,
state: State::Start,
iter: values.into_iter(),
len: len,
value: None,
@@ -378,19 +395,19 @@ mod deserializer {
type Error = Error;
#[inline]
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.state {
State::StartState => {
self.state = State::SepOrEndState;
State::Start => {
self.state = State::SepOrEnd;
visitor.visit_seq(self)
}
State::SepOrEndState => {
State::SepOrEnd => {
visitor.visit_usize(self.value.take().unwrap())
}
State::EndState => {
Err(Error::EndOfStreamError)
State::End => {
Err(Error::EndOfStream)
}
}
}
@@ -410,7 +427,7 @@ mod deserializer {
Ok(Some(try!(de::Deserialize::deserialize(self))))
}
None => {
self.state = State::EndState;
self.state = State::End;
Ok(None)
}
}
@@ -419,9 +436,9 @@ mod deserializer {
#[inline]
fn end(&mut self) -> Result<(), Error> {
match self.iter.next() {
Some(_) => Err(Error::SyntaxError),
Some(_) => Err(Error::Syntax),
None => {
self.state = State::EndState;
self.state = State::End;
Ok(())
}
}
@@ -437,19 +454,19 @@ mod deserializer {
type Error = Error;
#[inline]
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.state {
State::StartState => {
self.state = State::SepOrEndState;
State::Start => {
self.state = State::SepOrEnd;
visitor.visit_seq(self)
}
State::SepOrEndState => {
State::SepOrEnd => {
visitor.visit_u8(self.value.take().unwrap())
}
State::EndState => {
Err(Error::EndOfStreamError)
State::End => {
Err(Error::EndOfStream)
}
}
}
@@ -469,7 +486,7 @@ mod deserializer {
Ok(Some(try!(de::Deserialize::deserialize(self))))
}
None => {
self.state = State::EndState;
self.state = State::End;
Ok(None)
}
}
@@ -478,9 +495,9 @@ mod deserializer {
#[inline]
fn end(&mut self) -> Result<(), Error> {
match self.iter.next() {
Some(_) => Err(Error::SyntaxError),
Some(_) => Err(Error::Syntax),
None => {
self.state = State::EndState;
self.state = State::End;
Ok(())
}
}
@@ -504,14 +521,14 @@ fn run_decoder<
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();
fn run_deserializer<D, T>(mut d: D, value: T)
where D: Deserializer,
D::Error: Debug + PartialEq,
T: Clone + PartialEq + Debug + Deserialize
{
let v = T::deserialize(&mut d);
assert_eq!(value, v);
assert_eq!(Ok(value), v);
}
#[bench]
+79
View File
@@ -0,0 +1,79 @@
#[macro_export]
macro_rules! declare_ser_tests {
($($name:ident { $($value:expr => $tokens:expr,)+ })+) => {
$(
#[test]
fn $name() {
$(
::token::assert_ser_tokens(&$value, $tokens);
)+
}
)+
}
}
#[macro_export]
macro_rules! btreemap {
() => {
BTreeMap::new()
};
($($key:expr => $value:expr),+) => {
{
let mut map = BTreeMap::new();
$(map.insert($key, $value);)+
map
}
}
}
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
}
}
}
macro_rules! hashmap {
() => {
HashMap::new()
};
($($key:expr => $value:expr),+) => {
{
let mut map = HashMap::new();
$(map.insert($key, $value);)+
map
}
}
}
+3
View File
@@ -1,3 +1,6 @@
#![cfg_attr(feature = "nightly", feature(plugin))]
#![cfg_attr(feature = "nightly", plugin(clippy))]
extern crate serde;
include!(concat!(env!("OUT_DIR"), "/test.rs"));
+5 -2
View File
@@ -1,7 +1,10 @@
#[macro_use]
mod macros;
mod token;
mod test_annotations;
mod test_bytes;
mod test_de;
mod test_json;
mod test_json_builder;
mod test_macros;
mod test_ser;
+664 -38
View File
@@ -1,73 +1,699 @@
use serde::json;
use std::default::Default;
use serde::{Serialize, Serializer, Deserialize, Deserializer};
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Default {
a1: i32,
#[serde(default)]
a2: i32,
use token::{
Error,
Token,
assert_tokens,
assert_ser_tokens,
assert_de_tokens,
assert_de_tokens_error
};
trait Trait: Sized {
fn my_default() -> Self;
fn should_skip(&self) -> bool;
fn serialize_with<S>(&self, ser: &mut S) -> Result<(), S::Error>
where S: Serializer;
fn deserialize_with<D>(de: &mut D) -> Result<Self, D::Error>
where D: Deserializer;
}
impl Trait for i32 {
fn my_default() -> Self { 123 }
fn should_skip(&self) -> bool { *self == 123 }
fn serialize_with<S>(&self, ser: &mut S) -> Result<(), S::Error>
where S: Serializer
{
if *self == 123 {
true.serialize(ser)
} else {
false.serialize(ser)
}
}
fn deserialize_with<D>(de: &mut D) -> Result<Self, D::Error>
where D: Deserializer
{
if try!(Deserialize::deserialize(de)) {
Ok(123)
} else {
Ok(2)
}
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Rename {
struct DefaultStruct<A, B: Default, C> where C: Trait {
a1: A,
#[serde(default)]
a2: B,
#[serde(default="Trait::my_default")]
a3: C,
}
#[test]
fn test_default_struct() {
assert_de_tokens(
&DefaultStruct { a1: 1, a2: 2, a3: 3 },
vec![
Token::StructStart("DefaultStruct", Some(3)),
Token::StructSep,
Token::Str("a1"),
Token::I32(1),
Token::StructSep,
Token::Str("a2"),
Token::I32(2),
Token::StructSep,
Token::Str("a3"),
Token::I32(3),
Token::StructEnd,
]
);
assert_de_tokens(
&DefaultStruct { a1: 1, a2: 0, a3: 123 },
vec![
Token::StructStart("DefaultStruct", Some(1)),
Token::StructSep,
Token::Str("a1"),
Token::I32(1),
Token::StructEnd,
]
);
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum DefaultEnum<A, B: Default, C> where C: Trait {
Struct {
a1: A,
#[serde(default)]
a2: B,
#[serde(default="Trait::my_default")]
a3: C,
}
}
#[test]
fn test_default_enum() {
assert_de_tokens(
&DefaultEnum::Struct { a1: 1, a2: 2, a3: 3 },
vec![
Token::EnumMapStart("DefaultEnum", "Struct", Some(3)),
Token::EnumMapSep,
Token::Str("a1"),
Token::I32(1),
Token::EnumMapSep,
Token::Str("a2"),
Token::I32(2),
Token::EnumMapSep,
Token::Str("a3"),
Token::I32(3),
Token::EnumMapEnd,
]
);
assert_de_tokens(
&DefaultEnum::Struct { a1: 1, a2: 0, a3: 123 },
vec![
Token::EnumMapStart("DefaultEnum", "Struct", Some(3)),
Token::EnumMapSep,
Token::Str("a1"),
Token::I32(1),
Token::EnumMapEnd,
]
);
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct DenyUnknown {
a1: i32,
}
#[test]
fn test_ignore_unknown() {
// 'Default' allows unknown. Basic smoke test of ignore...
assert_de_tokens(
&DefaultStruct { a1: 1, a2: 2, a3: 3 },
vec![
Token::StructStart("DefaultStruct", Some(5)),
Token::StructSep,
Token::Str("whoops1"),
Token::I32(2),
Token::StructSep,
Token::Str("a1"),
Token::I32(1),
Token::StructSep,
Token::Str("whoops2"),
Token::SeqStart(Some(1)),
Token::SeqSep,
Token::I32(2),
Token::SeqEnd,
Token::StructSep,
Token::Str("a2"),
Token::I32(2),
Token::StructSep,
Token::Str("whoops3"),
Token::I32(2),
Token::StructSep,
Token::Str("a3"),
Token::I32(3),
Token::StructEnd,
]
);
assert_de_tokens_error::<DenyUnknown>(
vec![
Token::StructStart("DenyUnknown", Some(2)),
Token::StructSep,
Token::Str("a1"),
Token::I32(1),
Token::StructSep,
Token::Str("whoops"),
Token::I32(2),
Token::StructEnd,
],
Error::UnknownFieldError("whoops".to_owned())
);
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename="Superhero")]
struct RenameStruct {
a1: i32,
#[serde(rename="a3")]
a2: i32,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FormatRename {
#[serde(rename(serialize="SuperheroSer", deserialize="SuperheroDe"))]
struct RenameStructSerializeDeserialize {
a1: i32,
#[serde(rename(xml= "a4", json="a5"))]
#[serde(rename(serialize="a4", deserialize="a5"))]
a2: i32,
}
#[test]
fn test_rename_struct() {
assert_tokens(
&RenameStruct { a1: 1, a2: 2 },
vec![
Token::StructStart("Superhero", Some(2)),
Token::StructSep,
Token::Str("a1"),
Token::I32(1),
Token::StructSep,
Token::Str("a3"),
Token::I32(2),
Token::StructEnd,
]
);
assert_ser_tokens(
&RenameStructSerializeDeserialize { a1: 1, a2: 2 },
&[
Token::StructStart("SuperheroSer", Some(2)),
Token::StructSep,
Token::Str("a1"),
Token::I32(1),
Token::StructSep,
Token::Str("a4"),
Token::I32(2),
Token::StructEnd,
]
);
assert_de_tokens(
&RenameStructSerializeDeserialize { a1: 1, a2: 2 },
vec![
Token::StructStart("SuperheroDe", Some(2)),
Token::StructSep,
Token::Str("a1"),
Token::I32(1),
Token::StructSep,
Token::Str("a5"),
Token::I32(2),
Token::StructEnd,
]
);
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename="Superhero")]
enum RenameEnum {
#[serde(rename="bruce_wayne")]
Batman,
#[serde(rename="clark_kent")]
Superman(i8),
#[serde(rename="diana_prince")]
WonderWoman(i8, i8),
#[serde(rename="barry_allan")]
Flash {
#[serde(rename="b")]
a: i32,
},
}
#[derive(Debug, PartialEq, Deserialize, Serialize)]
enum SerEnum<A> {
Map {
#[serde(rename(serialize="SuperheroSer", deserialize="SuperheroDe"))]
enum RenameEnumSerializeDeserialize<A> {
#[serde(rename(serialize="dick_grayson", deserialize="jason_todd"))]
Robin {
a: i8,
#[serde(rename(xml= "c", json="d"))]
#[serde(rename(serialize="c", deserialize="d"))]
b: A,
},
}
#[test]
fn test_default() {
let deserialized_value: Default = json::from_str(&"{\"a1\":1,\"a2\":2}").unwrap();
assert_eq!(deserialized_value, Default { a1: 1, a2: 2 });
fn test_rename_enum() {
assert_tokens(
&RenameEnum::Batman,
vec![
Token::EnumUnit("Superhero", "bruce_wayne"),
]
);
let deserialized_value: Default = json::from_str(&"{\"a1\":1}").unwrap();
assert_eq!(deserialized_value, Default { a1: 1, a2: 0 });
assert_tokens(
&RenameEnum::Superman(0),
vec![
Token::EnumNewType("Superhero", "clark_kent"),
Token::I8(0),
]
);
assert_tokens(
&RenameEnum::WonderWoman(0, 1),
vec![
Token::EnumSeqStart("Superhero", "diana_prince", Some(2)),
Token::EnumSeqSep,
Token::I8(0),
Token::EnumSeqSep,
Token::I8(1),
Token::EnumSeqEnd,
]
);
assert_tokens(
&RenameEnum::Flash { a: 1 },
vec![
Token::EnumMapStart("Superhero", "barry_allan", Some(1)),
Token::EnumMapSep,
Token::Str("b"),
Token::I32(1),
Token::EnumMapEnd,
]
);
assert_ser_tokens(
&RenameEnumSerializeDeserialize::Robin {
a: 0,
b: String::new(),
},
&[
Token::EnumMapStart("SuperheroSer", "dick_grayson", Some(2)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(0),
Token::EnumMapSep,
Token::Str("c"),
Token::Str(""),
Token::EnumMapEnd,
]
);
assert_de_tokens(
&RenameEnumSerializeDeserialize::Robin {
a: 0,
b: String::new(),
},
vec![
Token::EnumMapStart("SuperheroDe", "jason_todd", Some(2)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(0),
Token::EnumMapSep,
Token::Str("d"),
Token::Str(""),
Token::EnumMapEnd,
]
);
}
#[derive(Debug, PartialEq, Serialize)]
struct SkipSerializingStruct<'a, B, C> where C: Trait {
a: &'a i8,
#[serde(skip_serializing)]
b: B,
#[serde(skip_serializing_if="Trait::should_skip")]
c: C,
}
#[test]
fn test_rename() {
let value = Rename { a1: 1, a2: 2 };
let serialized_value = json::to_string(&value).unwrap();
assert_eq!(serialized_value, "{\"a1\":1,\"a3\":2}");
fn test_skip_serializing_struct() {
let a = 1;
assert_ser_tokens(
&SkipSerializingStruct {
a: &a,
b: 2,
c: 3,
},
&[
Token::StructStart("SkipSerializingStruct", Some(2)),
let deserialized_value: Rename = json::from_str(&serialized_value).unwrap();
assert_eq!(value, deserialized_value);
Token::StructSep,
Token::Str("a"),
Token::I8(1),
Token::StructSep,
Token::Str("c"),
Token::I32(3),
Token::StructEnd,
]
);
assert_ser_tokens(
&SkipSerializingStruct {
a: &a,
b: 2,
c: 123,
},
&[
Token::StructStart("SkipSerializingStruct", Some(1)),
Token::StructSep,
Token::Str("a"),
Token::I8(1),
Token::StructEnd,
]
);
}
#[derive(Debug, PartialEq, Serialize)]
enum SkipSerializingEnum<'a, B, C> where C: Trait {
Struct {
a: &'a i8,
#[serde(skip_serializing)]
_b: B,
#[serde(skip_serializing_if="Trait::should_skip")]
c: C,
}
}
#[test]
fn test_format_rename() {
let value = FormatRename { a1: 1, a2: 2 };
let serialized_value = json::to_string(&value).unwrap();
assert_eq!(serialized_value, "{\"a1\":1,\"a5\":2}");
fn test_skip_serializing_enum() {
let a = 1;
assert_ser_tokens(
&SkipSerializingEnum::Struct {
a: &a,
_b: 2,
c: 3,
},
&[
Token::EnumMapStart("SkipSerializingEnum", "Struct", Some(2)),
let deserialized_value = json::from_str("{\"a1\":1,\"a5\":2}").unwrap();
assert_eq!(value, deserialized_value);
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::EnumMapSep,
Token::Str("c"),
Token::I32(3),
Token::EnumMapEnd,
]
);
assert_ser_tokens(
&SkipSerializingEnum::Struct {
a: &a,
_b: 2,
c: 123,
},
&[
Token::EnumMapStart("SkipSerializingEnum", "Struct", Some(1)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::EnumMapEnd,
]
);
}
#[derive(Debug, PartialEq, Serialize)]
struct SerializeWithStruct<'a, B> where B: Trait {
a: &'a i8,
#[serde(serialize_with="Trait::serialize_with")]
b: B,
}
#[test]
fn test_enum_format_rename() {
let s1 = String::new();
let value = SerEnum::Map { a: 0i8, b: s1 };
let serialized_value = json::to_string(&value).unwrap();
let ans = "{\"Map\":{\"a\":0,\"d\":\"\"}}";
assert_eq!(serialized_value, ans);
fn test_serialize_with_struct() {
let a = 1;
assert_ser_tokens(
&SerializeWithStruct {
a: &a,
b: 2,
},
&[
Token::StructStart("SerializeWithStruct", Some(2)),
let deserialized_value = json::from_str(ans).unwrap();
assert_eq!(value, deserialized_value);
Token::StructSep,
Token::Str("a"),
Token::I8(1),
Token::StructSep,
Token::Str("b"),
Token::Bool(false),
Token::StructEnd,
]
);
assert_ser_tokens(
&SerializeWithStruct {
a: &a,
b: 123,
},
&[
Token::StructStart("SerializeWithStruct", Some(2)),
Token::StructSep,
Token::Str("a"),
Token::I8(1),
Token::StructSep,
Token::Str("b"),
Token::Bool(true),
Token::StructEnd,
]
);
}
#[derive(Debug, PartialEq, Serialize)]
enum SerializeWithEnum<'a, B> where B: Trait {
Struct {
a: &'a i8,
#[serde(serialize_with="Trait::serialize_with")]
b: B,
}
}
#[test]
fn test_serialize_with_enum() {
let a = 1;
assert_ser_tokens(
&SerializeWithEnum::Struct {
a: &a,
b: 2,
},
&[
Token::EnumMapStart("SerializeWithEnum", "Struct", Some(2)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::EnumMapSep,
Token::Str("b"),
Token::Bool(false),
Token::EnumMapEnd,
]
);
assert_ser_tokens(
&SerializeWithEnum::Struct {
a: &a,
b: 123,
},
&[
Token::EnumMapStart("SerializeWithEnum", "Struct", Some(2)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::EnumMapSep,
Token::Str("b"),
Token::Bool(true),
Token::EnumMapEnd,
]
);
}
#[derive(Debug, PartialEq, Deserialize)]
struct DeserializeWithStruct<B> where B: Trait {
a: i8,
#[serde(deserialize_with="Trait::deserialize_with")]
b: B,
}
#[test]
fn test_deserialize_with_struct() {
assert_de_tokens(
&DeserializeWithStruct {
a: 1,
b: 2,
},
vec![
Token::StructStart("DeserializeWithStruct", Some(2)),
Token::StructSep,
Token::Str("a"),
Token::I8(1),
Token::StructSep,
Token::Str("b"),
Token::Bool(false),
Token::StructEnd,
]
);
assert_de_tokens(
&DeserializeWithStruct {
a: 1,
b: 123,
},
vec![
Token::StructStart("DeserializeWithStruct", Some(2)),
Token::StructSep,
Token::Str("a"),
Token::I8(1),
Token::StructSep,
Token::Str("b"),
Token::Bool(true),
Token::StructEnd,
]
);
}
#[derive(Debug, PartialEq, Deserialize)]
enum DeserializeWithEnum<B> where B: Trait {
Struct {
a: i8,
#[serde(deserialize_with="Trait::deserialize_with")]
b: B,
}
}
#[test]
fn test_deserialize_with_enum() {
assert_de_tokens(
&DeserializeWithEnum::Struct {
a: 1,
b: 2,
},
vec![
Token::EnumMapStart("DeserializeWithEnum", "Struct", Some(2)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::EnumMapSep,
Token::Str("b"),
Token::Bool(false),
Token::EnumMapEnd,
]
);
assert_de_tokens(
&DeserializeWithEnum::Struct {
a: 1,
b: 123,
},
vec![
Token::EnumMapStart("DeserializeWithEnum", "Struct", Some(2)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::EnumMapSep,
Token::Str("b"),
Token::Bool(true),
Token::EnumMapEnd,
]
);
}
+39 -64
View File
@@ -1,21 +1,38 @@
use serde;
use std::fmt;
use std::error;
use serde::Serialize;
use serde::bytes::{ByteBuf, Bytes};
use serde::json;
///////////////////////////////////////////////////////////////////////////////
#[derive(Debug, PartialEq)]
struct Error;
impl serde::ser::Error for Error {
fn custom<T: Into<String>>(_: T) -> Error { Error }
}
impl serde::de::Error for Error {
fn syntax_error() -> Error { Error }
fn custom<T: Into<String>>(_: T) -> Error { Error }
fn end_of_stream_error() -> Error { Error }
fn end_of_stream() -> Error { Error }
}
fn unknown_field_error(_field: &str) -> Error { Error }
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(format!("{:?}", self).as_ref())
}
}
fn missing_field_error(_field: &'static str) -> Error { Error }
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Deserialization Error"
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -35,74 +52,74 @@ impl BytesSerializer {
impl serde::Serializer for BytesSerializer {
type Error = Error;
fn visit_unit(&mut self) -> Result<(), Error> {
fn serialize_unit(&mut self) -> Result<(), Error> {
Err(Error)
}
fn visit_bool(&mut self, _v: bool) -> Result<(), Error> {
fn serialize_bool(&mut self, _v: bool) -> Result<(), Error> {
Err(Error)
}
fn visit_i64(&mut self, _v: i64) -> Result<(), Error> {
fn serialize_i64(&mut self, _v: i64) -> Result<(), Error> {
Err(Error)
}
fn visit_u64(&mut self, _v: u64) -> Result<(), Error> {
fn serialize_u64(&mut self, _v: u64) -> Result<(), Error> {
Err(Error)
}
fn visit_f32(&mut self, _v: f32) -> Result<(), Error> {
fn serialize_f32(&mut self, _v: f32) -> Result<(), Error> {
Err(Error)
}
fn visit_f64(&mut self, _v: f64) -> Result<(), Error> {
fn serialize_f64(&mut self, _v: f64) -> Result<(), Error> {
Err(Error)
}
fn visit_char(&mut self, _v: char) -> Result<(), Error> {
fn serialize_char(&mut self, _v: char) -> Result<(), Error> {
Err(Error)
}
fn visit_str(&mut self, _v: &str) -> Result<(), Error> {
fn serialize_str(&mut self, _v: &str) -> Result<(), Error> {
Err(Error)
}
fn visit_none(&mut self) -> Result<(), Error> {
fn serialize_none(&mut self) -> Result<(), Error> {
Err(Error)
}
fn visit_some<V>(&mut self, _value: V) -> Result<(), Error>
fn serialize_some<V>(&mut self, _value: V) -> Result<(), Error>
where V: serde::Serialize,
{
Err(Error)
}
fn visit_seq<V>(&mut self, _visitor: V) -> Result<(), Error>
fn serialize_seq<V>(&mut self, _visitor: V) -> Result<(), Error>
where V: serde::ser::SeqVisitor,
{
Err(Error)
}
fn visit_seq_elt<T>(&mut self, _value: T) -> Result<(), Error>
fn serialize_seq_elt<T>(&mut self, _value: T) -> Result<(), Error>
where T: serde::Serialize
{
Err(Error)
}
fn visit_map<V>(&mut self, _visitor: V) -> Result<(), Error>
fn serialize_map<V>(&mut self, _visitor: V) -> Result<(), Error>
where V: serde::ser::MapVisitor,
{
Err(Error)
}
fn visit_map_elt<K, V>(&mut self, _key: K, _value: V) -> Result<(), Error>
fn serialize_map_elt<K, V>(&mut self, _key: K, _value: V) -> Result<(), Error>
where K: serde::Serialize,
V: serde::Serialize,
{
Err(Error)
}
fn visit_bytes(&mut self, bytes: &[u8]) -> Result<(), Error> {
fn serialize_bytes(&mut self, bytes: &[u8]) -> Result<(), Error> {
assert_eq!(self.bytes, bytes);
Ok(())
}
@@ -125,13 +142,13 @@ impl BytesDeserializer {
impl serde::Deserializer for BytesDeserializer {
type Error = Error;
fn visit<V>(&mut self, _visitor: V) -> Result<V::Value, Error>
fn deserialize<V>(&mut self, _visitor: V) -> Result<V::Value, Error>
where V: serde::de::Visitor,
{
Err(Error)
}
fn visit_bytes<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn deserialize_bytes<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: serde::de::Visitor,
{
visitor.visit_byte_buf(self.bytes.take().unwrap())
@@ -140,17 +157,6 @@ impl serde::Deserializer for BytesDeserializer {
///////////////////////////////////////////////////////////////////////////////
#[test]
fn test_bytes_ser_json() {
let buf = vec![];
let bytes = Bytes::from(&buf);
assert_eq!(json::to_string(&bytes).unwrap(), "[]".to_string());
let buf = vec![1, 2, 3];
let bytes = Bytes::from(&buf);
assert_eq!(json::to_string(&bytes).unwrap(), "[1,2,3]".to_string());
}
#[test]
fn test_bytes_ser_bytes() {
let buf = vec![];
@@ -164,39 +170,8 @@ fn test_bytes_ser_bytes() {
bytes.serialize(&mut ser).unwrap();
}
#[test]
fn test_byte_buf_ser_json() {
let bytes = ByteBuf::new();
assert_eq!(json::to_string(&bytes).unwrap(), "[]".to_string());
let bytes = ByteBuf::from(vec![1, 2, 3]);
assert_eq!(json::to_string(&bytes).unwrap(), "[1,2,3]".to_string());
}
#[test]
fn test_byte_buf_ser_bytes() {
let bytes = ByteBuf::new();
let mut ser = BytesSerializer::new(vec![]);
bytes.serialize(&mut ser).unwrap();
let bytes = ByteBuf::from(vec![1, 2, 3]);
let mut ser = BytesSerializer::new(vec![1, 2, 3]);
bytes.serialize(&mut ser).unwrap();
}
///////////////////////////////////////////////////////////////////////////////
#[test]
fn test_byte_buf_de_json() {
let bytes = ByteBuf::new();
let v: ByteBuf = json::from_str("[]").unwrap();
assert_eq!(v, bytes);
let bytes = ByteBuf::from(vec![1, 2, 3]);
let v: ByteBuf = json::from_str("[1, 2, 3]").unwrap();
assert_eq!(v, bytes);
}
#[test]
fn test_byte_buf_de_bytes() {
let mut de = BytesDeserializer::new(vec![]);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-50
View File
@@ -1,50 +0,0 @@
use std::collections::BTreeMap;
use serde::json::value::Value;
use serde::json::builder::{ArrayBuilder, ObjectBuilder};
#[test]
fn test_array_builder() {
let value = ArrayBuilder::new().unwrap();
assert_eq!(value, Value::Array(Vec::new()));
let value = ArrayBuilder::new()
.push(1)
.push(2)
.push(3)
.unwrap();
assert_eq!(value, Value::Array(vec!(Value::U64(1), Value::U64(2), Value::U64(3))));
let value = ArrayBuilder::new()
.push_array(|bld| bld.push(1).push(2).push(3))
.unwrap();
assert_eq!(value, Value::Array(vec!(Value::Array(vec!(Value::U64(1), Value::U64(2), Value::U64(3))))));
let value = ArrayBuilder::new()
.push_object(|bld|
bld
.insert("a".to_string(), 1)
.insert("b".to_string(), 2))
.unwrap();
let mut map = BTreeMap::new();
map.insert("a".to_string(), Value::U64(1));
map.insert("b".to_string(), Value::U64(2));
assert_eq!(value, Value::Array(vec!(Value::Object(map))));
}
#[test]
fn test_object_builder() {
let value = ObjectBuilder::new().unwrap();
assert_eq!(value, Value::Object(BTreeMap::new()));
let value = ObjectBuilder::new()
.insert("a".to_string(), 1)
.insert("b".to_string(), 2)
.unwrap();
let mut map = BTreeMap::new();
map.insert("a".to_string(), Value::U64(1));
map.insert("b".to_string(), Value::U64(2));
assert_eq!(value, Value::Object(map));
}
+343 -224
View File
@@ -1,18 +1,4 @@
use std::collections::BTreeMap;
use serde::json::{self, Value};
macro_rules! btreemap {
() => {
BTreeMap::new()
};
($($key:expr => $value:expr),+) => {
{
let mut map = BTreeMap::new();
$(map.insert($key, $value);)+
map
}
}
}
use token::{Token, assert_tokens, assert_ser_tokens, assert_de_tokens};
/*
trait Trait {
@@ -83,7 +69,7 @@ enum SerEnum<'a, B: 'a, C: /* Trait + */ 'a, D> where D: /* Trait + */ 'a {
},
}
#[derive(Debug, PartialEq, Deserialize)]
#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum DeEnum<B, C: /* Trait */, D> /* where D: Trait */ {
Unit,
Seq(
@@ -131,25 +117,31 @@ enum Lifetimes<'a> {
NoLifetimeMap { a: i32 },
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct GenericStruct<T> {
x: T,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct GenericNewTypeStruct<T>(T);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct GenericTupleStruct<T, U>(T, U);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub enum GenericEnum<T, U> {
Unit,
NewType(T),
Seq(T, U),
Map { x: T, y: U },
}
#[test]
fn test_named_unit() {
let named_unit = NamedUnit;
assert_eq!(
json::to_string(&named_unit).unwrap(),
"null".to_string()
assert_tokens(
&NamedUnit,
vec![Token::UnitStruct("NamedUnit")]
);
assert_eq!(
json::to_value(&named_unit),
Value::Null
);
let v: NamedUnit = json::from_str("null").unwrap();
assert_eq!(v, named_unit);
let v: NamedUnit = json::from_value(Value::Null).unwrap();
assert_eq!(v, named_unit);
}
#[test]
@@ -157,35 +149,58 @@ fn test_ser_named_tuple() {
let a = 5;
let mut b = 6;
let c = 7;
let named_tuple = SerNamedTuple(&a, &mut b, c);
assert_ser_tokens(
&SerNamedTuple(&a, &mut b, c),
&[
Token::TupleStructStart("SerNamedTuple", Some(3)),
Token::TupleStructSep,
Token::I32(5),
assert_eq!(
json::to_string(&named_tuple).unwrap(),
"[5,6,7]"
);
Token::TupleStructSep,
Token::I32(6),
assert_eq!(
json::to_value(&named_tuple),
Value::Array(vec![Value::U64(5), Value::U64(6), Value::U64(7)])
Token::TupleStructSep,
Token::I32(7),
Token::TupleStructEnd,
],
);
}
#[test]
fn test_de_named_tuple() {
let v: DeNamedTuple<i32, i32, i32> = json::from_str("[1,2,3]").unwrap();
assert_eq!(
v,
DeNamedTuple(1, 2, 3)
assert_de_tokens(
&DeNamedTuple(5, 6, 7),
vec![
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(5),
Token::SeqSep,
Token::I32(6),
Token::SeqSep,
Token::I32(7),
Token::SeqEnd,
]
);
let v: Value = json::from_str("[1,2,3]").unwrap();
assert_eq!(
v,
Value::Array(vec![
Value::U64(1),
Value::U64(2),
Value::U64(3),
])
assert_de_tokens(
&DeNamedTuple(5, 6, 7),
vec![
Token::TupleStructStart("DeNamedTuple", Some(3)),
Token::TupleStructSep,
Token::I32(5),
Token::TupleStructSep,
Token::I32(6),
Token::TupleStructSep,
Token::I32(7),
Token::TupleStructEnd,
]
);
}
@@ -194,60 +209,68 @@ fn test_ser_named_map() {
let a = 5;
let mut b = 6;
let c = 7;
let named_map = SerNamedMap {
a: &a,
b: &mut b,
c: c,
};
assert_eq!(
json::to_string(&named_map).unwrap(),
"{\"a\":5,\"b\":6,\"c\":7}"
);
assert_ser_tokens(
&SerNamedMap {
a: &a,
b: &mut b,
c: c,
},
&[
Token::StructStart("SerNamedMap", Some(3)),
assert_eq!(
json::to_value(&named_map),
Value::Object(btreemap![
"a".to_string() => Value::U64(5),
"b".to_string() => Value::U64(6),
"c".to_string() => Value::U64(7)
])
Token::StructSep,
Token::Str("a"),
Token::I32(5),
Token::StructSep,
Token::Str("b"),
Token::I32(6),
Token::StructSep,
Token::Str("c"),
Token::I32(7),
Token::StructEnd,
]
);
}
#[test]
fn test_de_named_map() {
let v = DeNamedMap {
a: 5,
b: 6,
c: 7,
};
assert_de_tokens(
&DeNamedMap {
a: 5,
b: 6,
c: 7,
},
vec![
Token::StructStart("DeNamedMap", Some(3)),
let v2: DeNamedMap<i32, i32, i32> = json::from_str(
"{\"a\":5,\"b\":6,\"c\":7}"
).unwrap();
assert_eq!(v, v2);
Token::StructSep,
Token::Str("a"),
Token::I32(5),
let v2 = json::from_value(Value::Object(btreemap![
"a".to_string() => Value::U64(5),
"b".to_string() => Value::U64(6),
"c".to_string() => Value::U64(7)
])).unwrap();
assert_eq!(v, v2);
Token::StructSep,
Token::Str("b"),
Token::I32(6),
Token::StructSep,
Token::Str("c"),
Token::I32(7),
Token::StructEnd,
]
);
}
#[test]
fn test_ser_enum_unit() {
assert_eq!(
json::to_string(&SerEnum::Unit::<u32, u32, u32>).unwrap(),
"{\"Unit\":[]}"
);
assert_eq!(
json::to_value(&SerEnum::Unit::<u32, u32, u32>),
Value::Object(btreemap!(
"Unit".to_string() => Value::Array(vec![]))
)
assert_ser_tokens(
&SerEnum::Unit::<u32, u32, u32>,
&[
Token::EnumUnit("SerEnum", "Unit"),
]
);
}
@@ -260,37 +283,32 @@ fn test_ser_enum_seq() {
let mut e = 5;
//let f = 6;
assert_eq!(
json::to_string(&SerEnum::Seq(
assert_ser_tokens(
&SerEnum::Seq(
a,
b,
&c,
//d,
&mut e,
//f,
)).unwrap(),
"{\"Seq\":[1,2,3,5]}".to_string()
);
),
&[
Token::EnumSeqStart("SerEnum", "Seq", Some(4)),
assert_eq!(
json::to_value(&SerEnum::Seq(
a,
b,
&c,
//d,
&mut e,
//e,
)),
Value::Object(btreemap!(
"Seq".to_string() => Value::Array(vec![
Value::U64(1),
Value::U64(2),
Value::U64(3),
//Value::U64(4),
Value::U64(5),
//Value::U64(6),
])
))
Token::EnumSeqSep,
Token::I8(1),
Token::EnumSeqSep,
Token::I32(2),
Token::EnumSeqSep,
Token::I32(3),
Token::EnumSeqSep,
Token::I32(5),
Token::EnumSeqEnd,
],
);
}
@@ -303,54 +321,46 @@ fn test_ser_enum_map() {
let mut e = 5;
//let f = 6;
assert_eq!(
json::to_string(&SerEnum::Map {
assert_ser_tokens(
&SerEnum::Map {
a: a,
b: b,
c: &c,
//d: d,
e: &mut e,
//f: f,
}).unwrap(),
"{\"Map\":{\"a\":1,\"b\":2,\"c\":3,\"e\":5}}".to_string()
);
},
&[
Token::EnumMapStart("SerEnum", "Map", Some(4)),
assert_eq!(
json::to_value(&SerEnum::Map {
a: a,
b: b,
c: &c,
//d: d,
e: &mut e,
//f: f,
}),
Value::Object(btreemap!(
"Map".to_string() => Value::Object(btreemap![
"a".to_string() => Value::U64(1),
"b".to_string() => Value::U64(2),
"c".to_string() => Value::U64(3),
//"d".to_string() => Value::U64(4)
"e".to_string() => Value::U64(5)
//"f".to_string() => Value::U64(6)
])
))
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::EnumMapSep,
Token::Str("b"),
Token::I32(2),
Token::EnumMapSep,
Token::Str("c"),
Token::I32(3),
Token::EnumMapSep,
Token::Str("e"),
Token::I32(5),
Token::EnumMapEnd,
],
);
}
#[test]
fn test_de_enum_unit() {
let v: DeEnum<_, _, _> = json::from_str("{\"Unit\":[]}").unwrap();
assert_eq!(
v,
DeEnum::Unit::<u32, u32, u32>
);
let v: DeEnum<_, _, _> = json::from_value(Value::Object(btreemap!(
"Unit".to_string() => Value::Array(vec![]))
)).unwrap();
assert_eq!(
v,
DeEnum::Unit::<u32, u32, u32>
assert_tokens(
&DeEnum::Unit::<u32, u32, u32>,
vec![
Token::EnumUnit("DeEnum", "Unit"),
],
);
}
@@ -363,39 +373,32 @@ fn test_de_enum_seq() {
let e = 5;
//let f = 6;
let v: DeEnum<_, _, _> = json::from_str("{\"Seq\":[1,2,3,5]}").unwrap();
assert_eq!(
v,
DeEnum::Seq(
assert_tokens(
&DeEnum::Seq(
a,
b,
c,
//d,
e,
//f,
)
);
),
vec![
Token::EnumSeqStart("DeEnum", "Seq", Some(4)),
let v: DeEnum<_, _, _> = json::from_value(Value::Object(btreemap!(
"Seq".to_string() => Value::Array(vec![
Value::U64(1),
Value::U64(2),
Value::U64(3),
//Value::U64(4),
Value::U64(5),
//Value::U64(6),
])
))).unwrap();
assert_eq!(
v,
DeEnum::Seq(
a,
b,
c,
//d,
e,
//e,
)
Token::EnumSeqSep,
Token::I8(1),
Token::EnumSeqSep,
Token::I32(2),
Token::EnumSeqSep,
Token::I32(3),
Token::EnumSeqSep,
Token::I32(5),
Token::EnumSeqEnd,
],
);
}
@@ -408,70 +411,186 @@ fn test_de_enum_map() {
let e = 5;
//let f = 6;
let v: DeEnum<_, _, _> = json::from_str(
"{\"Map\":{\"a\":1,\"b\":2,\"c\":3,\"e\":5}}"
).unwrap();
assert_eq!(
v,
DeEnum::Map {
assert_tokens(
&DeEnum::Map {
a: a,
b: b,
c: c,
//d: d,
e: e,
//f: f,
}
);
},
vec![
Token::EnumMapStart("DeEnum", "Map", Some(4)),
let v: DeEnum<_, _, _> = json::from_value(Value::Object(btreemap!(
"Map".to_string() => Value::Object(btreemap![
"a".to_string() => Value::U64(1),
"b".to_string() => Value::U64(2),
"c".to_string() => Value::U64(3),
//"d".to_string() => Value::U64(4)
"e".to_string() => Value::U64(5)
//"f".to_string() => Value::U64(6)
])
))).unwrap();
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
assert_eq!(
v,
DeEnum::Map {
a: a,
b: b,
c: c,
//d: d,
e: e,
//f: f,
}
Token::EnumMapSep,
Token::Str("b"),
Token::I32(2),
Token::EnumMapSep,
Token::Str("c"),
Token::I32(3),
Token::EnumMapSep,
Token::Str("e"),
Token::I32(5),
Token::EnumMapEnd,
],
);
}
#[test]
fn test_lifetimes() {
let value = 5;
let lifetime = Lifetimes::LifetimeSeq(&value);
assert_eq!(
json::to_string(&lifetime).unwrap(),
"{\"LifetimeSeq\":[5]}"
assert_ser_tokens(
&Lifetimes::LifetimeSeq(&value),
&[
Token::EnumNewType("Lifetimes", "LifetimeSeq"),
Token::I32(5),
]
);
let lifetime = Lifetimes::NoLifetimeSeq(5);
assert_eq!(
json::to_string(&lifetime).unwrap(),
"{\"NoLifetimeSeq\":[5]}"
assert_ser_tokens(
&Lifetimes::NoLifetimeSeq(5),
&[
Token::EnumNewType("Lifetimes", "NoLifetimeSeq"),
Token::I32(5),
]
);
let value = 5;
let lifetime = Lifetimes::LifetimeMap { a: &value };
assert_eq!(
json::to_string(&lifetime).unwrap(),
"{\"LifetimeMap\":{\"a\":5}}"
assert_ser_tokens(
&Lifetimes::LifetimeMap { a: &value },
&[
Token::EnumMapStart("Lifetimes", "LifetimeMap", Some(1)),
Token::EnumMapSep,
Token::Str("a"),
Token::I32(5),
Token::EnumMapEnd,
]
);
let lifetime = Lifetimes::NoLifetimeMap { a: 5 };
assert_eq!(
json::to_string(&lifetime).unwrap(),
"{\"NoLifetimeMap\":{\"a\":5}}"
assert_ser_tokens(
&Lifetimes::NoLifetimeMap { a: 5 },
&[
Token::EnumMapStart("Lifetimes", "NoLifetimeMap", Some(1)),
Token::EnumMapSep,
Token::Str("a"),
Token::I32(5),
Token::EnumMapEnd,
]
);
}
#[test]
fn test_generic_struct() {
assert_tokens(
&GenericStruct { x: 5u32 },
vec![
Token::StructStart("GenericStruct", Some(1)),
Token::StructSep,
Token::Str("x"),
Token::U32(5),
Token::StructEnd,
]
);
}
#[test]
fn test_generic_newtype_struct() {
assert_tokens(
&GenericNewTypeStruct(5u32),
vec![
Token::StructNewType("GenericNewTypeStruct"),
Token::U32(5),
]
);
}
#[test]
fn test_generic_tuple_struct() {
assert_tokens(
&GenericTupleStruct(5u32, 6u32),
vec![
Token::TupleStructStart("GenericTupleStruct", Some(2)),
Token::TupleStructSep,
Token::U32(5),
Token::TupleStructSep,
Token::U32(6),
Token::TupleStructEnd,
]
);
}
#[test]
fn test_generic_enum_unit() {
assert_tokens(
&GenericEnum::Unit::<u32, u32>,
vec![
Token::EnumUnit("GenericEnum", "Unit"),
]
);
}
#[test]
fn test_generic_enum_newtype() {
assert_tokens(
&GenericEnum::NewType::<u32, u32>(5),
vec![
Token::EnumNewType("GenericEnum", "NewType"),
Token::U32(5),
]
);
}
#[test]
fn test_generic_enum_seq() {
assert_tokens(
&GenericEnum::Seq::<u32, u32>(5, 6),
vec![
Token::EnumSeqStart("GenericEnum", "Seq", Some(2)),
Token::EnumSeqSep,
Token::U32(5),
Token::EnumSeqSep,
Token::U32(6),
Token::EnumSeqEnd,
]
);
}
#[test]
fn test_generic_enum_map() {
assert_tokens(
&GenericEnum::Map::<u32, u32> { x: 5, y: 6 },
vec![
Token::EnumMapStart("GenericEnum", "Map", Some(2)),
Token::EnumMapSep,
Token::Str("x"),
Token::U32(5),
Token::EnumMapSep,
Token::Str("y"),
Token::U32(6),
Token::EnumMapEnd,
]
);
}
+135 -361
View File
@@ -1,274 +1,20 @@
use std::vec;
use std::collections::BTreeMap;
use std::net;
use std::path::{Path, PathBuf};
use std::str;
use serde::ser::{Serialize, Serializer, SeqVisitor, MapVisitor};
#[derive(Clone, PartialEq, Debug)]
pub enum Token<'a> {
Bool(bool),
Isize(isize),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
Usize(usize),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
F32(f32),
F64(f64),
Char(char),
Str(&'a str),
Option(bool),
Unit,
NamedUnit(&'a str),
EnumUnit(&'a str, &'a str),
SeqStart(Option<usize>),
NamedSeqStart(&'a str, Option<usize>),
EnumSeqStart(&'a str, &'a str, Option<usize>),
SeqSep,
SeqEnd,
MapStart(Option<usize>),
NamedMapStart(&'a str, Option<usize>),
EnumMapStart(&'a str, &'a str, Option<usize>),
MapSep,
MapEnd,
}
struct AssertSerializer<'a> {
iter: vec::IntoIter<Token<'a>>,
}
impl<'a> AssertSerializer<'a> {
fn new(values: Vec<Token<'a>>) -> AssertSerializer {
AssertSerializer {
iter: values.into_iter(),
}
}
fn visit_sequence<V>(&mut self, mut visitor: V) -> Result<(), ()>
where V: SeqVisitor
{
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.iter.next(), Some(Token::SeqEnd));
Ok(())
}
fn visit_mapping<V>(&mut self, mut visitor: V) -> Result<(), ()>
where V: MapVisitor
{
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.iter.next(), Some(Token::MapEnd));
Ok(())
}
}
impl<'a> Serializer for AssertSerializer<'a> {
type Error = ();
fn visit_unit(&mut self) -> Result<(), ()> {
assert_eq!(self.iter.next(), Some(Token::Unit));
Ok(())
}
fn visit_named_unit(&mut self, name: &str) -> Result<(), ()> {
assert_eq!(self.iter.next().unwrap(), Token::NamedUnit(name));
Ok(())
}
fn visit_enum_unit(&mut self, name: &str, variant: &str) -> Result<(), ()> {
assert_eq!(self.iter.next().unwrap(), Token::EnumUnit(name, variant));
Ok(())
}
fn visit_bool(&mut self, v: bool) -> Result<(), ()> {
assert_eq!(self.iter.next(), Some(Token::Bool(v)));
Ok(())
}
fn visit_isize(&mut self, v: isize) -> Result<(), ()> {
assert_eq!(self.iter.next(), Some(Token::Isize(v)));
Ok(())
}
fn visit_i8(&mut self, v: i8) -> Result<(), ()> {
assert_eq!(self.iter.next(), Some(Token::I8(v)));
Ok(())
}
fn visit_i16(&mut self, v: i16) -> Result<(), ()> {
assert_eq!(self.iter.next(), Some(Token::I16(v)));
Ok(())
}
fn visit_i32(&mut self, v: i32) -> Result<(), ()> {
assert_eq!(self.iter.next(), Some(Token::I32(v)));
Ok(())
}
fn visit_i64(&mut self, v: i64) -> Result<(), ()> {
assert_eq!(self.iter.next(), Some(Token::I64(v)));
Ok(())
}
fn visit_usize(&mut self, v: usize) -> Result<(), ()> {
assert_eq!(self.iter.next(), Some(Token::Usize(v)));
Ok(())
}
fn visit_u8(&mut self, v: u8) -> Result<(), ()> {
assert_eq!(self.iter.next(), Some(Token::U8(v)));
Ok(())
}
fn visit_u16(&mut self, v: u16) -> Result<(), ()> {
assert_eq!(self.iter.next(), Some(Token::U16(v)));
Ok(())
}
fn visit_u32(&mut self, v: u32) -> Result<(), ()> {
assert_eq!(self.iter.next(), Some(Token::U32(v)));
Ok(())
}
fn visit_u64(&mut self, v: u64) -> Result<(), ()> {
assert_eq!(self.iter.next(), Some(Token::U64(v)));
Ok(())
}
fn visit_f32(&mut self, v: f32) -> Result<(), ()> {
assert_eq!(self.iter.next(), Some(Token::F32(v)));
Ok(())
}
fn visit_f64(&mut self, v: f64) -> Result<(), ()> {
assert_eq!(self.iter.next(), Some(Token::F64(v)));
Ok(())
}
fn visit_char(&mut self, v: char) -> Result<(), ()> {
assert_eq!(self.iter.next(), Some(Token::Char(v)));
Ok(())
}
fn visit_str(&mut self, v: &str) -> Result<(), ()> {
assert_eq!(self.iter.next().unwrap(), Token::Str(v));
Ok(())
}
fn visit_none(&mut self) -> Result<(), ()> {
assert_eq!(self.iter.next(), Some(Token::Option(false)));
Ok(())
}
fn visit_some<V>(&mut self, value: V) -> Result<(), ()>
where V: Serialize,
{
assert_eq!(self.iter.next(), Some(Token::Option(true)));
value.serialize(self)
}
fn visit_seq<V>(&mut self, visitor: V) -> Result<(), ()>
where V: SeqVisitor
{
let len = visitor.len();
assert_eq!(self.iter.next(), Some(Token::SeqStart(len)));
self.visit_sequence(visitor)
}
fn visit_named_seq<V>(&mut self, name: &str, visitor: V) -> Result<(), ()>
where V: SeqVisitor
{
let len = visitor.len();
assert_eq!(self.iter.next().unwrap(), Token::NamedSeqStart(name, len));
self.visit_sequence(visitor)
}
fn visit_enum_seq<V>(&mut self,
name: &str,
variant: &str,
visitor: V) -> Result<(), ()>
where V: SeqVisitor
{
let len = visitor.len();
assert_eq!(self.iter.next().unwrap(), Token::EnumSeqStart(name, variant, len));
self.visit_sequence(visitor)
}
fn visit_seq_elt<T>(&mut self, value: T) -> Result<(), ()>
where T: Serialize
{
assert_eq!(self.iter.next(), Some(Token::SeqSep));
value.serialize(self)
}
fn visit_map<V>(&mut self, visitor: V) -> Result<(), ()>
where V: MapVisitor
{
let len = visitor.len();
assert_eq!(self.iter.next(), Some(Token::MapStart(len)));
self.visit_mapping(visitor)
}
fn visit_named_map<V>(&mut self, name: &str, visitor: V) -> Result<(), ()>
where V: MapVisitor
{
let len = visitor.len();
assert_eq!(self.iter.next().unwrap(), Token::NamedMapStart(name, len));
self.visit_mapping(visitor)
}
fn visit_enum_map<V>(&mut self, name: &str, variant: &str, visitor: V) -> Result<(), ()>
where V: MapVisitor
{
let len = visitor.len();
assert_eq!(self.iter.next().unwrap(), Token::EnumMapStart(name, variant, len));
self.visit_mapping(visitor)
}
fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), ()>
where K: Serialize,
V: Serialize,
{
assert_eq!(self.iter.next(), Some(Token::MapSep));
try!(key.serialize(self));
value.serialize(self)
}
}
use token::{self, Token};
//////////////////////////////////////////////////////////////////////////
#[derive(Serialize)]
struct NamedUnit;
struct UnitStruct;
#[derive(Serialize)]
struct NamedSeq(i32, i32, i32);
struct TupleStruct(i32, i32, i32);
#[derive(Serialize)]
struct NamedMap {
struct Struct {
a: i32,
b: i32,
c: i32,
@@ -277,91 +23,69 @@ struct NamedMap {
#[derive(Serialize)]
enum Enum {
Unit,
One(i32),
Seq(i32, i32),
Map { a: i32, b: i32 },
}
//////////////////////////////////////////////////////////////////////////
macro_rules! btreemap {
() => {
BTreeMap::new()
};
($($key:expr => $value:expr),+) => {
{
let mut map = BTreeMap::new();
$(map.insert($key, $value);)+
map
}
}
}
macro_rules! declare_test {
($name:ident { $($value:expr => $tokens:expr,)+ }) => {
#[test]
fn $name() {
$(
let mut ser = AssertSerializer::new($tokens);
assert_eq!($value.serialize(&mut ser), Ok(()));
)+
}
}
}
macro_rules! declare_tests {
($($name:ident { $($value:expr => $tokens:expr,)+ })+) => {
$(
declare_test!($name { $($value => $tokens,)+ });
)+
}
}
declare_tests! {
declare_ser_tests! {
test_unit {
() => vec![Token::Unit],
() => &[Token::Unit],
}
test_bool {
true => vec![Token::Bool(true)],
false => vec![Token::Bool(false)],
true => &[Token::Bool(true)],
false => &[Token::Bool(false)],
}
test_isizes {
0isize => vec![Token::Isize(0)],
0i8 => vec![Token::I8(0)],
0i16 => vec![Token::I16(0)],
0i32 => vec![Token::I32(0)],
0i64 => vec![Token::I64(0)],
0isize => &[Token::Isize(0)],
0i8 => &[Token::I8(0)],
0i16 => &[Token::I16(0)],
0i32 => &[Token::I32(0)],
0i64 => &[Token::I64(0)],
}
test_usizes {
0usize => vec![Token::Usize(0)],
0u8 => vec![Token::U8(0)],
0u16 => vec![Token::U16(0)],
0u32 => vec![Token::U32(0)],
0u64 => vec![Token::U64(0)],
0usize => &[Token::Usize(0)],
0u8 => &[Token::U8(0)],
0u16 => &[Token::U16(0)],
0u32 => &[Token::U32(0)],
0u64 => &[Token::U64(0)],
}
test_floats {
0f32 => vec![Token::F32(0.)],
0f64 => vec![Token::F64(0.)],
0f32 => &[Token::F32(0.)],
0f64 => &[Token::F64(0.)],
}
test_char {
'a' => vec![Token::Char('a')],
'a' => &[Token::Char('a')],
}
test_str {
"abc" => vec![Token::Str("abc")],
"abc".to_string() => vec![Token::Str("abc")],
"abc" => &[Token::Str("abc")],
"abc".to_owned() => &[Token::Str("abc")],
}
test_option {
None::<i32> => vec![Token::Option(false)],
Some(1) => vec![
None::<i32> => &[Token::Option(false)],
Some(1) => &[
Token::Option(true),
Token::I32(1),
],
}
test_result {
Ok::<i32, i32>(0) => &[
Token::EnumNewType("Result", "Ok"),
Token::I32(0),
],
Err::<i32, i32>(1) => &[
Token::EnumNewType("Result", "Err"),
Token::I32(1),
],
}
test_slice {
&[0][..0] => vec![
&[0][..0] => &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
],
&[1, 2, 3][..] => vec![
&[1, 2, 3][..] => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(1),
@@ -375,12 +99,12 @@ declare_tests! {
],
}
test_array {
[0; 0] => vec![
Token::SeqStart(Some(0)),
[0; 0] => &[
Token::SeqArrayStart(0),
Token::SeqEnd,
],
[1, 2, 3] => vec![
Token::SeqStart(Some(3)),
[1, 2, 3] => &[
Token::SeqArrayStart(3),
Token::SeqSep,
Token::I32(1),
@@ -393,11 +117,11 @@ declare_tests! {
],
}
test_vec {
Vec::<isize>::new() => vec![
Vec::<isize>::new() => &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
],
vec![vec![], vec![1], vec![2, 3]] => vec![
vec![vec![], vec![1], vec![2, 3]] => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::SeqStart(Some(0)),
@@ -421,34 +145,34 @@ declare_tests! {
],
}
test_tuple {
(1,) => vec![
Token::SeqStart(Some(1)),
Token::SeqSep,
(1,) => &[
Token::TupleStart(1),
Token::TupleSep,
Token::I32(1),
Token::SeqEnd,
Token::TupleEnd,
],
(1, 2, 3) => vec![
Token::SeqStart(Some(3)),
Token::SeqSep,
(1, 2, 3) => &[
Token::TupleStart(3),
Token::TupleSep,
Token::I32(1),
Token::SeqSep,
Token::TupleSep,
Token::I32(2),
Token::SeqSep,
Token::TupleSep,
Token::I32(3),
Token::SeqEnd,
Token::TupleEnd,
],
}
test_btreemap {
btreemap![1 => 2] => vec![
btreemap![1 => 2] => &[
Token::MapStart(Some(1)),
Token::MapSep,
Token::I32(1),
Token::I32(2),
Token::MapEnd,
],
btreemap![1 => 2, 3 => 4] => vec![
btreemap![1 => 2, 3 => 4] => &[
Token::MapStart(Some(2)),
Token::MapSep,
Token::I32(1),
@@ -459,7 +183,7 @@ declare_tests! {
Token::I32(4),
Token::MapEnd,
],
btreemap![1 => btreemap![], 2 => btreemap![3 => 4, 5 => 6]] => vec![
btreemap![1 => btreemap![], 2 => btreemap![3 => 4, 5 => 6]] => &[
Token::MapStart(Some(2)),
Token::MapSep,
Token::I32(1),
@@ -480,61 +204,111 @@ declare_tests! {
Token::MapEnd,
],
}
test_named_unit {
NamedUnit => vec![Token::NamedUnit("NamedUnit")],
test_unit_struct {
UnitStruct => &[Token::UnitStruct("UnitStruct")],
}
test_named_seq {
NamedSeq(1, 2, 3) => vec![
Token::NamedSeqStart("NamedSeq", Some(3)),
Token::SeqSep,
test_tuple_struct {
TupleStruct(1, 2, 3) => &[
Token::TupleStructStart("TupleStruct", Some(3)),
Token::TupleStructSep,
Token::I32(1),
Token::SeqSep,
Token::TupleStructSep,
Token::I32(2),
Token::SeqSep,
Token::TupleStructSep,
Token::I32(3),
Token::SeqEnd,
Token::TupleStructEnd,
],
}
test_named_map {
NamedMap { a: 1, b: 2, c: 3 } => vec![
Token::NamedMapStart("NamedMap", Some(3)),
Token::MapSep,
test_struct {
Struct { a: 1, b: 2, c: 3 } => &[
Token::StructStart("Struct", Some(3)),
Token::StructSep,
Token::Str("a"),
Token::I32(1),
Token::MapSep,
Token::StructSep,
Token::Str("b"),
Token::I32(2),
Token::MapSep,
Token::StructSep,
Token::Str("c"),
Token::I32(3),
Token::MapEnd,
Token::StructEnd,
],
}
test_enum {
Enum::Unit => vec![Token::EnumUnit("Enum", "Unit")],
Enum::Seq(1, 2) => vec![
Enum::Unit => &[Token::EnumUnit("Enum", "Unit")],
Enum::One(42) => &[Token::EnumNewType("Enum", "One"), Token::I32(42)],
Enum::Seq(1, 2) => &[
Token::EnumSeqStart("Enum", "Seq", Some(2)),
Token::SeqSep,
Token::EnumSeqSep,
Token::I32(1),
Token::SeqSep,
Token::EnumSeqSep,
Token::I32(2),
Token::SeqEnd,
Token::EnumSeqEnd,
],
Enum::Map { a: 1, b: 2 } => vec![
Enum::Map { a: 1, b: 2 } => &[
Token::EnumMapStart("Enum", "Map", Some(2)),
Token::MapSep,
Token::EnumMapSep,
Token::Str("a"),
Token::I32(1),
Token::MapSep,
Token::EnumMapSep,
Token::Str("b"),
Token::I32(2),
Token::MapEnd,
Token::EnumMapEnd,
],
}
test_net_ipv4addr {
"1.2.3.4".parse::<net::Ipv4Addr>().unwrap() => &[Token::Str("1.2.3.4")],
}
test_net_ipv6addr {
"::1".parse::<net::Ipv6Addr>().unwrap() => &[Token::Str("::1")],
}
test_net_socketaddr {
"1.2.3.4:1234".parse::<net::SocketAddr>().unwrap() => &[Token::Str("1.2.3.4:1234")],
"1.2.3.4:1234".parse::<net::SocketAddrV4>().unwrap() => &[Token::Str("1.2.3.4:1234")],
"[::1]:1234".parse::<net::SocketAddrV6>().unwrap() => &[Token::Str("[::1]:1234")],
}
test_path {
Path::new("/usr/local/lib") => &[
Token::Str("/usr/local/lib"),
],
}
test_path_buf {
PathBuf::from("/usr/local/lib") => &[
Token::Str("/usr/local/lib"),
],
}
}
#[cfg(feature = "nightly")]
#[test]
fn test_net_ipaddr() {
assert_ser_tokens(
"1.2.3.4".parse::<net::IpAddr>().unwrap(),
&[Token::Str("1.2.3.4")],
);
}
#[test]
fn test_cannot_serialize_paths() {
let path = unsafe {
str::from_utf8_unchecked(b"Hello \xF0\x90\x80World")
};
token::assert_ser_tokens_error(
&Path::new(path),
&[Token::Str("Hello World")],
token::Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned()));
let mut path_buf = PathBuf::new();
path_buf.push(path);
token::assert_ser_tokens_error(
&path_buf,
&[Token::Str("Hello World")],
token::Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned()));
}
File diff suppressed because it is too large Load Diff