summaryrefslogtreecommitdiffstats
path: root/third_party/rust/serde_cbor
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/rust/serde_cbor
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/serde_cbor')
-rw-r--r--third_party/rust/serde_cbor/.cargo-checksum.json1
-rw-r--r--third_party/rust/serde_cbor/CONTRIBUTING.md29
-rw-r--r--third_party/rust/serde_cbor/Cargo.lock68
-rw-r--r--third_party/rust/serde_cbor/Cargo.toml44
-rw-r--r--third_party/rust/serde_cbor/LICENSE-APACHE201
-rw-r--r--third_party/rust/serde_cbor/LICENSE-MIT19
-rw-r--r--third_party/rust/serde_cbor/README.md97
-rw-r--r--third_party/rust/serde_cbor/examples/readme.rs39
-rw-r--r--third_party/rust/serde_cbor/examples/tags.rs84
-rw-r--r--third_party/rust/serde_cbor/examples/tux.cbor1
-rw-r--r--third_party/rust/serde_cbor/src/de.rs1360
-rw-r--r--third_party/rust/serde_cbor/src/error.rs318
-rw-r--r--third_party/rust/serde_cbor/src/lib.rs369
-rw-r--r--third_party/rust/serde_cbor/src/read.rs637
-rw-r--r--third_party/rust/serde_cbor/src/ser.rs743
-rw-r--r--third_party/rust/serde_cbor/src/tags.rs220
-rw-r--r--third_party/rust/serde_cbor/src/value/de.rs166
-rw-r--r--third_party/rust/serde_cbor/src/value/mod.rs156
-rw-r--r--third_party/rust/serde_cbor/src/value/ser.rs443
-rw-r--r--third_party/rust/serde_cbor/src/write.rs175
-rw-r--r--third_party/rust/serde_cbor/tests/bennofs.rs60
-rw-r--r--third_party/rust/serde_cbor/tests/canonical.rs104
-rw-r--r--third_party/rust/serde_cbor/tests/crash.cborbin0 -> 190 bytes
-rw-r--r--third_party/rust/serde_cbor/tests/de.rs747
-rw-r--r--third_party/rust/serde_cbor/tests/enum.rs236
-rw-r--r--third_party/rust/serde_cbor/tests/kietaub.cborbin0 -> 212 bytes
-rw-r--r--third_party/rust/serde_cbor/tests/ser.rs254
-rw-r--r--third_party/rust/serde_cbor/tests/std_types.rs186
-rw-r--r--third_party/rust/serde_cbor/tests/tags.rs48
-rw-r--r--third_party/rust/serde_cbor/tests/value.rs100
30 files changed, 6905 insertions, 0 deletions
diff --git a/third_party/rust/serde_cbor/.cargo-checksum.json b/third_party/rust/serde_cbor/.cargo-checksum.json
new file mode 100644
index 0000000000..03e08b7b06
--- /dev/null
+++ b/third_party/rust/serde_cbor/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CONTRIBUTING.md":"bcbbc1fd8aefd2af15d432b551ddc32b0b832c1ad669eeedfaffb2092448c080","Cargo.lock":"b900f78562d5ae2ffffc0e8f739328df268f0fb80696018eb5df8e5e633b733e","Cargo.toml":"522e55ca99d851f9a3e7361f090451fc87c6097320c77bd574a80df27c183078","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"e03e58ea9205f51989b7a50f450051b24e6516cc1f0b920222dcda992072be99","README.md":"abb494d9608a40bac62da0bbd4680c0f03d960922d92261fb6492a1ee448d5c6","examples/readme.rs":"2e356830c62e84605d6b7efa07a0266ad96ed960fde09d4ae241c642ff662ab2","examples/tags.rs":"a1e1e4de8a5b09c54f96a56b8d7dc749fff9c73facb1dcad05540bc83f34dbd2","examples/tux.cbor":"3251bceb0a182543de2129cd920b2af597c481513a0624887a7daeb468c530f8","src/de.rs":"433d2e10bf1be80f881dfd5355a0df1a1c6b1e09a2d36c4d6f39894b13b42e0b","src/error.rs":"9247283d47617626c90a0d32bba40b54a18c6bb0ecce37057d7423ff9158d223","src/lib.rs":"efe97da47a332789d29eb4480a65ae00b4ccd9e6ba22d2b2c945cbeb97edf2b5","src/read.rs":"001754714cf10e9691e3284bf8170348346858be8e5d72ee845853b928588c7c","src/ser.rs":"0b7cb6162e104bfea55f6bffa591d19876236a798134fec8dbabb1c2d4a22363","src/tags.rs":"8d83efd96daca49ac51f24d41b986f4247fcd2a011855ffc99e9388834bd31a3","src/value/de.rs":"986784dcf015464b01f669949f823ba0e29b7414f6d56cad3311cee036d1a954","src/value/mod.rs":"0afa696a6ed01f97380f84e4e219090393bc8cc52cd9c11f4db3eb5b1fb85e7f","src/value/ser.rs":"f5d505125ae496c99d611c24cb0905199b3b66b949ae18bb48863317b686f301","src/write.rs":"6bcc413fe531799cd979d954615e73dd87e185082858a63c5aef73f0fbe08806","tests/bennofs.rs":"2211b234f442e909659f0610fcb20e7cf746bc6c648fe258e5300ebcd6a4251f","tests/canonical.rs":"37fcbe3a1956c72e4aef808acb2e194f09ae8aaa752c6a94cf6d06731c19948d","tests/crash.cbor":"8aeb60947fc5d43e80f3c884fc6cb37c9021cc691492d055a14e55c69b366d1f","tests/de.rs":"545cf5f5bd1ab0b3b4c05c4985baf40ad419dc1568f28549d17eacf5efc7beb7","tests/enum.rs":"699886e517546396979c9843b6d1c513b4370af81e2b0d3bcf0727435c5c0a8a","tests/kietaub.cbor":"98146fa75d5970eea896baa19b5aeda31695d6ceeed4b23aa67fc13142123a9a","tests/ser.rs":"7eadf27fb58b8bd498f0be8e1670d76de36e3f21b565daeb8ec9cf30140c068e","tests/std_types.rs":"549e357ad5062eb8ae298df3bbbd0e8ee87ee0434f8c67dc53642ff2b2171e40","tests/tags.rs":"e847b9ab49f47a81a09e34d4af3bd25bb546e408915f033dc06b03b275f68065","tests/value.rs":"540469dccb6c6f3542b75934707203dff93132a7e160de798a21f16caf16075e"},"package":"2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"} \ No newline at end of file
diff --git a/third_party/rust/serde_cbor/CONTRIBUTING.md b/third_party/rust/serde_cbor/CONTRIBUTING.md
new file mode 100644
index 0000000000..1489ade658
--- /dev/null
+++ b/third_party/rust/serde_cbor/CONTRIBUTING.md
@@ -0,0 +1,29 @@
+# Contributing to Serde CBOR
+Thanks for your interest!
+There are many ways to help:
+
+* write an issue about a problem you encountered
+* submit a pull request
+* add documentation and examples
+
+## Pull Requests
+
+Code should be easy to understand and documented.
+For new features and fixed bugs please add a test to one of the files in `test/`.
+The tests are run on Travis CI to catch regressions early.
+Format your code with `cargo fmt` before committing.
+Currently Serde CBOR does not contain `unsafe` code and I would like to keep it this way.
+
+## Making a Release
+
+* [ ] Make sure the crate compiles and all tests pass.
+* [ ] (Optional) Test that the fuzzer works and fuzz the crate for some time.
+* [ ] Write a list with all changes made since the last release
+* [ ] Increment the version number in `Cargo.toml` and the `README.md`. Bugfixes increase the patch version while new features or an increased minimum Rust version require a new minor version.
+* [ ] Check that the file `examples/readme.rs` and the example from the `README.md` match.
+* [ ] Commit the changes.
+* [ ] Add a git tag with the new version number:
+ `git tag "v42.0.2"`
+* [ ] Push the changes: `git push --tags`
+* [ ] Run `cargo publish`
+* [ ] Add a new release to GitHub with a list of changes. \ No newline at end of file
diff --git a/third_party/rust/serde_cbor/Cargo.lock b/third_party/rust/serde_cbor/Cargo.lock
new file mode 100644
index 0000000000..b91ed7cd52
--- /dev/null
+++ b/third_party/rust/serde_cbor/Cargo.lock
@@ -0,0 +1,68 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "half"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ff54597ea139063f4225f1ec47011b03c9de4a486957ff3fc506881dac951d0"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
+
+[[package]]
+name = "serde_cbor"
+version = "0.11.2"
+dependencies = [
+ "half",
+ "serde",
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
diff --git a/third_party/rust/serde_cbor/Cargo.toml b/third_party/rust/serde_cbor/Cargo.toml
new file mode 100644
index 0000000000..2960dbe95d
--- /dev/null
+++ b/third_party/rust/serde_cbor/Cargo.toml
@@ -0,0 +1,44 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "serde_cbor"
+version = "0.11.2"
+authors = ["Pyfisch <pyfisch@posteo.org>", "Steven Fackler <sfackler@gmail.com>"]
+description = "CBOR support for serde."
+readme = "README.md"
+keywords = ["serde", "cbor", "serialization", "no_std"]
+categories = ["encoding"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/pyfisch/cbor"
+[dependencies.half]
+version = "1.2.0"
+
+[dependencies.serde]
+version = "1.0.14"
+default-features = false
+[dev-dependencies.serde_derive]
+version = "1.0.14"
+default-features = false
+
+[features]
+alloc = ["serde/alloc"]
+default = ["std"]
+std = ["serde/std"]
+tags = []
+unsealed_read_write = []
+[badges.maintenance]
+status = "as-is"
+
+[badges.travis-ci]
+repository = "pyfisch/cbor"
diff --git a/third_party/rust/serde_cbor/LICENSE-APACHE b/third_party/rust/serde_cbor/LICENSE-APACHE
new file mode 100644
index 0000000000..16fe87b06e
--- /dev/null
+++ b/third_party/rust/serde_cbor/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/third_party/rust/serde_cbor/LICENSE-MIT b/third_party/rust/serde_cbor/LICENSE-MIT
new file mode 100644
index 0000000000..b1b75fa62c
--- /dev/null
+++ b/third_party/rust/serde_cbor/LICENSE-MIT
@@ -0,0 +1,19 @@
+Copyright (c) 2015 Pyfisch
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/third_party/rust/serde_cbor/README.md b/third_party/rust/serde_cbor/README.md
new file mode 100644
index 0000000000..b49e8adbc3
--- /dev/null
+++ b/third_party/rust/serde_cbor/README.md
@@ -0,0 +1,97 @@
+# Serde CBOR
+[![Build Status](https://travis-ci.org/pyfisch/cbor.svg?branch=master)](https://travis-ci.org/pyfisch/cbor)
+[![Crates.io](https://img.shields.io/crates/v/serde_cbor.svg)](https://crates.io/crates/serde_cbor)
+[![Documentation](https://docs.rs/serde_cbor/badge.svg)](https://docs.rs/serde_cbor)
+
+## PROJECT IS ARCHIVED
+
+After almost 6 years it is time to retire this crate.
+This implementation of CBOR for serde is used in hundreds of projects with widely differing needs.
+Besides the standard features it contains code for no-std environments, a packed encoding and CBOR tags.
+However while these features are useful to many people they sometimes interact poorly with each others and with optional features of serde itself.
+Because I don't use the crate myself and because of the potential for new errors I have been reluctant to accept any changes or additional features for the crate.
+Since this situation is unlikely to change anytime soon and no one else stepped up to maintain this crate I am archiving the repository today.
+If the crate works for you there is no need to switch to another implementation.
+However if you encounter problems or for new projects I recommend you take a look at these crates:
+
+* [ciborium](https://crates.io/crates/ciborium)
+* [minicbor](https://crates.io/crates/minicbor)
+
+~~ Pyfisch, August 2021
+
+
+
+This crate implements the Concise Binary Object Representation from [RFC 7049].
+It builds on [Serde], the generic serialization framework for Rust.
+CBOR provides a binary encoding for a superset
+of the JSON data model that is small and very fast to parse.
+
+[RFC 7049]: https://tools.ietf.org/html/rfc7049
+[Serde]: https://github.com/serde-rs/serde
+
+## Usage
+
+Serde CBOR supports Rust 1.40 and up. Add this to your `Cargo.toml`:
+```toml
+[dependencies]
+serde_cbor = "0.11.2"
+```
+
+Storing and loading Rust types is easy and requires only
+minimal modifications to the program code.
+
+```rust
+use serde_derive::{Deserialize, Serialize};
+use std::error::Error;
+use std::fs::File;
+
+// Types annotated with `Serialize` can be stored as CBOR.
+// To be able to load them again add `Deserialize`.
+#[derive(Debug, Serialize, Deserialize)]
+struct Mascot {
+ name: String,
+ species: String,
+ year_of_birth: u32,
+}
+
+fn main() -> Result<(), Box<dyn Error>> {
+ let ferris = Mascot {
+ name: "Ferris".to_owned(),
+ species: "crab".to_owned(),
+ year_of_birth: 2015,
+ };
+
+ let ferris_file = File::create("examples/ferris.cbor")?;
+ // Write Ferris to the given file.
+ // Instead of a file you can use any type that implements `io::Write`
+ // like a HTTP body, database connection etc.
+ serde_cbor::to_writer(ferris_file, &ferris)?;
+
+ let tux_file = File::open("examples/tux.cbor")?;
+ // Load Tux from a file.
+ // Serde CBOR performs roundtrip serialization meaning that
+ // the data will not change in any way.
+ let tux: Mascot = serde_cbor::from_reader(tux_file)?;
+
+ println!("{:?}", tux);
+ // prints: Mascot { name: "Tux", species: "penguin", year_of_birth: 1996 }
+
+ Ok(())
+}
+```
+
+There are a lot of options available to customize the format.
+To operate on untyped CBOR values have a look at the `Value` type.
+
+## License
+Licensed under either of
+
+ * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
+additional terms or conditions.
diff --git a/third_party/rust/serde_cbor/examples/readme.rs b/third_party/rust/serde_cbor/examples/readme.rs
new file mode 100644
index 0000000000..7689394b79
--- /dev/null
+++ b/third_party/rust/serde_cbor/examples/readme.rs
@@ -0,0 +1,39 @@
+// NOTE: This file should be kept in sync with README.md
+
+use serde_derive::{Deserialize, Serialize};
+use std::error::Error;
+use std::fs::File;
+
+// Types annotated with `Serialize` can be stored as CBOR.
+// To be able to load them again add `Deserialize`.
+#[derive(Debug, Serialize, Deserialize)]
+struct Mascot {
+ name: String,
+ species: String,
+ year_of_birth: u32,
+}
+
+fn main() -> Result<(), Box<dyn Error>> {
+ let ferris = Mascot {
+ name: "Ferris".to_owned(),
+ species: "crab".to_owned(),
+ year_of_birth: 2015,
+ };
+
+ let ferris_file = File::create("examples/ferris.cbor")?;
+ // Write Ferris to the given file.
+ // Instead of a file you can use any type that implements `io::Write`
+ // like a HTTP body, database connection etc.
+ serde_cbor::to_writer(ferris_file, &ferris)?;
+
+ let tux_file = File::open("examples/tux.cbor")?;
+ // Load Tux from a file.
+ // Serde CBOR performs roundtrip serialization meaning that
+ // the data will not change in any way.
+ let tux: Mascot = serde_cbor::from_reader(tux_file)?;
+
+ println!("{:?}", tux);
+ // prints: Mascot { name: "Tux", species: "penguin", year_of_birth: 1996 }
+
+ Ok(())
+}
diff --git a/third_party/rust/serde_cbor/examples/tags.rs b/third_party/rust/serde_cbor/examples/tags.rs
new file mode 100644
index 0000000000..9281b9b845
--- /dev/null
+++ b/third_party/rust/serde_cbor/examples/tags.rs
@@ -0,0 +1,84 @@
+use serde::de::{Deserialize, Deserializer};
+use serde::ser::{Serialize, Serializer};
+use serde_cbor::tags::Tagged;
+use serde_cbor::Value;
+use serde_derive::{Deserialize, Serialize};
+use std::error::Error;
+
+/// https://tools.ietf.org/html/rfc7049#section-2.4.1
+#[derive(Debug, PartialEq)]
+struct Date(String);
+
+impl Serialize for Date {
+ fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
+ Tagged::new(Some(0), &self.0).serialize(s)
+ }
+}
+
+impl<'de> Deserialize<'de> for Date {
+ fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
+ let tagged = Tagged::<String>::deserialize(deserializer)?;
+ match tagged.tag {
+ Some(0) | None => Ok(Date(tagged.value)),
+ Some(_) => Err(serde::de::Error::custom("unexpected tag")),
+ }
+ }
+}
+
+/// https://tools.ietf.org/html/rfc7049#section-2.4.4.3
+#[derive(Debug, PartialEq)]
+struct Uri(String);
+
+impl Serialize for Uri {
+ fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
+ Tagged::new(Some(32), &self.0).serialize(s)
+ }
+}
+impl<'de> Deserialize<'de> for Uri {
+ fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
+ let tagged = Tagged::<String>::deserialize(deserializer)?;
+ match tagged.tag {
+ // allow deserialization even if there is no tag. Allows roundtrip via other formats such as json
+ Some(0) | None => Ok(Uri(tagged.value)),
+ Some(_) => Err(serde::de::Error::custom("unexpected tag")),
+ }
+ }
+}
+
+#[derive(Debug, Serialize, Deserialize, PartialEq)]
+struct Bookmark {
+ title: String,
+ link: Uri,
+ created: Date,
+}
+
+fn main() -> Result<(), Box<dyn Error>> {
+ let bookmark = Bookmark {
+ title: "The Example Domain".into(),
+ link: Uri("http://example.org/".into()),
+ created: Date("2003-12-13T18:30:02Z".into()),
+ };
+
+ // serialize the struct to bytes
+ let bytes1 = serde_cbor::to_vec(&bookmark)?;
+ // deserialize to a serde_cbor::Value
+ let value1: Value = serde_cbor::from_slice(&bytes1)?;
+ println!("{:?}", value1);
+ // serialize the value to bytes
+ let bytes2 = serde_cbor::to_vec(&value1)?;
+ // deserialize to a serde_cbor::Value
+ let value2: Value = serde_cbor::from_slice(&bytes2)?;
+ println!("{:?}", value2);
+ // deserialize to a Bookmark
+ let result: Bookmark = serde_cbor::from_slice(&bytes2)?;
+
+ // check that the roundtrip was successful
+ assert_eq!(value1, value2);
+ assert_eq!(bookmark, result);
+
+ // check that going via a format that does not support tags does work
+ // let json = serde_json::to_vec(&bookmark)?;
+ // let result: Bookmark = serde_json::from_slice(&json)?;
+ // assert_eq!(bookmark, result);
+ Ok(())
+}
diff --git a/third_party/rust/serde_cbor/examples/tux.cbor b/third_party/rust/serde_cbor/examples/tux.cbor
new file mode 100644
index 0000000000..c3331aabc1
--- /dev/null
+++ b/third_party/rust/serde_cbor/examples/tux.cbor
@@ -0,0 +1 @@
+£dnamecTuxgspeciesgpenguinmyear_of_birthÌ \ No newline at end of file
diff --git a/third_party/rust/serde_cbor/src/de.rs b/third_party/rust/serde_cbor/src/de.rs
new file mode 100644
index 0000000000..170e0593cf
--- /dev/null
+++ b/third_party/rust/serde_cbor/src/de.rs
@@ -0,0 +1,1360 @@
+//! Deserialization.
+
+use core::f32;
+use core::marker::PhantomData;
+use core::result;
+use core::str;
+use half::f16;
+use serde::de;
+#[cfg(feature = "std")]
+use std::io;
+
+use crate::error::{Error, ErrorCode, Result};
+#[cfg(not(feature = "unsealed_read_write"))]
+use crate::read::EitherLifetime;
+#[cfg(feature = "unsealed_read_write")]
+pub use crate::read::EitherLifetime;
+#[cfg(feature = "std")]
+pub use crate::read::IoRead;
+use crate::read::Offset;
+#[cfg(any(feature = "std", feature = "alloc"))]
+pub use crate::read::SliceRead;
+pub use crate::read::{MutSliceRead, Read, SliceReadFixed};
+#[cfg(feature = "tags")]
+use crate::tags::set_tag;
+/// Decodes a value from CBOR data in a slice.
+///
+/// # Examples
+///
+/// Deserialize a `String`
+///
+/// ```
+/// # use serde_cbor::de;
+/// let v: Vec<u8> = vec![0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72];
+/// let value: String = de::from_slice(&v[..]).unwrap();
+/// assert_eq!(value, "foobar");
+/// ```
+///
+/// Deserialize a borrowed string with zero copies.
+///
+/// ```
+/// # use serde_cbor::de;
+/// let v: Vec<u8> = vec![0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72];
+/// let value: &str = de::from_slice(&v[..]).unwrap();
+/// assert_eq!(value, "foobar");
+/// ```
+#[cfg(any(feature = "std", feature = "alloc"))]
+pub fn from_slice<'a, T>(slice: &'a [u8]) -> Result<T>
+where
+ T: de::Deserialize<'a>,
+{
+ let mut deserializer = Deserializer::from_slice(slice);
+ let value = de::Deserialize::deserialize(&mut deserializer)?;
+ deserializer.end()?;
+ Ok(value)
+}
+
+// When the "std" feature is enabled there should be little to no need to ever use this function,
+// as `from_slice` covers all use cases (at the expense of being less efficient).
+/// Decode a value from CBOR data in a mutable slice.
+///
+/// This can be used in analogy to `from_slice`. Unlike `from_slice`, this will use the slice's
+/// mutability to rearrange data in it in order to resolve indefinite byte or text strings without
+/// resorting to allocations.
+pub fn from_mut_slice<'a, T>(slice: &'a mut [u8]) -> Result<T>
+where
+ T: de::Deserialize<'a>,
+{
+ let mut deserializer = Deserializer::from_mut_slice(slice);
+ let value = de::Deserialize::deserialize(&mut deserializer)?;
+ deserializer.end()?;
+ Ok(value)
+}
+
+// When the "std" feature is enabled there should be little to no need to ever use this function,
+// as `from_slice` covers all use cases and is much more reliable (at the expense of being less
+// efficient).
+/// Decode a value from CBOR data using a scratch buffer.
+///
+/// Users should generally prefer to use `from_slice` or `from_mut_slice` over this function,
+/// as decoding may fail when the scratch buffer turns out to be too small.
+///
+/// A realistic use case for this method would be decoding in a `no_std` environment from an
+/// immutable slice that is too large to copy.
+pub fn from_slice_with_scratch<'a, 'b, T>(slice: &'a [u8], scratch: &'b mut [u8]) -> Result<T>
+where
+ T: de::Deserialize<'a>,
+{
+ let mut deserializer = Deserializer::from_slice_with_scratch(slice, scratch);
+ let value = de::Deserialize::deserialize(&mut deserializer)?;
+ deserializer.end()?;
+ Ok(value)
+}
+
+/// Decodes a value from CBOR data in a reader.
+///
+/// # Examples
+///
+/// Deserialize a `String`
+///
+/// ```
+/// # use serde_cbor::de;
+/// let v: Vec<u8> = vec![0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72];
+/// let value: String = de::from_reader(&v[..]).unwrap();
+/// assert_eq!(value, "foobar");
+/// ```
+///
+/// Note that `from_reader` cannot borrow data:
+///
+/// ```compile_fail
+/// # use serde_cbor::de;
+/// let v: Vec<u8> = vec![0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72];
+/// let value: &str = de::from_reader(&v[..]).unwrap();
+/// assert_eq!(value, "foobar");
+/// ```
+#[cfg(feature = "std")]
+pub fn from_reader<T, R>(reader: R) -> Result<T>
+where
+ T: de::DeserializeOwned,
+ R: io::Read,
+{
+ let mut deserializer = Deserializer::from_reader(reader);
+ let value = de::Deserialize::deserialize(&mut deserializer)?;
+ deserializer.end()?;
+ Ok(value)
+}
+
+/// A Serde `Deserialize`r of CBOR data.
+#[derive(Debug)]
+pub struct Deserializer<R> {
+ read: R,
+ remaining_depth: u8,
+ accept_named: bool,
+ accept_packed: bool,
+ accept_standard_enums: bool,
+ accept_legacy_enums: bool,
+}
+
+#[cfg(feature = "std")]
+impl<R> Deserializer<IoRead<R>>
+where
+ R: io::Read,
+{
+ /// Constructs a `Deserializer` which reads from a `Read`er.
+ pub fn from_reader(reader: R) -> Deserializer<IoRead<R>> {
+ Deserializer::new(IoRead::new(reader))
+ }
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a> Deserializer<SliceRead<'a>> {
+ /// Constructs a `Deserializer` which reads from a slice.
+ ///
+ /// Borrowed strings and byte slices will be provided when possible.
+ pub fn from_slice(bytes: &'a [u8]) -> Deserializer<SliceRead<'a>> {
+ Deserializer::new(SliceRead::new(bytes))
+ }
+}
+
+impl<'a> Deserializer<MutSliceRead<'a>> {
+ /// Constructs a `Deserializer` which reads from a mutable slice that doubles as its own
+ /// scratch buffer.
+ ///
+ /// Borrowed strings and byte slices will be provided even for indefinite strings.
+ pub fn from_mut_slice(bytes: &'a mut [u8]) -> Deserializer<MutSliceRead<'a>> {
+ Deserializer::new(MutSliceRead::new(bytes))
+ }
+}
+
+impl<'a, 'b> Deserializer<SliceReadFixed<'a, 'b>> {
+ #[doc(hidden)]
+ pub fn from_slice_with_scratch(
+ bytes: &'a [u8],
+ scratch: &'b mut [u8],
+ ) -> Deserializer<SliceReadFixed<'a, 'b>> {
+ Deserializer::new(SliceReadFixed::new(bytes, scratch))
+ }
+}
+
+impl<'de, R> Deserializer<R>
+where
+ R: Read<'de>,
+{
+ /// Constructs a `Deserializer` from one of the possible serde_cbor input sources.
+ ///
+ /// `from_slice` and `from_reader` should normally be used instead of this method.
+ pub fn new(read: R) -> Self {
+ Deserializer {
+ read,
+ remaining_depth: 128,
+ accept_named: true,
+ accept_packed: true,
+ accept_standard_enums: true,
+ accept_legacy_enums: true,
+ }
+ }
+
+ /// Don't accept named variants and fields.
+ pub fn disable_named_format(mut self) -> Self {
+ self.accept_named = false;
+ self
+ }
+
+ /// Don't accept numbered variants and fields.
+ pub fn disable_packed_format(mut self) -> Self {
+ self.accept_packed = false;
+ self
+ }
+
+ /// Don't accept the new enum format used by `serde_cbor` versions >= v0.10.
+ pub fn disable_standard_enums(mut self) -> Self {
+ self.accept_standard_enums = false;
+ self
+ }
+
+ /// Don't accept the old enum format used by `serde_cbor` versions <= v0.9.
+ pub fn disable_legacy_enums(mut self) -> Self {
+ self.accept_legacy_enums = false;
+ self
+ }
+
+ /// This method should be called after a value has been deserialized to ensure there is no
+ /// trailing data in the input source.
+ pub fn end(&mut self) -> Result<()> {
+ match self.next()? {
+ Some(_) => Err(self.error(ErrorCode::TrailingData)),
+ None => Ok(()),
+ }
+ }
+
+ /// Turn a CBOR deserializer into an iterator over values of type T.
+ #[allow(clippy::should_implement_trait)] // Trait doesn't allow unconstrained T.
+ pub fn into_iter<T>(self) -> StreamDeserializer<'de, R, T>
+ where
+ T: de::Deserialize<'de>,
+ {
+ StreamDeserializer {
+ de: self,
+ output: PhantomData,
+ lifetime: PhantomData,
+ }
+ }
+
+ fn next(&mut self) -> Result<Option<u8>> {
+ self.read.next()
+ }
+
+ fn peek(&mut self) -> Result<Option<u8>> {
+ self.read.peek()
+ }
+
+ fn consume(&mut self) {
+ self.read.discard();
+ }
+
+ fn error(&self, reason: ErrorCode) -> Error {
+ let offset = self.read.offset();
+ Error::syntax(reason, offset)
+ }
+
+ fn parse_u8(&mut self) -> Result<u8> {
+ match self.next()? {
+ Some(byte) => Ok(byte),
+ None => Err(self.error(ErrorCode::EofWhileParsingValue)),
+ }
+ }
+
+ fn parse_u16(&mut self) -> Result<u16> {
+ let mut buf = [0; 2];
+ self.read
+ .read_into(&mut buf)
+ .map(|()| u16::from_be_bytes(buf))
+ }
+
+ fn parse_u32(&mut self) -> Result<u32> {
+ let mut buf = [0; 4];
+ self.read
+ .read_into(&mut buf)
+ .map(|()| u32::from_be_bytes(buf))
+ }
+
+ fn parse_u64(&mut self) -> Result<u64> {
+ let mut buf = [0; 8];
+ self.read
+ .read_into(&mut buf)
+ .map(|()| u64::from_be_bytes(buf))
+ }
+
+ fn parse_bytes<V>(&mut self, len: usize, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ match self.read.read(len)? {
+ EitherLifetime::Long(buf) => visitor.visit_borrowed_bytes(buf),
+ EitherLifetime::Short(buf) => visitor.visit_bytes(buf),
+ }
+ }
+
+ fn parse_indefinite_bytes<V>(&mut self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ self.read.clear_buffer();
+ loop {
+ let byte = self.parse_u8()?;
+ let len = match byte {
+ 0x40..=0x57 => byte as usize - 0x40,
+ 0x58 => self.parse_u8()? as usize,
+ 0x59 => self.parse_u16()? as usize,
+ 0x5a => self.parse_u32()? as usize,
+ 0x5b => {
+ let len = self.parse_u64()?;
+ if len > usize::max_value() as u64 {
+ return Err(self.error(ErrorCode::LengthOutOfRange));
+ }
+ len as usize
+ }
+ 0xff => break,
+ _ => return Err(self.error(ErrorCode::UnexpectedCode)),
+ };
+
+ self.read.read_to_buffer(len)?;
+ }
+
+ match self.read.take_buffer() {
+ EitherLifetime::Long(buf) => visitor.visit_borrowed_bytes(buf),
+ EitherLifetime::Short(buf) => visitor.visit_bytes(buf),
+ }
+ }
+
+ fn convert_str<'a>(buf: &'a [u8], buf_end_offset: u64) -> Result<&'a str> {
+ match str::from_utf8(buf) {
+ Ok(s) => Ok(s),
+ Err(e) => {
+ let shift = buf.len() - e.valid_up_to();
+ let offset = buf_end_offset - shift as u64;
+ Err(Error::syntax(ErrorCode::InvalidUtf8, offset))
+ }
+ }
+ }
+
+ fn parse_str<V>(&mut self, len: usize, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ if let Some(offset) = self.read.offset().checked_add(len as u64) {
+ match self.read.read(len)? {
+ EitherLifetime::Long(buf) => {
+ let s = Self::convert_str(buf, offset)?;
+ visitor.visit_borrowed_str(s)
+ }
+ EitherLifetime::Short(buf) => {
+ let s = Self::convert_str(buf, offset)?;
+ visitor.visit_str(s)
+ }
+ }
+ } else {
+ // An overflow would have occured.
+ Err(Error::syntax(
+ ErrorCode::LengthOutOfRange,
+ self.read.offset(),
+ ))
+ }
+ }
+
+ fn parse_indefinite_str<V>(&mut self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ self.read.clear_buffer();
+ loop {
+ let byte = self.parse_u8()?;
+ let len = match byte {
+ 0x60..=0x77 => byte as usize - 0x60,
+ 0x78 => self.parse_u8()? as usize,
+ 0x79 => self.parse_u16()? as usize,
+ 0x7a => self.parse_u32()? as usize,
+ 0x7b => {
+ let len = self.parse_u64()?;
+ if len > usize::max_value() as u64 {
+ return Err(self.error(ErrorCode::LengthOutOfRange));
+ }
+ len as usize
+ }
+ 0xff => break,
+ _ => return Err(self.error(ErrorCode::UnexpectedCode)),
+ };
+
+ self.read.read_to_buffer(len)?;
+ }
+
+ let offset = self.read.offset();
+ match self.read.take_buffer() {
+ EitherLifetime::Long(buf) => {
+ let s = Self::convert_str(buf, offset)?;
+ visitor.visit_borrowed_str(s)
+ }
+ EitherLifetime::Short(buf) => {
+ let s = Self::convert_str(buf, offset)?;
+ visitor.visit_str(s)
+ }
+ }
+ }
+
+ #[cfg(feature = "tags")]
+ fn handle_tagged_value<V>(&mut self, tag: u64, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ self.recursion_checked(|d| {
+ set_tag(Some(tag));
+ let r = visitor.visit_newtype_struct(d);
+ set_tag(None);
+ r
+ })
+ }
+
+ #[cfg(not(feature = "tags"))]
+ fn handle_tagged_value<V>(&mut self, _tag: u64, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ self.recursion_checked(|de| de.parse_value(visitor))
+ }
+
+ fn recursion_checked<F, T>(&mut self, f: F) -> Result<T>
+ where
+ F: FnOnce(&mut Deserializer<R>) -> Result<T>,
+ {
+ self.remaining_depth -= 1;
+ if self.remaining_depth == 0 {
+ return Err(self.error(ErrorCode::RecursionLimitExceeded));
+ }
+ let r = f(self);
+ self.remaining_depth += 1;
+ r
+ }
+
+ fn parse_array<V>(&mut self, mut len: usize, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ self.recursion_checked(|de| {
+ let value = visitor.visit_seq(SeqAccess { de, len: &mut len })?;
+
+ if len != 0 {
+ Err(de.error(ErrorCode::TrailingData))
+ } else {
+ Ok(value)
+ }
+ })
+ }
+
+ fn parse_indefinite_array<V>(&mut self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ self.recursion_checked(|de| {
+ let value = visitor.visit_seq(IndefiniteSeqAccess { de })?;
+ match de.next()? {
+ Some(0xff) => Ok(value),
+ Some(_) => Err(de.error(ErrorCode::TrailingData)),
+ None => Err(de.error(ErrorCode::EofWhileParsingArray)),
+ }
+ })
+ }
+
+ fn parse_map<V>(&mut self, mut len: usize, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ let accept_packed = self.accept_packed;
+ let accept_named = self.accept_named;
+ self.recursion_checked(|de| {
+ let value = visitor.visit_map(MapAccess {
+ de,
+ len: &mut len,
+ accept_named,
+ accept_packed,
+ })?;
+
+ if len != 0 {
+ Err(de.error(ErrorCode::TrailingData))
+ } else {
+ Ok(value)
+ }
+ })
+ }
+
+ fn parse_indefinite_map<V>(&mut self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ let accept_named = self.accept_named;
+ let accept_packed = self.accept_packed;
+ self.recursion_checked(|de| {
+ let value = visitor.visit_map(IndefiniteMapAccess {
+ de,
+ accept_packed,
+ accept_named,
+ })?;
+ match de.next()? {
+ Some(0xff) => Ok(value),
+ Some(_) => Err(de.error(ErrorCode::TrailingData)),
+ None => Err(de.error(ErrorCode::EofWhileParsingMap)),
+ }
+ })
+ }
+
+ fn parse_enum<V>(&mut self, mut len: usize, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ self.recursion_checked(|de| {
+ let value = visitor.visit_enum(VariantAccess {
+ seq: SeqAccess { de, len: &mut len },
+ })?;
+
+ if len != 0 {
+ Err(de.error(ErrorCode::TrailingData))
+ } else {
+ Ok(value)
+ }
+ })
+ }
+
+ fn parse_enum_map<V>(&mut self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ let accept_named = self.accept_named;
+ let accept_packed = self.accept_packed;
+ self.recursion_checked(|de| {
+ let mut len = 1;
+ let value = visitor.visit_enum(VariantAccessMap {
+ map: MapAccess {
+ de,
+ len: &mut len,
+ accept_packed,
+ accept_named,
+ },
+ })?;
+
+ if len != 0 {
+ Err(de.error(ErrorCode::TrailingData))
+ } else {
+ Ok(value)
+ }
+ })
+ }
+
+ fn parse_indefinite_enum<V>(&mut self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ self.recursion_checked(|de| {
+ let value = visitor.visit_enum(VariantAccess {
+ seq: IndefiniteSeqAccess { de },
+ })?;
+ match de.next()? {
+ Some(0xff) => Ok(value),
+ Some(_) => Err(de.error(ErrorCode::TrailingData)),
+ None => Err(de.error(ErrorCode::EofWhileParsingArray)),
+ }
+ })
+ }
+
+ fn parse_f16(&mut self) -> Result<f32> {
+ Ok(f32::from(f16::from_bits(self.parse_u16()?)))
+ }
+
+ fn parse_f32(&mut self) -> Result<f32> {
+ self.parse_u32().map(|i| f32::from_bits(i))
+ }
+
+ fn parse_f64(&mut self) -> Result<f64> {
+ self.parse_u64().map(|i| f64::from_bits(i))
+ }
+
+ // Don't warn about the `unreachable!` in case
+ // exhaustive integer pattern matching is enabled.
+ #[allow(unreachable_patterns)]
+ fn parse_value<V>(&mut self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ let byte = self.parse_u8()?;
+ match byte {
+ // Major type 0: an unsigned integer
+ 0x00..=0x17 => visitor.visit_u8(byte),
+ 0x18 => {
+ let value = self.parse_u8()?;
+ visitor.visit_u8(value)
+ }
+ 0x19 => {
+ let value = self.parse_u16()?;
+ visitor.visit_u16(value)
+ }
+ 0x1a => {
+ let value = self.parse_u32()?;
+ visitor.visit_u32(value)
+ }
+ 0x1b => {
+ let value = self.parse_u64()?;
+ visitor.visit_u64(value)
+ }
+ 0x1c..=0x1f => Err(self.error(ErrorCode::UnassignedCode)),
+
+ // Major type 1: a negative integer
+ 0x20..=0x37 => visitor.visit_i8(-1 - (byte - 0x20) as i8),
+ 0x38 => {
+ let value = self.parse_u8()?;
+ visitor.visit_i16(-1 - i16::from(value))
+ }
+ 0x39 => {
+ let value = self.parse_u16()?;
+ visitor.visit_i32(-1 - i32::from(value))
+ }
+ 0x3a => {
+ let value = self.parse_u32()?;
+ visitor.visit_i64(-1 - i64::from(value))
+ }
+ 0x3b => {
+ let value = self.parse_u64()?;
+ if value > i64::max_value() as u64 {
+ return visitor.visit_i128(-1 - i128::from(value));
+ }
+ visitor.visit_i64(-1 - value as i64)
+ }
+ 0x3c..=0x3f => Err(self.error(ErrorCode::UnassignedCode)),
+
+ // Major type 2: a byte string
+ 0x40..=0x57 => self.parse_bytes(byte as usize - 0x40, visitor),
+ 0x58 => {
+ let len = self.parse_u8()?;
+ self.parse_bytes(len as usize, visitor)
+ }
+ 0x59 => {
+ let len = self.parse_u16()?;
+ self.parse_bytes(len as usize, visitor)
+ }
+ 0x5a => {
+ let len = self.parse_u32()?;
+ self.parse_bytes(len as usize, visitor)
+ }
+ 0x5b => {
+ let len = self.parse_u64()?;
+ if len > usize::max_value() as u64 {
+ return Err(self.error(ErrorCode::LengthOutOfRange));
+ }
+ self.parse_bytes(len as usize, visitor)
+ }
+ 0x5c..=0x5e => Err(self.error(ErrorCode::UnassignedCode)),
+ 0x5f => self.parse_indefinite_bytes(visitor),
+
+ // Major type 3: a text string
+ 0x60..=0x77 => self.parse_str(byte as usize - 0x60, visitor),
+ 0x78 => {
+ let len = self.parse_u8()?;
+ self.parse_str(len as usize, visitor)
+ }
+ 0x79 => {
+ let len = self.parse_u16()?;
+ self.parse_str(len as usize, visitor)
+ }
+ 0x7a => {
+ let len = self.parse_u32()?;
+ self.parse_str(len as usize, visitor)
+ }
+ 0x7b => {
+ let len = self.parse_u64()?;
+ if len > usize::max_value() as u64 {
+ return Err(self.error(ErrorCode::LengthOutOfRange));
+ }
+ self.parse_str(len as usize, visitor)
+ }
+ 0x7c..=0x7e => Err(self.error(ErrorCode::UnassignedCode)),
+ 0x7f => self.parse_indefinite_str(visitor),
+
+ // Major type 4: an array of data items
+ 0x80..=0x97 => self.parse_array(byte as usize - 0x80, visitor),
+ 0x98 => {
+ let len = self.parse_u8()?;
+ self.parse_array(len as usize, visitor)
+ }
+ 0x99 => {
+ let len = self.parse_u16()?;
+ self.parse_array(len as usize, visitor)
+ }
+ 0x9a => {
+ let len = self.parse_u32()?;
+ self.parse_array(len as usize, visitor)
+ }
+ 0x9b => {
+ let len = self.parse_u64()?;
+ if len > usize::max_value() as u64 {
+ return Err(self.error(ErrorCode::LengthOutOfRange));
+ }
+ self.parse_array(len as usize, visitor)
+ }
+ 0x9c..=0x9e => Err(self.error(ErrorCode::UnassignedCode)),
+ 0x9f => self.parse_indefinite_array(visitor),
+
+ // Major type 5: a map of pairs of data items
+ 0xa0..=0xb7 => self.parse_map(byte as usize - 0xa0, visitor),
+ 0xb8 => {
+ let len = self.parse_u8()?;
+ self.parse_map(len as usize, visitor)
+ }
+ 0xb9 => {
+ let len = self.parse_u16()?;
+ self.parse_map(len as usize, visitor)
+ }
+ 0xba => {
+ let len = self.parse_u32()?;
+ self.parse_map(len as usize, visitor)
+ }
+ 0xbb => {
+ let len = self.parse_u64()?;
+ if len > usize::max_value() as u64 {
+ return Err(self.error(ErrorCode::LengthOutOfRange));
+ }
+ self.parse_map(len as usize, visitor)
+ }
+ 0xbc..=0xbe => Err(self.error(ErrorCode::UnassignedCode)),
+ 0xbf => self.parse_indefinite_map(visitor),
+
+ // Major type 6: optional semantic tagging of other major types
+ 0xc0..=0xd7 => {
+ let tag = u64::from(byte) - 0xc0;
+ self.handle_tagged_value(tag, visitor)
+ }
+ 0xd8 => {
+ let tag = self.parse_u8()?;
+ self.handle_tagged_value(tag.into(), visitor)
+ }
+ 0xd9 => {
+ let tag = self.parse_u16()?;
+ self.handle_tagged_value(tag.into(), visitor)
+ }
+ 0xda => {
+ let tag = self.parse_u32()?;
+ self.handle_tagged_value(tag.into(), visitor)
+ }
+ 0xdb => {
+ let tag = self.parse_u64()?;
+ self.handle_tagged_value(tag, visitor)
+ }
+ 0xdc..=0xdf => Err(self.error(ErrorCode::UnassignedCode)),
+
+ // Major type 7: floating-point numbers and other simple data types that need no content
+ 0xe0..=0xf3 => Err(self.error(ErrorCode::UnassignedCode)),
+ 0xf4 => visitor.visit_bool(false),
+ 0xf5 => visitor.visit_bool(true),
+ 0xf6 => visitor.visit_unit(),
+ 0xf7 => visitor.visit_unit(),
+ 0xf8 => Err(self.error(ErrorCode::UnassignedCode)),
+ 0xf9 => {
+ let value = self.parse_f16()?;
+ visitor.visit_f32(value)
+ }
+ 0xfa => {
+ let value = self.parse_f32()?;
+ visitor.visit_f32(value)
+ }
+ 0xfb => {
+ let value = self.parse_f64()?;
+ visitor.visit_f64(value)
+ }
+ 0xfc..=0xfe => Err(self.error(ErrorCode::UnassignedCode)),
+ 0xff => Err(self.error(ErrorCode::UnexpectedCode)),
+
+ _ => unreachable!(),
+ }
+ }
+}
+
+impl<'de, 'a, R> de::Deserializer<'de> for &'a mut Deserializer<R>
+where
+ R: Read<'de>,
+{
+ type Error = Error;
+
+ #[inline]
+ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ self.parse_value(visitor)
+ }
+
+ #[inline]
+ fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ match self.peek()? {
+ Some(0xf6) => {
+ self.consume();
+ visitor.visit_none()
+ }
+ _ => visitor.visit_some(self),
+ }
+ }
+
+ #[inline]
+ fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ visitor.visit_newtype_struct(self)
+ }
+
+ // Unit variants are encoded as just the variant identifier.
+ // Tuple variants are encoded as an array of the variant identifier followed by the fields.
+ // Struct variants are encoded as an array of the variant identifier followed by the struct.
+ #[inline]
+ fn deserialize_enum<V>(
+ self,
+ _name: &str,
+ _variants: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ match self.peek()? {
+ Some(byte @ 0x80..=0x9f) => {
+ if !self.accept_legacy_enums {
+ return Err(self.error(ErrorCode::WrongEnumFormat));
+ }
+ self.consume();
+ match byte {
+ 0x80..=0x97 => self.parse_enum(byte as usize - 0x80, visitor),
+ 0x98 => {
+ let len = self.parse_u8()?;
+ self.parse_enum(len as usize, visitor)
+ }
+ 0x99 => {
+ let len = self.parse_u16()?;
+ self.parse_enum(len as usize, visitor)
+ }
+ 0x9a => {
+ let len = self.parse_u32()?;
+ self.parse_enum(len as usize, visitor)
+ }
+ 0x9b => {
+ let len = self.parse_u64()?;
+ if len > usize::max_value() as u64 {
+ return Err(self.error(ErrorCode::LengthOutOfRange));
+ }
+ self.parse_enum(len as usize, visitor)
+ }
+ 0x9c..=0x9e => Err(self.error(ErrorCode::UnassignedCode)),
+ 0x9f => self.parse_indefinite_enum(visitor),
+
+ _ => unreachable!(),
+ }
+ }
+ Some(0xa1) => {
+ if !self.accept_standard_enums {
+ return Err(self.error(ErrorCode::WrongEnumFormat));
+ }
+ self.consume();
+ self.parse_enum_map(visitor)
+ }
+ None => Err(self.error(ErrorCode::EofWhileParsingValue)),
+ _ => {
+ if !self.accept_standard_enums && !self.accept_legacy_enums {
+ return Err(self.error(ErrorCode::WrongEnumFormat));
+ }
+ visitor.visit_enum(UnitVariantAccess { de: self })
+ }
+ }
+ }
+
+ #[inline]
+ fn is_human_readable(&self) -> bool {
+ false
+ }
+
+ serde::forward_to_deserialize_any! {
+ bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string unit
+ unit_struct seq tuple tuple_struct map struct identifier ignored_any
+ bytes byte_buf
+ }
+}
+
+impl<R> Deserializer<R>
+where
+ R: Offset,
+{
+ /// Return the current offset in the reader
+ #[inline]
+ pub fn byte_offset(&self) -> usize {
+ self.read.byte_offset()
+ }
+}
+
+trait MakeError {
+ fn error(&self, code: ErrorCode) -> Error;
+}
+
+struct SeqAccess<'a, R> {
+ de: &'a mut Deserializer<R>,
+ len: &'a mut usize,
+}
+
+impl<'de, 'a, R> de::SeqAccess<'de> for SeqAccess<'a, R>
+where
+ R: Read<'de>,
+{
+ type Error = Error;
+
+ fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
+ where
+ T: de::DeserializeSeed<'de>,
+ {
+ if *self.len == 0 {
+ return Ok(None);
+ }
+ *self.len -= 1;
+
+ let value = seed.deserialize(&mut *self.de)?;
+ Ok(Some(value))
+ }
+
+ fn size_hint(&self) -> Option<usize> {
+ Some(*self.len)
+ }
+}
+
+impl<'de, 'a, R> MakeError for SeqAccess<'a, R>
+where
+ R: Read<'de>,
+{
+ fn error(&self, code: ErrorCode) -> Error {
+ self.de.error(code)
+ }
+}
+
+struct IndefiniteSeqAccess<'a, R> {
+ de: &'a mut Deserializer<R>,
+}
+
+impl<'de, 'a, R> de::SeqAccess<'de> for IndefiniteSeqAccess<'a, R>
+where
+ R: Read<'de>,
+{
+ type Error = Error;
+
+ fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
+ where
+ T: de::DeserializeSeed<'de>,
+ {
+ match self.de.peek()? {
+ Some(0xff) => return Ok(None),
+ Some(_) => {}
+ None => return Err(self.de.error(ErrorCode::EofWhileParsingArray)),
+ }
+
+ let value = seed.deserialize(&mut *self.de)?;
+ Ok(Some(value))
+ }
+}
+
+impl<'de, 'a, R> MakeError for IndefiniteSeqAccess<'a, R>
+where
+ R: Read<'de>,
+{
+ fn error(&self, code: ErrorCode) -> Error {
+ self.de.error(code)
+ }
+}
+
+struct MapAccess<'a, R> {
+ de: &'a mut Deserializer<R>,
+ len: &'a mut usize,
+ accept_named: bool,
+ accept_packed: bool,
+}
+
+impl<'de, 'a, R> de::MapAccess<'de> for MapAccess<'a, R>
+where
+ R: Read<'de>,
+{
+ type Error = Error;
+
+ fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
+ where
+ K: de::DeserializeSeed<'de>,
+ {
+ if *self.len == 0 {
+ return Ok(None);
+ }
+ *self.len -= 1;
+
+ match self.de.peek()? {
+ Some(_byte @ 0x00..=0x1b) if !self.accept_packed => {
+ return Err(self.de.error(ErrorCode::WrongStructFormat));
+ }
+ Some(_byte @ 0x60..=0x7f) if !self.accept_named => {
+ return Err(self.de.error(ErrorCode::WrongStructFormat));
+ }
+ _ => {}
+ };
+
+ let value = seed.deserialize(&mut *self.de)?;
+ Ok(Some(value))
+ }
+
+ fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
+ where
+ V: de::DeserializeSeed<'de>,
+ {
+ seed.deserialize(&mut *self.de)
+ }
+
+ fn size_hint(&self) -> Option<usize> {
+ Some(*self.len)
+ }
+}
+
+impl<'de, 'a, R> MakeError for MapAccess<'a, R>
+where
+ R: Read<'de>,
+{
+ fn error(&self, code: ErrorCode) -> Error {
+ self.de.error(code)
+ }
+}
+
+struct IndefiniteMapAccess<'a, R> {
+ de: &'a mut Deserializer<R>,
+ accept_packed: bool,
+ accept_named: bool,
+}
+
+impl<'de, 'a, R> de::MapAccess<'de> for IndefiniteMapAccess<'a, R>
+where
+ R: Read<'de>,
+{
+ type Error = Error;
+
+ fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
+ where
+ K: de::DeserializeSeed<'de>,
+ {
+ match self.de.peek()? {
+ Some(_byte @ 0x00..=0x1b) if !self.accept_packed => {
+ return Err(self.de.error(ErrorCode::WrongStructFormat))
+ }
+ Some(_byte @ 0x60..=0x7f) if !self.accept_named => {
+ return Err(self.de.error(ErrorCode::WrongStructFormat))
+ }
+ Some(0xff) => return Ok(None),
+ Some(_) => {}
+ None => return Err(self.de.error(ErrorCode::EofWhileParsingMap)),
+ }
+
+ let value = seed.deserialize(&mut *self.de)?;
+ Ok(Some(value))
+ }
+
+ fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
+ where
+ V: de::DeserializeSeed<'de>,
+ {
+ seed.deserialize(&mut *self.de)
+ }
+}
+
+struct UnitVariantAccess<'a, R> {
+ de: &'a mut Deserializer<R>,
+}
+
+impl<'de, 'a, R> de::EnumAccess<'de> for UnitVariantAccess<'a, R>
+where
+ R: Read<'de>,
+{
+ type Error = Error;
+ type Variant = UnitVariantAccess<'a, R>;
+
+ fn variant_seed<V>(self, seed: V) -> Result<(V::Value, UnitVariantAccess<'a, R>)>
+ where
+ V: de::DeserializeSeed<'de>,
+ {
+ let variant = seed.deserialize(&mut *self.de)?;
+ Ok((variant, self))
+ }
+}
+
+impl<'de, 'a, R> de::VariantAccess<'de> for UnitVariantAccess<'a, R>
+where
+ R: Read<'de>,
+{
+ type Error = Error;
+
+ fn unit_variant(self) -> Result<()> {
+ Ok(())
+ }
+
+ fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value>
+ where
+ T: de::DeserializeSeed<'de>,
+ {
+ Err(de::Error::invalid_type(
+ de::Unexpected::UnitVariant,
+ &"newtype variant",
+ ))
+ }
+
+ fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ Err(de::Error::invalid_type(
+ de::Unexpected::UnitVariant,
+ &"tuple variant",
+ ))
+ }
+
+ fn struct_variant<V>(self, _fields: &'static [&'static str], _visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ Err(de::Error::invalid_type(
+ de::Unexpected::UnitVariant,
+ &"struct variant",
+ ))
+ }
+}
+
+struct VariantAccess<T> {
+ seq: T,
+}
+
+impl<'de, T> de::EnumAccess<'de> for VariantAccess<T>
+where
+ T: de::SeqAccess<'de, Error = Error> + MakeError,
+{
+ type Error = Error;
+ type Variant = VariantAccess<T>;
+
+ fn variant_seed<V>(mut self, seed: V) -> Result<(V::Value, VariantAccess<T>)>
+ where
+ V: de::DeserializeSeed<'de>,
+ {
+ let variant = match self.seq.next_element_seed(seed) {
+ Ok(Some(variant)) => variant,
+ Ok(None) => return Err(self.seq.error(ErrorCode::ArrayTooShort)),
+ Err(e) => return Err(e),
+ };
+ Ok((variant, self))
+ }
+}
+
+impl<'de, T> de::VariantAccess<'de> for VariantAccess<T>
+where
+ T: de::SeqAccess<'de, Error = Error> + MakeError,
+{
+ type Error = Error;
+
+ fn unit_variant(mut self) -> Result<()> {
+ match self.seq.next_element() {
+ Ok(Some(())) => Ok(()),
+ Ok(None) => Err(self.seq.error(ErrorCode::ArrayTooLong)),
+ Err(e) => Err(e),
+ }
+ }
+
+ fn newtype_variant_seed<S>(mut self, seed: S) -> Result<S::Value>
+ where
+ S: de::DeserializeSeed<'de>,
+ {
+ match self.seq.next_element_seed(seed) {
+ Ok(Some(variant)) => Ok(variant),
+ Ok(None) => Err(self.seq.error(ErrorCode::ArrayTooShort)),
+ Err(e) => Err(e),
+ }
+ }
+
+ fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ visitor.visit_seq(self.seq)
+ }
+
+ fn struct_variant<V>(mut self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ let seed = StructVariantSeed { visitor };
+ match self.seq.next_element_seed(seed) {
+ Ok(Some(variant)) => Ok(variant),
+ Ok(None) => Err(self.seq.error(ErrorCode::ArrayTooShort)),
+ Err(e) => Err(e),
+ }
+ }
+}
+
+struct StructVariantSeed<V> {
+ visitor: V,
+}
+
+impl<'de, V> de::DeserializeSeed<'de> for StructVariantSeed<V>
+where
+ V: de::Visitor<'de>,
+{
+ type Value = V::Value;
+
+ fn deserialize<D>(self, de: D) -> result::Result<V::Value, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ {
+ de.deserialize_any(self.visitor)
+ }
+}
+
+/// Iterator that deserializes a stream into multiple CBOR values.
+///
+/// A stream deserializer can be created from any CBOR deserializer using the
+/// `Deserializer::into_iter` method.
+///
+/// ```
+/// # extern crate serde_cbor;
+/// use serde_cbor::de::Deserializer;
+/// use serde_cbor::value::Value;
+///
+/// # fn main() {
+/// let data: Vec<u8> = vec![
+/// 0x01, 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72,
+/// ];
+/// let mut it = Deserializer::from_slice(&data[..]).into_iter::<Value>();
+/// assert_eq!(
+/// Value::Integer(1),
+/// it.next().unwrap().unwrap()
+/// );
+/// assert_eq!(
+/// Value::Text("foobar".to_string()),
+/// it.next().unwrap().unwrap()
+/// );
+/// # }
+/// ```
+#[derive(Debug)]
+pub struct StreamDeserializer<'de, R, T> {
+ de: Deserializer<R>,
+ output: PhantomData<T>,
+ lifetime: PhantomData<&'de ()>,
+}
+
+impl<'de, R, T> StreamDeserializer<'de, R, T>
+where
+ R: Read<'de>,
+ T: de::Deserialize<'de>,
+{
+ /// Create a new CBOR stream deserializer from one of the possible
+ /// serde_cbor input sources.
+ ///
+ /// Typically it is more convenient to use one of these methods instead:
+ ///
+ /// * `Deserializer::from_slice(...).into_iter()`
+ /// * `Deserializer::from_reader(...).into_iter()`
+ pub fn new(read: R) -> StreamDeserializer<'de, R, T> {
+ StreamDeserializer {
+ de: Deserializer::new(read),
+ output: PhantomData,
+ lifetime: PhantomData,
+ }
+ }
+}
+
+impl<'de, R, T> StreamDeserializer<'de, R, T>
+where
+ R: Offset,
+ T: de::Deserialize<'de>,
+{
+ /// Return the current offset in the reader
+ #[inline]
+ pub fn byte_offset(&self) -> usize {
+ self.de.byte_offset()
+ }
+}
+
+impl<'de, R, T> Iterator for StreamDeserializer<'de, R, T>
+where
+ R: Read<'de>,
+ T: de::Deserialize<'de>,
+{
+ type Item = Result<T>;
+
+ fn next(&mut self) -> Option<Result<T>> {
+ match self.de.peek() {
+ Ok(Some(_)) => Some(T::deserialize(&mut self.de)),
+ Ok(None) => None,
+ Err(e) => Some(Err(e)),
+ }
+ }
+}
+
+struct VariantAccessMap<T> {
+ map: T,
+}
+
+impl<'de, T> de::EnumAccess<'de> for VariantAccessMap<T>
+where
+ T: de::MapAccess<'de, Error = Error> + MakeError,
+{
+ type Error = Error;
+ type Variant = VariantAccessMap<T>;
+
+ fn variant_seed<V>(mut self, seed: V) -> Result<(V::Value, VariantAccessMap<T>)>
+ where
+ V: de::DeserializeSeed<'de>,
+ {
+ let variant = match self.map.next_key_seed(seed) {
+ Ok(Some(variant)) => variant,
+ Ok(None) => return Err(self.map.error(ErrorCode::ArrayTooShort)),
+ Err(e) => return Err(e),
+ };
+ Ok((variant, self))
+ }
+}
+
+impl<'de, T> de::VariantAccess<'de> for VariantAccessMap<T>
+where
+ T: de::MapAccess<'de, Error = Error> + MakeError,
+{
+ type Error = Error;
+
+ fn unit_variant(mut self) -> Result<()> {
+ match self.map.next_value() {
+ Ok(()) => Ok(()),
+ Err(e) => Err(e),
+ }
+ }
+
+ fn newtype_variant_seed<S>(mut self, seed: S) -> Result<S::Value>
+ where
+ S: de::DeserializeSeed<'de>,
+ {
+ self.map.next_value_seed(seed)
+ }
+
+ fn tuple_variant<V>(mut self, _len: usize, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ let seed = StructVariantSeed { visitor };
+ self.map.next_value_seed(seed)
+ }
+
+ fn struct_variant<V>(mut self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ let seed = StructVariantSeed { visitor };
+ self.map.next_value_seed(seed)
+ }
+}
diff --git a/third_party/rust/serde_cbor/src/error.rs b/third_party/rust/serde_cbor/src/error.rs
new file mode 100644
index 0000000000..b1a6a459e5
--- /dev/null
+++ b/third_party/rust/serde_cbor/src/error.rs
@@ -0,0 +1,318 @@
+//! When serializing or deserializing CBOR goes wrong.
+use core::fmt;
+use core::result;
+use serde::de;
+use serde::ser;
+#[cfg(feature = "std")]
+use std::error;
+#[cfg(feature = "std")]
+use std::io;
+
+/// This type represents all possible errors that can occur when serializing or deserializing CBOR
+/// data.
+pub struct Error(ErrorImpl);
+
+/// Alias for a `Result` with the error type `serde_cbor::Error`.
+pub type Result<T> = result::Result<T, Error>;
+
+/// Categorizes the cause of a `serde_cbor::Error`.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum Category {
+ /// The error was caused by a failure to read or write bytes on an IO stream.
+ Io,
+ /// The error was caused by input that was not syntactically valid CBOR.
+ Syntax,
+ /// The error was caused by input data that was semantically incorrect.
+ Data,
+ /// The error was caused by prematurely reaching the end of the input data.
+ Eof,
+}
+
+impl Error {
+ /// The byte offset at which the error occurred.
+ pub fn offset(&self) -> u64 {
+ self.0.offset
+ }
+
+ pub(crate) fn syntax(code: ErrorCode, offset: u64) -> Error {
+ Error(ErrorImpl { code, offset })
+ }
+
+ #[cfg(feature = "std")]
+ pub(crate) fn io(error: io::Error) -> Error {
+ Error(ErrorImpl {
+ code: ErrorCode::Io(error),
+ offset: 0,
+ })
+ }
+
+ #[cfg(all(not(feature = "std"), feature = "unsealed_read_write"))]
+ /// Creates an error signalling that the underlying `Read` encountered an I/O error.
+ pub fn io() -> Error {
+ Error(ErrorImpl {
+ code: ErrorCode::Io,
+ offset: 0,
+ })
+ }
+
+ #[cfg(feature = "unsealed_read_write")]
+ /// Creates an error signalling that the scratch buffer was too small to fit the data.
+ pub fn scratch_too_small(offset: u64) -> Error {
+ Error(ErrorImpl {
+ code: ErrorCode::ScratchTooSmall,
+ offset,
+ })
+ }
+
+ #[cfg(not(feature = "unsealed_read_write"))]
+ pub(crate) fn scratch_too_small(offset: u64) -> Error {
+ Error(ErrorImpl {
+ code: ErrorCode::ScratchTooSmall,
+ offset,
+ })
+ }
+
+ #[cfg(feature = "unsealed_read_write")]
+ /// Creates an error with a custom message.
+ ///
+ /// **Note**: When the "std" feature is disabled, the message will be discarded.
+ pub fn message<T: fmt::Display>(_msg: T) -> Error {
+ #[cfg(not(feature = "std"))]
+ {
+ Error(ErrorImpl {
+ code: ErrorCode::Message,
+ offset: 0,
+ })
+ }
+ #[cfg(feature = "std")]
+ {
+ Error(ErrorImpl {
+ code: ErrorCode::Message(_msg.to_string()),
+ offset: 0,
+ })
+ }
+ }
+
+ #[cfg(not(feature = "unsealed_read_write"))]
+ pub(crate) fn message<T: fmt::Display>(_msg: T) -> Error {
+ #[cfg(not(feature = "std"))]
+ {
+ Error(ErrorImpl {
+ code: ErrorCode::Message,
+ offset: 0,
+ })
+ }
+ #[cfg(feature = "std")]
+ {
+ Error(ErrorImpl {
+ code: ErrorCode::Message(_msg.to_string()),
+ offset: 0,
+ })
+ }
+ }
+
+ #[cfg(feature = "unsealed_read_write")]
+ /// Creates an error signalling that the underlying read
+ /// encountered an end of input.
+ pub fn eof(offset: u64) -> Error {
+ Error(ErrorImpl {
+ code: ErrorCode::EofWhileParsingValue,
+ offset,
+ })
+ }
+
+ /// Categorizes the cause of this error.
+ pub fn classify(&self) -> Category {
+ match self.0.code {
+ #[cfg(feature = "std")]
+ ErrorCode::Message(_) => Category::Data,
+ #[cfg(not(feature = "std"))]
+ ErrorCode::Message => Category::Data,
+ #[cfg(feature = "std")]
+ ErrorCode::Io(_) => Category::Io,
+ #[cfg(not(feature = "std"))]
+ ErrorCode::Io => Category::Io,
+ ErrorCode::ScratchTooSmall => Category::Io,
+ ErrorCode::EofWhileParsingValue
+ | ErrorCode::EofWhileParsingArray
+ | ErrorCode::EofWhileParsingMap => Category::Eof,
+ ErrorCode::LengthOutOfRange
+ | ErrorCode::InvalidUtf8
+ | ErrorCode::UnassignedCode
+ | ErrorCode::UnexpectedCode
+ | ErrorCode::TrailingData
+ | ErrorCode::ArrayTooShort
+ | ErrorCode::ArrayTooLong
+ | ErrorCode::RecursionLimitExceeded
+ | ErrorCode::WrongEnumFormat
+ | ErrorCode::WrongStructFormat => Category::Syntax,
+ }
+ }
+
+ /// Returns true if this error was caused by a failure to read or write bytes on an IO stream.
+ pub fn is_io(&self) -> bool {
+ match self.classify() {
+ Category::Io => true,
+ _ => false,
+ }
+ }
+
+ /// Returns true if this error was caused by input that was not syntactically valid CBOR.
+ pub fn is_syntax(&self) -> bool {
+ match self.classify() {
+ Category::Syntax => true,
+ _ => false,
+ }
+ }
+
+ /// Returns true if this error was caused by data that was semantically incorrect.
+ pub fn is_data(&self) -> bool {
+ match self.classify() {
+ Category::Data => true,
+ _ => false,
+ }
+ }
+
+ /// Returns true if this error was caused by prematurely reaching the end of the input data.
+ pub fn is_eof(&self) -> bool {
+ match self.classify() {
+ Category::Eof => true,
+ _ => false,
+ }
+ }
+
+ /// Returns true if this error was caused by the scratch buffer being too small.
+ ///
+ /// Note this being `true` implies that `is_io()` is also `true`.
+ pub fn is_scratch_too_small(&self) -> bool {
+ match self.0.code {
+ ErrorCode::ScratchTooSmall => true,
+ _ => false,
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl error::Error for Error {
+ fn source(&self) -> Option<&(dyn error::Error + 'static)> {
+ match self.0.code {
+ ErrorCode::Io(ref err) => Some(err),
+ _ => None,
+ }
+ }
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if self.0.offset == 0 {
+ fmt::Display::fmt(&self.0.code, f)
+ } else {
+ write!(f, "{} at offset {}", self.0.code, self.0.offset)
+ }
+ }
+}
+
+impl fmt::Debug for Error {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Debug::fmt(&self.0, fmt)
+ }
+}
+
+impl de::Error for Error {
+ fn custom<T: fmt::Display>(msg: T) -> Error {
+ Error::message(msg)
+ }
+
+ fn invalid_type(unexp: de::Unexpected<'_>, exp: &dyn de::Expected) -> Error {
+ if let de::Unexpected::Unit = unexp {
+ Error::custom(format_args!("invalid type: null, expected {}", exp))
+ } else {
+ Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
+ }
+ }
+}
+
+impl ser::Error for Error {
+ fn custom<T: fmt::Display>(msg: T) -> Error {
+ Error::message(msg)
+ }
+}
+
+#[cfg(feature = "std")]
+impl From<io::Error> for Error {
+ fn from(e: io::Error) -> Error {
+ Error::io(e)
+ }
+}
+
+#[cfg(not(feature = "std"))]
+impl From<core::fmt::Error> for Error {
+ fn from(_: core::fmt::Error) -> Error {
+ Error(ErrorImpl {
+ code: ErrorCode::Message,
+ offset: 0,
+ })
+ }
+}
+
+#[derive(Debug)]
+struct ErrorImpl {
+ code: ErrorCode,
+ offset: u64,
+}
+
+#[derive(Debug)]
+pub(crate) enum ErrorCode {
+ #[cfg(feature = "std")]
+ Message(String),
+ #[cfg(not(feature = "std"))]
+ Message,
+ #[cfg(feature = "std")]
+ Io(io::Error),
+ #[allow(unused)]
+ #[cfg(not(feature = "std"))]
+ Io,
+ ScratchTooSmall,
+ EofWhileParsingValue,
+ EofWhileParsingArray,
+ EofWhileParsingMap,
+ LengthOutOfRange,
+ InvalidUtf8,
+ UnassignedCode,
+ UnexpectedCode,
+ TrailingData,
+ ArrayTooShort,
+ ArrayTooLong,
+ RecursionLimitExceeded,
+ WrongEnumFormat,
+ WrongStructFormat,
+}
+
+impl fmt::Display for ErrorCode {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ #[cfg(feature = "std")]
+ ErrorCode::Message(ref msg) => f.write_str(msg),
+ #[cfg(not(feature = "std"))]
+ ErrorCode::Message => f.write_str("Unknown error"),
+ #[cfg(feature = "std")]
+ ErrorCode::Io(ref err) => fmt::Display::fmt(err, f),
+ #[cfg(not(feature = "std"))]
+ ErrorCode::Io => f.write_str("Unknown I/O error"),
+ ErrorCode::ScratchTooSmall => f.write_str("Scratch buffer too small"),
+ ErrorCode::EofWhileParsingValue => f.write_str("EOF while parsing a value"),
+ ErrorCode::EofWhileParsingArray => f.write_str("EOF while parsing an array"),
+ ErrorCode::EofWhileParsingMap => f.write_str("EOF while parsing a map"),
+ ErrorCode::LengthOutOfRange => f.write_str("length out of range"),
+ ErrorCode::InvalidUtf8 => f.write_str("invalid UTF-8"),
+ ErrorCode::UnassignedCode => f.write_str("unassigned type"),
+ ErrorCode::UnexpectedCode => f.write_str("unexpected code"),
+ ErrorCode::TrailingData => f.write_str("trailing data"),
+ ErrorCode::ArrayTooShort => f.write_str("array too short"),
+ ErrorCode::ArrayTooLong => f.write_str("array too long"),
+ ErrorCode::RecursionLimitExceeded => f.write_str("recursion limit exceeded"),
+ ErrorCode::WrongEnumFormat => f.write_str("wrong enum format"),
+ ErrorCode::WrongStructFormat => f.write_str("wrong struct format"),
+ }
+ }
+}
diff --git a/third_party/rust/serde_cbor/src/lib.rs b/third_party/rust/serde_cbor/src/lib.rs
new file mode 100644
index 0000000000..5566854153
--- /dev/null
+++ b/third_party/rust/serde_cbor/src/lib.rs
@@ -0,0 +1,369 @@
+//! CBOR and serialization.
+//!
+//! # Usage
+//!
+//! Serde CBOR supports Rust 1.40 and up. Add this to your `Cargo.toml`:
+//! ```toml
+//! [dependencies]
+//! serde_cbor = "0.10"
+//! ```
+//!
+//! Storing and loading Rust types is easy and requires only
+//! minimal modifications to the program code.
+//!
+//! ```rust
+//! use serde_derive::{Deserialize, Serialize};
+//! use std::error::Error;
+//! use std::fs::File;
+//!
+//! // Types annotated with `Serialize` can be stored as CBOR.
+//! // To be able to load them again add `Deserialize`.
+//! #[derive(Debug, Serialize, Deserialize)]
+//! struct Mascot {
+//! name: String,
+//! species: String,
+//! year_of_birth: u32,
+//! }
+//!
+//! fn main() -> Result<(), Box<dyn Error>> {
+//! let ferris = Mascot {
+//! name: "Ferris".to_owned(),
+//! species: "crab".to_owned(),
+//! year_of_birth: 2015,
+//! };
+//!
+//! let ferris_file = File::create("examples/ferris.cbor")?;
+//! // Write Ferris to the given file.
+//! // Instead of a file you can use any type that implements `io::Write`
+//! // like a HTTP body, database connection etc.
+//! serde_cbor::to_writer(ferris_file, &ferris)?;
+//!
+//! let tux_file = File::open("examples/tux.cbor")?;
+//! // Load Tux from a file.
+//! // Serde CBOR performs roundtrip serialization meaning that
+//! // the data will not change in any way.
+//! let tux: Mascot = serde_cbor::from_reader(tux_file)?;
+//!
+//! println!("{:?}", tux);
+//! // prints: Mascot { name: "Tux", species: "penguin", year_of_birth: 1996 }
+//!
+//! Ok(())
+//! }
+//! ```
+//!
+//! There are a lot of options available to customize the format.
+//! To operate on untyped CBOR values have a look at the `Value` type.
+//!
+//! # Type-based Serialization and Deserialization
+//! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
+//! from CBOR 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 an annotation to automatically generate the
+//! code for these traits: `#[derive(Serialize, Deserialize)]`.
+//!
+//! The CBOR API also provides an enum `serde_cbor::Value`.
+//!
+//! # Packed Encoding
+//! When serializing structs or enums in CBOR the keys or enum variant names will be serialized
+//! as string keys to a map. Especially in embedded environments this can increase the file
+//! size too much. In packed encoding all struct keys, as well as any enum variant that has no data,
+//! will be serialized as variable sized integers. The first 24 entries in any struct consume only a
+//! single byte! Packed encoding uses serde's preferred [externally tagged enum
+//! format](https://serde.rs/enum-representations.html) and therefore serializes enum variant names
+//! as string keys when that variant contains data. So, in the packed encoding example, `FirstVariant`
+//! encodes to a single byte, but encoding `SecondVariant` requires 16 bytes.
+//!
+//! To serialize a document in this format use `Serializer::new(writer).packed_format()` or
+//! the shorthand `ser::to_vec_packed`. The deserialization works without any changes.
+//!
+//! If you would like to omit the enum variant encoding for all variants, including ones that
+//! contain data, you can add `legacy_enums()` in addition to `packed_format()`, as can seen
+//! in the Serialize using minimal encoding example.
+//!
+//! # Self describing documents
+//! In some contexts different formats are used but there is no way to declare the format used
+//! out of band. For this reason CBOR has a magic number that may be added before any document.
+//! Self describing documents are created with `serializer.self_describe()`.
+//!
+//! # Examples
+//! Read a CBOR value that is known to be a map of string keys to string values and print it.
+//!
+//! ```rust
+//! use std::collections::BTreeMap;
+//! use serde_cbor::from_slice;
+//!
+//! let slice = b"\xa5aaaAabaBacaCadaDaeaE";
+//! let value: BTreeMap<String, String> = from_slice(slice).unwrap();
+//! println!("{:?}", value); // {"e": "E", "d": "D", "a": "A", "c": "C", "b": "B"}
+//! ```
+//!
+//! Read a general CBOR value with an unknown content.
+//!
+//! ```rust
+//! use serde_cbor::from_slice;
+//! use serde_cbor::value::Value;
+//!
+//! let slice = b"\x82\x01\xa1aaab";
+//! let value: Value = from_slice(slice).unwrap();
+//! println!("{:?}", value); // Array([U64(1), Object({String("a"): String("b")})])
+//! ```
+//!
+//! Serialize an object.
+//!
+//! ```rust
+//! use std::collections::BTreeMap;
+//! use serde_cbor::to_vec;
+//!
+//! let mut programming_languages = BTreeMap::new();
+//! programming_languages.insert("rust", vec!["safe", "concurrent", "fast"]);
+//! programming_languages.insert("python", vec!["powerful", "friendly", "open"]);
+//! programming_languages.insert("js", vec!["lightweight", "interpreted", "object-oriented"]);
+//! let encoded = to_vec(&programming_languages);
+//! assert_eq!(encoded.unwrap().len(), 103);
+//! ```
+//!
+//! Deserializing data in the middle of a slice
+//! ```
+//! # extern crate serde_cbor;
+//! use serde_cbor::Deserializer;
+//!
+//! # fn main() {
+//! let data: Vec<u8> = vec![
+//! 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x66, 0x66, 0x6f, 0x6f, 0x62,
+//! 0x61, 0x72,
+//! ];
+//! let mut deserializer = Deserializer::from_slice(&data);
+//! let value: &str = serde::de::Deserialize::deserialize(&mut deserializer)
+//! .unwrap();
+//! let rest = &data[deserializer.byte_offset()..];
+//! assert_eq!(value, "foobar");
+//! assert_eq!(rest, &[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]);
+//! # }
+//! ```
+//!
+//! Serialize using packed encoding
+//!
+//! ```rust
+//! use serde_derive::{Deserialize, Serialize};
+//! use serde_cbor::ser::to_vec_packed;
+//! use WithTwoVariants::*;
+//!
+//! #[derive(Debug, Serialize, Deserialize)]
+//! enum WithTwoVariants {
+//! FirstVariant,
+//! SecondVariant(u8),
+//! }
+//!
+//! let cbor = to_vec_packed(&FirstVariant).unwrap();
+//! assert_eq!(cbor.len(), 1);
+//!
+//! let cbor = to_vec_packed(&SecondVariant(0)).unwrap();
+//! assert_eq!(cbor.len(), 16); // Includes 13 bytes of "SecondVariant"
+//! ```
+//!
+//! Serialize using minimal encoding
+//!
+//! ```rust
+//! use serde_derive::{Deserialize, Serialize};
+//! use serde_cbor::{Result, Serializer, ser::{self, IoWrite}};
+//! use WithTwoVariants::*;
+//!
+//! fn to_vec_minimal<T>(value: &T) -> Result<Vec<u8>>
+//! where
+//! T: serde::Serialize,
+//! {
+//! let mut vec = Vec::new();
+//! value.serialize(&mut Serializer::new(&mut IoWrite::new(&mut vec)).packed_format().legacy_enums())?;
+//! Ok(vec)
+//! }
+//!
+//! #[derive(Debug, Serialize, Deserialize)]
+//! enum WithTwoVariants {
+//! FirstVariant,
+//! SecondVariant(u8),
+//! }
+//!
+//! let cbor = to_vec_minimal(&FirstVariant).unwrap();
+//! assert_eq!(cbor.len(), 1);
+//!
+//! let cbor = to_vec_minimal(&SecondVariant(0)).unwrap();
+//! assert_eq!(cbor.len(), 3);
+//! ```
+//!
+//! # `no-std` support
+//!
+//! Serde CBOR supports building in a `no_std` context, use the following lines
+//! in your `Cargo.toml` dependencies:
+//! ``` toml
+//! [dependencies]
+//! serde = { version = "1.0", default-features = false }
+//! serde_cbor = { version = "0.10", default-features = false }
+//! ```
+//!
+//! Without the `std` feature the functions [from_reader], [from_slice], [to_vec], and [to_writer]
+//! are not exported. To export [from_slice] and [to_vec] enable the `alloc` feature. The `alloc`
+//! feature uses the [`alloc` library][alloc-lib] and requires at least version 1.36.0 of Rust.
+//!
+//! [alloc-lib]: https://doc.rust-lang.org/alloc/
+//!
+//! *Note*: to use derive macros in serde you will need to declare `serde`
+//! dependency like so:
+//! ``` toml
+//! serde = { version = "1.0", default-features = false, features = ["derive"] }
+//! ```
+//!
+//! Serialize an object with `no_std` and without `alloc`.
+//! ``` rust
+//! # #[macro_use] extern crate serde_derive;
+//! # fn main() -> Result<(), serde_cbor::Error> {
+//! use serde::Serialize;
+//! use serde_cbor::Serializer;
+//! use serde_cbor::ser::SliceWrite;
+//!
+//! #[derive(Serialize)]
+//! struct User {
+//! user_id: u32,
+//! password_hash: [u8; 4],
+//! }
+//!
+//! let mut buf = [0u8; 100];
+//! let writer = SliceWrite::new(&mut buf[..]);
+//! let mut ser = Serializer::new(writer);
+//! let user = User {
+//! user_id: 42,
+//! password_hash: [1, 2, 3, 4],
+//! };
+//! user.serialize(&mut ser)?;
+//! let writer = ser.into_inner();
+//! let size = writer.bytes_written();
+//! let expected = [
+//! 0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d,
+//! 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73,
+//! 0x68, 0x84, 0x1, 0x2, 0x3, 0x4
+//! ];
+//! assert_eq!(&buf[..size], expected);
+//! # Ok(())
+//! # }
+//! ```
+//!
+//! Deserialize an object.
+//! ``` rust
+//! # #[macro_use] extern crate serde_derive;
+//! # fn main() -> Result<(), serde_cbor::Error> {
+//! #[derive(Debug, PartialEq, Deserialize)]
+//! struct User {
+//! user_id: u32,
+//! password_hash: [u8; 4],
+//! }
+//!
+//! let value = [
+//! 0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d,
+//! 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73,
+//! 0x68, 0x84, 0x1, 0x2, 0x3, 0x4
+//! ];
+//!
+//! // from_slice_with_scratch will not alter input data, use it whenever you
+//! // borrow from somewhere else.
+//! // You will have to size your scratch according to the input data you
+//! // expect.
+//! use serde_cbor::de::from_slice_with_scratch;
+//! let mut scratch = [0u8; 32];
+//! let user: User = from_slice_with_scratch(&value[..], &mut scratch)?;
+//! assert_eq!(user, User {
+//! user_id: 42,
+//! password_hash: [1, 2, 3, 4],
+//! });
+//!
+//! let mut value = [
+//! 0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d,
+//! 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73,
+//! 0x68, 0x84, 0x1, 0x2, 0x3, 0x4
+//! ];
+//!
+//! // from_mut_slice will move data around the input slice, you may only use it
+//! // on data you may own or can modify.
+//! use serde_cbor::de::from_mut_slice;
+//! let user: User = from_mut_slice(&mut value[..])?;
+//! assert_eq!(user, User {
+//! user_id: 42,
+//! password_hash: [1, 2, 3, 4],
+//! });
+//! # Ok(())
+//! # }
+//! ```
+//!
+//! # Limitations
+//!
+//! While Serde CBOR strives to support all features of Serde and CBOR
+//! there are a few limitations.
+//!
+//! * [Tags] are ignored during deserialization and can't be emitted during
+//! serialization. This is because Serde has no concept of tagged
+//! values. See:&nbsp;[#3]
+//! * Unknown [simple values] cause an `UnassignedCode` error.
+//! The simple values *False* and *True* are recognized and parsed as bool.
+//! *Null* and *Undefined* are both deserialized as *unit*.
+//! The *unit* type is serialized as *Null*. See:&nbsp;[#86]
+//! * [128-bit integers] can't be directly encoded in CBOR. If you need them
+//! store them as a byte string. See:&nbsp;[#77]
+//!
+//! [Tags]: https://tools.ietf.org/html/rfc7049#section-2.4.4
+//! [#3]: https://github.com/pyfisch/cbor/issues/3
+//! [simple values]: https://tools.ietf.org/html/rfc7049#section-3.5
+//! [#86]: https://github.com/pyfisch/cbor/issues/86
+//! [128-bit integers]: https://doc.rust-lang.org/std/primitive.u128.html
+//! [#77]: https://github.com/pyfisch/cbor/issues/77
+
+#![deny(missing_docs)]
+#![cfg_attr(not(feature = "std"), no_std)]
+
+// When we are running tests in no_std mode we need to explicitly link std, because `cargo test`
+// will not work without it.
+#[cfg(all(not(feature = "std"), test))]
+extern crate std;
+
+#[cfg(feature = "alloc")]
+extern crate alloc;
+
+pub mod de;
+pub mod error;
+mod read;
+pub mod ser;
+pub mod tags;
+mod write;
+
+#[cfg(feature = "std")]
+pub mod value;
+
+// Re-export the [items recommended by serde](https://serde.rs/conventions.html).
+#[doc(inline)]
+pub use crate::de::{Deserializer, StreamDeserializer};
+
+#[doc(inline)]
+pub use crate::error::{Error, Result};
+
+#[doc(inline)]
+pub use crate::ser::Serializer;
+
+// Convenience functions for serialization and deserialization.
+// These functions are only available in `std` mode.
+#[cfg(feature = "std")]
+#[doc(inline)]
+pub use crate::de::from_reader;
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+#[doc(inline)]
+pub use crate::de::from_slice;
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+#[doc(inline)]
+pub use crate::ser::to_vec;
+
+#[cfg(feature = "std")]
+#[doc(inline)]
+pub use crate::ser::to_writer;
+
+// Re-export the value type like serde_json
+#[cfg(feature = "std")]
+#[doc(inline)]
+pub use crate::value::Value;
diff --git a/third_party/rust/serde_cbor/src/read.rs b/third_party/rust/serde_cbor/src/read.rs
new file mode 100644
index 0000000000..1b53018df8
--- /dev/null
+++ b/third_party/rust/serde_cbor/src/read.rs
@@ -0,0 +1,637 @@
+#[cfg(feature = "alloc")]
+use alloc::{vec, vec::Vec};
+#[cfg(feature = "std")]
+use core::cmp;
+use core::mem;
+
+#[cfg(feature = "std")]
+use std::io::{self, Read as StdRead};
+
+use crate::error::{Error, ErrorCode, Result};
+
+#[cfg(not(feature = "unsealed_read_write"))]
+/// Trait used by the deserializer for iterating over input.
+///
+/// This trait is sealed by default, enabling the `unsealed_read_write` feature removes this bound
+/// to allow objects outside of this crate to implement this trait.
+pub trait Read<'de>: private::Sealed {
+ #[doc(hidden)]
+ /// Read n bytes from the input.
+ ///
+ /// Implementations that can are asked to return a slice with a Long lifetime that outlives the
+ /// decoder, but others (eg. ones that need to allocate the data into a temporary buffer) can
+ /// return it with a Short lifetime that just lives for the time of read's mutable borrow of
+ /// the reader.
+ ///
+ /// This may, as a side effect, clear the reader's scratch buffer (as the provided
+ /// implementation does).
+
+ // A more appropriate lifetime setup for this (that would allow the Deserializer::convert_str
+ // to stay a function) would be something like `fn read<'a, 'r: 'a>(&'a mut 'r immut self, ...) -> ...
+ // EitherLifetime<'r, 'de>>`, which borrows self mutably for the duration of the function and
+ // downgrates that reference to an immutable one that outlives the result (protecting the
+ // scratch buffer from changes), but alas, that can't be expressed (yet?).
+ fn read<'a>(&'a mut self, n: usize) -> Result<EitherLifetime<'a, 'de>> {
+ self.clear_buffer();
+ self.read_to_buffer(n)?;
+
+ Ok(self.take_buffer())
+ }
+
+ #[doc(hidden)]
+ fn next(&mut self) -> Result<Option<u8>>;
+
+ #[doc(hidden)]
+ fn peek(&mut self) -> Result<Option<u8>>;
+
+ #[doc(hidden)]
+ fn clear_buffer(&mut self);
+
+ #[doc(hidden)]
+ fn read_to_buffer(&mut self, n: usize) -> Result<()>;
+
+ #[doc(hidden)]
+ fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de>;
+
+ #[doc(hidden)]
+ fn read_into(&mut self, buf: &mut [u8]) -> Result<()>;
+
+ #[doc(hidden)]
+ fn discard(&mut self);
+
+ #[doc(hidden)]
+ fn offset(&self) -> u64;
+}
+
+#[cfg(feature = "unsealed_read_write")]
+/// Trait used by the deserializer for iterating over input.
+pub trait Read<'de> {
+ /// Read n bytes from the input.
+ ///
+ /// Implementations that can are asked to return a slice with a Long lifetime that outlives the
+ /// decoder, but others (eg. ones that need to allocate the data into a temporary buffer) can
+ /// return it with a Short lifetime that just lives for the time of read's mutable borrow of
+ /// the reader.
+ ///
+ /// This may, as a side effect, clear the reader's scratch buffer (as the provided
+ /// implementation does).
+
+ // A more appropriate lifetime setup for this (that would allow the Deserializer::convert_str
+ // to stay a function) would be something like `fn read<'a, 'r: 'a>(&'a mut 'r immut self, ...) -> ...
+ // EitherLifetime<'r, 'de>>`, which borrows self mutably for the duration of the function and
+ // downgrates that reference to an immutable one that outlives the result (protecting the
+ // scratch buffer from changes), but alas, that can't be expressed (yet?).
+ fn read<'a>(&'a mut self, n: usize) -> Result<EitherLifetime<'a, 'de>> {
+ self.clear_buffer();
+ self.read_to_buffer(n)?;
+
+ Ok(self.take_buffer())
+ }
+
+ /// Read the next byte from the input, if any.
+ fn next(&mut self) -> Result<Option<u8>>;
+
+ /// Peek at the next byte of the input, if any. This does not advance the reader, so the result
+ /// of this function will remain the same until a read or clear occurs.
+ fn peek(&mut self) -> Result<Option<u8>>;
+
+ /// Clear the underlying scratch buffer
+ fn clear_buffer(&mut self);
+
+ /// Append n bytes from the reader to the reader's scratch buffer (without clearing it)
+ fn read_to_buffer(&mut self, n: usize) -> Result<()>;
+
+ /// Read out everything accumulated in the reader's scratch buffer. This may, as a side effect,
+ /// clear it.
+ fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de>;
+
+ /// Read from the input until `buf` is full or end of input is encountered.
+ fn read_into(&mut self, buf: &mut [u8]) -> Result<()>;
+
+ /// Discard any data read by `peek`.
+ fn discard(&mut self);
+
+ /// Returns the offset from the start of the reader.
+ fn offset(&self) -> u64;
+}
+
+/// Represents a reader that can return its current position
+pub trait Offset {
+ fn byte_offset(&self) -> usize;
+}
+
+/// Represents a buffer with one of two lifetimes.
+pub enum EitherLifetime<'short, 'long> {
+ /// The short lifetime
+ Short(&'short [u8]),
+ /// The long lifetime
+ Long(&'long [u8]),
+}
+
+#[cfg(not(feature = "unsealed_read_write"))]
+mod private {
+ pub trait Sealed {}
+}
+
+/// CBOR input source that reads from a std::io input stream.
+#[cfg(feature = "std")]
+#[derive(Debug)]
+pub struct IoRead<R>
+where
+ R: io::Read,
+{
+ reader: OffsetReader<R>,
+ scratch: Vec<u8>,
+ ch: Option<u8>,
+}
+
+#[cfg(feature = "std")]
+impl<R> IoRead<R>
+where
+ R: io::Read,
+{
+ /// Creates a new CBOR input source to read from a std::io input stream.
+ pub fn new(reader: R) -> IoRead<R> {
+ IoRead {
+ reader: OffsetReader { reader, offset: 0 },
+ scratch: vec![],
+ ch: None,
+ }
+ }
+
+ #[inline]
+ fn next_inner(&mut self) -> Result<Option<u8>> {
+ let mut buf = [0; 1];
+ loop {
+ match self.reader.read(&mut buf) {
+ Ok(0) => return Ok(None),
+ Ok(_) => return Ok(Some(buf[0])),
+ Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
+ Err(e) => return Err(Error::io(e)),
+ }
+ }
+ }
+}
+
+#[cfg(all(feature = "std", not(feature = "unsealed_read_write")))]
+impl<R> private::Sealed for IoRead<R> where R: io::Read {}
+
+#[cfg(feature = "std")]
+impl<'de, R> Read<'de> for IoRead<R>
+where
+ R: io::Read,
+{
+ #[inline]
+ fn next(&mut self) -> Result<Option<u8>> {
+ match self.ch.take() {
+ Some(ch) => Ok(Some(ch)),
+ None => self.next_inner(),
+ }
+ }
+
+ #[inline]
+ fn peek(&mut self) -> Result<Option<u8>> {
+ match self.ch {
+ Some(ch) => Ok(Some(ch)),
+ None => {
+ self.ch = self.next_inner()?;
+ Ok(self.ch)
+ }
+ }
+ }
+
+ fn read_to_buffer(&mut self, mut n: usize) -> Result<()> {
+ // defend against malicious input pretending to be huge strings by limiting growth
+ self.scratch.reserve(cmp::min(n, 16 * 1024));
+
+ if n == 0 {
+ return Ok(());
+ }
+
+ if let Some(ch) = self.ch.take() {
+ self.scratch.push(ch);
+ n -= 1;
+ }
+
+ // n == 0 is OK here and needs no further special treatment
+
+ let transfer_result = {
+ // Prepare for take() (which consumes its reader) by creating a reference adaptor
+ // that'll only live in this block
+ let reference = self.reader.by_ref();
+ // Append the first n bytes of the reader to the scratch vector (or up to
+ // an error or EOF indicated by a shorter read)
+ let mut taken = reference.take(n as u64);
+ taken.read_to_end(&mut self.scratch)
+ };
+
+ match transfer_result {
+ Ok(r) if r == n => Ok(()),
+ Ok(_) => Err(Error::syntax(
+ ErrorCode::EofWhileParsingValue,
+ self.offset(),
+ )),
+ Err(e) => Err(Error::io(e)),
+ }
+ }
+
+ fn clear_buffer(&mut self) {
+ self.scratch.clear();
+ }
+
+ fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de> {
+ EitherLifetime::Short(&self.scratch)
+ }
+
+ fn read_into(&mut self, buf: &mut [u8]) -> Result<()> {
+ self.reader.read_exact(buf).map_err(|e| {
+ if e.kind() == io::ErrorKind::UnexpectedEof {
+ Error::syntax(ErrorCode::EofWhileParsingValue, self.offset())
+ } else {
+ Error::io(e)
+ }
+ })
+ }
+
+ #[inline]
+ fn discard(&mut self) {
+ self.ch = None;
+ }
+
+ fn offset(&self) -> u64 {
+ self.reader.offset
+ }
+}
+
+#[cfg(feature = "std")]
+impl<R> Offset for IoRead<R>
+where
+ R: std::io::Read,
+{
+ fn byte_offset(&self) -> usize {
+ self.offset() as usize
+ }
+}
+
+#[cfg(feature = "std")]
+#[derive(Debug)]
+struct OffsetReader<R> {
+ reader: R,
+ offset: u64,
+}
+
+#[cfg(feature = "std")]
+impl<R> io::Read for OffsetReader<R>
+where
+ R: io::Read,
+{
+ #[inline]
+ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+ let r = self.reader.read(buf);
+ if let Ok(count) = r {
+ self.offset += count as u64;
+ }
+ r
+ }
+}
+
+/// A CBOR input source that reads from a slice of bytes.
+#[cfg(any(feature = "std", feature = "alloc"))]
+#[derive(Debug)]
+pub struct SliceRead<'a> {
+ slice: &'a [u8],
+ scratch: Vec<u8>,
+ index: usize,
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a> SliceRead<'a> {
+ /// Creates a CBOR input source to read from a slice of bytes.
+ pub fn new(slice: &'a [u8]) -> SliceRead<'a> {
+ SliceRead {
+ slice,
+ scratch: vec![],
+ index: 0,
+ }
+ }
+
+ fn end(&self, n: usize) -> Result<usize> {
+ match self.index.checked_add(n) {
+ Some(end) if end <= self.slice.len() => Ok(end),
+ _ => Err(Error::syntax(
+ ErrorCode::EofWhileParsingValue,
+ self.slice.len() as u64,
+ )),
+ }
+ }
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a> Offset for SliceRead<'a> {
+ #[inline]
+ fn byte_offset(&self) -> usize {
+ self.index
+ }
+}
+
+#[cfg(all(
+ any(feature = "std", feature = "alloc"),
+ not(feature = "unsealed_read_write")
+))]
+impl<'a> private::Sealed for SliceRead<'a> {}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a> Read<'a> for SliceRead<'a> {
+ #[inline]
+ fn next(&mut self) -> Result<Option<u8>> {
+ Ok(if self.index < self.slice.len() {
+ let ch = self.slice[self.index];
+ self.index += 1;
+ Some(ch)
+ } else {
+ None
+ })
+ }
+
+ #[inline]
+ fn peek(&mut self) -> Result<Option<u8>> {
+ Ok(if self.index < self.slice.len() {
+ Some(self.slice[self.index])
+ } else {
+ None
+ })
+ }
+
+ fn clear_buffer(&mut self) {
+ self.scratch.clear();
+ }
+
+ fn read_to_buffer(&mut self, n: usize) -> Result<()> {
+ let end = self.end(n)?;
+ let slice = &self.slice[self.index..end];
+ self.scratch.extend_from_slice(slice);
+ self.index = end;
+
+ Ok(())
+ }
+
+ #[inline]
+ fn read<'b>(&'b mut self, n: usize) -> Result<EitherLifetime<'b, 'a>> {
+ let end = self.end(n)?;
+ let slice = &self.slice[self.index..end];
+ self.index = end;
+ Ok(EitherLifetime::Long(slice))
+ }
+
+ fn take_buffer<'b>(&'b mut self) -> EitherLifetime<'b, 'a> {
+ EitherLifetime::Short(&self.scratch)
+ }
+
+ #[inline]
+ fn read_into(&mut self, buf: &mut [u8]) -> Result<()> {
+ let end = self.end(buf.len())?;
+ buf.copy_from_slice(&self.slice[self.index..end]);
+ self.index = end;
+ Ok(())
+ }
+
+ #[inline]
+ fn discard(&mut self) {
+ self.index += 1;
+ }
+
+ fn offset(&self) -> u64 {
+ self.index as u64
+ }
+}
+
+/// A CBOR input source that reads from a slice of bytes using a fixed size scratch buffer.
+///
+/// [`SliceRead`](struct.SliceRead.html) and [`MutSliceRead`](struct.MutSliceRead.html) are usually
+/// preferred over this, as they can handle indefinite length items.
+#[derive(Debug)]
+pub struct SliceReadFixed<'a, 'b> {
+ slice: &'a [u8],
+ scratch: &'b mut [u8],
+ index: usize,
+ scratch_index: usize,
+}
+
+impl<'a, 'b> SliceReadFixed<'a, 'b> {
+ /// Creates a CBOR input source to read from a slice of bytes, backed by a scratch buffer.
+ pub fn new(slice: &'a [u8], scratch: &'b mut [u8]) -> SliceReadFixed<'a, 'b> {
+ SliceReadFixed {
+ slice,
+ scratch,
+ index: 0,
+ scratch_index: 0,
+ }
+ }
+
+ fn end(&self, n: usize) -> Result<usize> {
+ match self.index.checked_add(n) {
+ Some(end) if end <= self.slice.len() => Ok(end),
+ _ => Err(Error::syntax(
+ ErrorCode::EofWhileParsingValue,
+ self.slice.len() as u64,
+ )),
+ }
+ }
+
+ fn scratch_end(&self, n: usize) -> Result<usize> {
+ match self.scratch_index.checked_add(n) {
+ Some(end) if end <= self.scratch.len() => Ok(end),
+ _ => Err(Error::scratch_too_small(self.index as u64)),
+ }
+ }
+}
+
+#[cfg(not(feature = "unsealed_read_write"))]
+impl<'a, 'b> private::Sealed for SliceReadFixed<'a, 'b> {}
+
+impl<'a, 'b> Read<'a> for SliceReadFixed<'a, 'b> {
+ #[inline]
+ fn next(&mut self) -> Result<Option<u8>> {
+ Ok(if self.index < self.slice.len() {
+ let ch = self.slice[self.index];
+ self.index += 1;
+ Some(ch)
+ } else {
+ None
+ })
+ }
+
+ #[inline]
+ fn peek(&mut self) -> Result<Option<u8>> {
+ Ok(if self.index < self.slice.len() {
+ Some(self.slice[self.index])
+ } else {
+ None
+ })
+ }
+
+ fn clear_buffer(&mut self) {
+ self.scratch_index = 0;
+ }
+
+ fn read_to_buffer(&mut self, n: usize) -> Result<()> {
+ let end = self.end(n)?;
+ let scratch_end = self.scratch_end(n)?;
+ let slice = &self.slice[self.index..end];
+ self.scratch[self.scratch_index..scratch_end].copy_from_slice(&slice);
+ self.index = end;
+ self.scratch_index = scratch_end;
+
+ Ok(())
+ }
+
+ fn read<'c>(&'c mut self, n: usize) -> Result<EitherLifetime<'c, 'a>> {
+ let end = self.end(n)?;
+ let slice = &self.slice[self.index..end];
+ self.index = end;
+ Ok(EitherLifetime::Long(slice))
+ }
+
+ fn take_buffer<'c>(&'c mut self) -> EitherLifetime<'c, 'a> {
+ EitherLifetime::Short(&self.scratch[0..self.scratch_index])
+ }
+
+ #[inline]
+ fn read_into(&mut self, buf: &mut [u8]) -> Result<()> {
+ let end = self.end(buf.len())?;
+ buf.copy_from_slice(&self.slice[self.index..end]);
+ self.index = end;
+ Ok(())
+ }
+
+ #[inline]
+ fn discard(&mut self) {
+ self.index += 1;
+ }
+
+ fn offset(&self) -> u64 {
+ self.index as u64
+ }
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a, 'b> Offset for SliceReadFixed<'a, 'b> {
+ #[inline]
+ fn byte_offset(&self) -> usize {
+ self.index
+ }
+}
+
+/// A CBOR input source that reads from a slice of bytes, and can move data around internally to
+/// reassemble indefinite strings without the need of an allocated scratch buffer.
+#[derive(Debug)]
+pub struct MutSliceRead<'a> {
+ /// A complete view of the reader's data. It is promised that bytes before buffer_end are not
+ /// mutated any more.
+ slice: &'a mut [u8],
+ /// Read cursor position in slice
+ index: usize,
+ /// Number of bytes already discarded from the slice
+ before: usize,
+ /// End of the buffer area that contains all bytes read_into_buffer. This is always <= index.
+ buffer_end: usize,
+}
+
+impl<'a> MutSliceRead<'a> {
+ /// Creates a CBOR input source to read from a slice of bytes.
+ pub fn new(slice: &'a mut [u8]) -> MutSliceRead<'a> {
+ MutSliceRead {
+ slice,
+ index: 0,
+ before: 0,
+ buffer_end: 0,
+ }
+ }
+
+ fn end(&self, n: usize) -> Result<usize> {
+ match self.index.checked_add(n) {
+ Some(end) if end <= self.slice.len() => Ok(end),
+ _ => Err(Error::syntax(
+ ErrorCode::EofWhileParsingValue,
+ self.slice.len() as u64,
+ )),
+ }
+ }
+}
+
+#[cfg(not(feature = "unsealed_read_write"))]
+impl<'a> private::Sealed for MutSliceRead<'a> {}
+
+impl<'a> Read<'a> for MutSliceRead<'a> {
+ #[inline]
+ fn next(&mut self) -> Result<Option<u8>> {
+ // This is duplicated from SliceRead, can that be eased?
+ Ok(if self.index < self.slice.len() {
+ let ch = self.slice[self.index];
+ self.index += 1;
+ Some(ch)
+ } else {
+ None
+ })
+ }
+
+ #[inline]
+ fn peek(&mut self) -> Result<Option<u8>> {
+ // This is duplicated from SliceRead, can that be eased?
+ Ok(if self.index < self.slice.len() {
+ Some(self.slice[self.index])
+ } else {
+ None
+ })
+ }
+
+ fn clear_buffer(&mut self) {
+ self.slice = &mut mem::replace(&mut self.slice, &mut [])[self.index..];
+ self.before += self.index;
+ self.index = 0;
+ self.buffer_end = 0;
+ }
+
+ fn read_to_buffer(&mut self, n: usize) -> Result<()> {
+ let end = self.end(n)?;
+ debug_assert!(
+ self.buffer_end <= self.index,
+ "MutSliceRead invariant violated: scratch buffer exceeds index"
+ );
+ self.slice[self.buffer_end..end].rotate_left(self.index - self.buffer_end);
+ self.buffer_end += n;
+ self.index = end;
+
+ Ok(())
+ }
+
+ fn take_buffer<'b>(&'b mut self) -> EitherLifetime<'b, 'a> {
+ let (left, right) = mem::replace(&mut self.slice, &mut []).split_at_mut(self.index);
+ self.slice = right;
+ self.before += self.index;
+ self.index = 0;
+
+ let left = &left[..self.buffer_end];
+ self.buffer_end = 0;
+
+ EitherLifetime::Long(left)
+ }
+
+ #[inline]
+ fn read_into(&mut self, buf: &mut [u8]) -> Result<()> {
+ // This is duplicated from SliceRead, can that be eased?
+ let end = self.end(buf.len())?;
+ buf.copy_from_slice(&self.slice[self.index..end]);
+ self.index = end;
+ Ok(())
+ }
+
+ #[inline]
+ fn discard(&mut self) {
+ self.index += 1;
+ }
+
+ fn offset(&self) -> u64 {
+ (self.before + self.index) as u64
+ }
+}
diff --git a/third_party/rust/serde_cbor/src/ser.rs b/third_party/rust/serde_cbor/src/ser.rs
new file mode 100644
index 0000000000..7016dc340a
--- /dev/null
+++ b/third_party/rust/serde_cbor/src/ser.rs
@@ -0,0 +1,743 @@
+//! Serialize a Rust data structure to CBOR data.
+
+#[cfg(feature = "alloc")]
+use alloc::vec::Vec;
+
+#[cfg(feature = "std")]
+pub use crate::write::IoWrite;
+pub use crate::write::{SliceWrite, Write};
+
+use crate::error::{Error, Result};
+use half::f16;
+use serde::ser::{self, Serialize};
+#[cfg(feature = "std")]
+use std::io;
+
+use crate::tags::{get_tag, CBOR_NEWTYPE_NAME};
+
+/// Serializes a value to a vector.
+#[cfg(any(feature = "std", feature = "alloc"))]
+pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
+where
+ T: ser::Serialize,
+{
+ let mut vec = Vec::new();
+ value.serialize(&mut Serializer::new(&mut vec))?;
+ Ok(vec)
+}
+
+/// Serializes a value to a vector in packed format.
+#[cfg(feature = "std")]
+pub fn to_vec_packed<T>(value: &T) -> Result<Vec<u8>>
+where
+ T: ser::Serialize,
+{
+ let mut vec = Vec::new();
+ value.serialize(&mut Serializer::new(&mut IoWrite::new(&mut vec)).packed_format())?;
+ Ok(vec)
+}
+
+/// Serializes a value to a writer.
+#[cfg(feature = "std")]
+pub fn to_writer<W, T>(writer: W, value: &T) -> Result<()>
+where
+ W: io::Write,
+ T: ser::Serialize,
+{
+ value.serialize(&mut Serializer::new(&mut IoWrite::new(writer)))
+}
+
+/// A structure for serializing Rust values to CBOR.
+#[derive(Debug)]
+pub struct Serializer<W> {
+ writer: W,
+ packed: bool,
+ enum_as_map: bool,
+}
+
+impl<W> Serializer<W>
+where
+ W: Write,
+{
+ /// Creates a new CBOR serializer.
+ ///
+ /// `to_vec` and `to_writer` should normally be used instead of this method.
+ #[inline]
+ pub fn new(writer: W) -> Self {
+ Serializer {
+ writer,
+ packed: false,
+ enum_as_map: true,
+ }
+ }
+
+ /// Choose concise/packed format for serializer.
+ ///
+ /// In the packed format enum variant names and field names
+ /// are replaced with numeric indizes to conserve space.
+ pub fn packed_format(mut self) -> Self {
+ self.packed = true;
+ self
+ }
+
+ /// Enable old enum format used by `serde_cbor` versions <= v0.9.
+ ///
+ /// The `legacy_enums` option determines how enums are encoded.
+ ///
+ /// This makes no difference when encoding and decoding enums using
+ /// this crate, but it shows up when decoding to a `Value` or decoding
+ /// in other languages.
+ ///
+ /// # Examples
+ ///
+ /// Given the following enum
+ ///
+ /// ```rust
+ /// enum Enum {
+ /// Unit,
+ /// NewType(i32),
+ /// Tuple(String, bool),
+ /// Struct{ x: i32, y: i32 },
+ /// }
+ /// ```
+ /// we will give the `Value` with the same encoding for each case using
+ /// JSON notation.
+ ///
+ /// ## Default encodings
+ ///
+ /// * `Enum::Unit` encodes as `"Unit"`
+ /// * `Enum::NewType(10)` encodes as `{"NewType": 10}`
+ /// * `Enum::Tuple("x", true)` encodes as `{"Tuple": ["x", true]}`
+ ///
+ /// ## Legacy encodings
+ ///
+ /// * `Enum::Unit` encodes as `"Unit"`
+ /// * `Enum::NewType(10)` encodes as `["NewType", 10]`
+ /// * `Enum::Tuple("x", true)` encodes as `["Tuple", "x", true]`
+ /// * `Enum::Struct{ x: 5, y: -5 }` encodes as `["Struct", {"x": 5, "y": -5}]`
+ pub fn legacy_enums(mut self) -> Self {
+ self.enum_as_map = false;
+ self
+ }
+
+ /// Writes a CBOR self-describe tag to the stream.
+ ///
+ /// Tagging allows a decoder to distinguish different file formats based on their content
+ /// without further information.
+ #[inline]
+ pub fn self_describe(&mut self) -> Result<()> {
+ let mut buf = [6 << 5 | 25, 0, 0];
+ (&mut buf[1..]).copy_from_slice(&55799u16.to_be_bytes());
+ self.writer.write_all(&buf).map_err(|e| e.into())
+ }
+
+ /// Unwrap the `Writer` from the `Serializer`.
+ #[inline]
+ pub fn into_inner(self) -> W {
+ self.writer
+ }
+
+ #[inline]
+ fn write_u8(&mut self, major: u8, value: u8) -> Result<()> {
+ if value <= 0x17 {
+ self.writer.write_all(&[major << 5 | value])
+ } else {
+ let buf = [major << 5 | 24, value];
+ self.writer.write_all(&buf)
+ }
+ .map_err(|e| e.into())
+ }
+
+ #[inline]
+ fn write_u16(&mut self, major: u8, value: u16) -> Result<()> {
+ if value <= u16::from(u8::max_value()) {
+ self.write_u8(major, value as u8)
+ } else {
+ let mut buf = [major << 5 | 25, 0, 0];
+ (&mut buf[1..]).copy_from_slice(&value.to_be_bytes());
+ self.writer.write_all(&buf).map_err(|e| e.into())
+ }
+ }
+
+ #[inline]
+ fn write_u32(&mut self, major: u8, value: u32) -> Result<()> {
+ if value <= u32::from(u16::max_value()) {
+ self.write_u16(major, value as u16)
+ } else {
+ let mut buf = [major << 5 | 26, 0, 0, 0, 0];
+ (&mut buf[1..]).copy_from_slice(&value.to_be_bytes());
+ self.writer.write_all(&buf).map_err(|e| e.into())
+ }
+ }
+
+ #[inline]
+ fn write_u64(&mut self, major: u8, value: u64) -> Result<()> {
+ if value <= u64::from(u32::max_value()) {
+ self.write_u32(major, value as u32)
+ } else {
+ let mut buf = [major << 5 | 27, 0, 0, 0, 0, 0, 0, 0, 0];
+ (&mut buf[1..]).copy_from_slice(&value.to_be_bytes());
+ self.writer.write_all(&buf).map_err(|e| e.into())
+ }
+ }
+
+ #[inline]
+ fn serialize_collection<'a>(
+ &'a mut self,
+ major: u8,
+ len: Option<usize>,
+ ) -> Result<CollectionSerializer<'a, W>> {
+ let needs_eof = match len {
+ Some(len) => {
+ self.write_u64(major, len as u64)?;
+ false
+ }
+ None => {
+ self.writer
+ .write_all(&[major << 5 | 31])
+ .map_err(|e| e.into())?;
+ true
+ }
+ };
+
+ Ok(CollectionSerializer {
+ ser: self,
+ needs_eof,
+ })
+ }
+}
+
+impl<'a, W> ser::Serializer for &'a mut Serializer<W>
+where
+ W: Write,
+{
+ type Ok = ();
+ type Error = Error;
+
+ type SerializeSeq = CollectionSerializer<'a, W>;
+ type SerializeTuple = &'a mut Serializer<W>;
+ type SerializeTupleStruct = &'a mut Serializer<W>;
+ type SerializeTupleVariant = &'a mut Serializer<W>;
+ type SerializeMap = CollectionSerializer<'a, W>;
+ type SerializeStruct = StructSerializer<'a, W>;
+ type SerializeStructVariant = StructSerializer<'a, W>;
+
+ #[inline]
+ fn serialize_bool(self, value: bool) -> Result<()> {
+ let value = if value { 0xf5 } else { 0xf4 };
+ self.writer.write_all(&[value]).map_err(|e| e.into())
+ }
+
+ #[inline]
+ fn serialize_i8(self, value: i8) -> Result<()> {
+ if value < 0 {
+ self.write_u8(1, -(value + 1) as u8)
+ } else {
+ self.write_u8(0, value as u8)
+ }
+ }
+
+ #[inline]
+ fn serialize_i16(self, value: i16) -> Result<()> {
+ if value < 0 {
+ self.write_u16(1, -(value + 1) as u16)
+ } else {
+ self.write_u16(0, value as u16)
+ }
+ }
+
+ #[inline]
+ fn serialize_i32(self, value: i32) -> Result<()> {
+ if value < 0 {
+ self.write_u32(1, -(value + 1) as u32)
+ } else {
+ self.write_u32(0, value as u32)
+ }
+ }
+
+ #[inline]
+ fn serialize_i64(self, value: i64) -> Result<()> {
+ if value < 0 {
+ self.write_u64(1, -(value + 1) as u64)
+ } else {
+ self.write_u64(0, value as u64)
+ }
+ }
+
+ #[inline]
+ fn serialize_i128(self, value: i128) -> Result<()> {
+ if value < 0 {
+ if -(value + 1) > i128::from(u64::max_value()) {
+ return Err(Error::message("The number can't be stored in CBOR"));
+ }
+ self.write_u64(1, -(value + 1) as u64)
+ } else {
+ if value > i128::from(u64::max_value()) {
+ return Err(Error::message("The number can't be stored in CBOR"));
+ }
+ self.write_u64(0, value as u64)
+ }
+ }
+
+ #[inline]
+ fn serialize_u8(self, value: u8) -> Result<()> {
+ self.write_u8(0, value)
+ }
+
+ #[inline]
+ fn serialize_u16(self, value: u16) -> Result<()> {
+ self.write_u16(0, value)
+ }
+
+ #[inline]
+ fn serialize_u32(self, value: u32) -> Result<()> {
+ self.write_u32(0, value)
+ }
+
+ #[inline]
+ fn serialize_u64(self, value: u64) -> Result<()> {
+ self.write_u64(0, value)
+ }
+
+ #[inline]
+ fn serialize_u128(self, value: u128) -> Result<()> {
+ if value > u128::from(u64::max_value()) {
+ return Err(Error::message("The number can't be stored in CBOR"));
+ }
+ self.write_u64(0, value as u64)
+ }
+
+ #[inline]
+ #[allow(clippy::float_cmp)]
+ fn serialize_f32(self, value: f32) -> Result<()> {
+ if value.is_infinite() {
+ if value.is_sign_positive() {
+ self.writer.write_all(&[0xf9, 0x7c, 0x00])
+ } else {
+ self.writer.write_all(&[0xf9, 0xfc, 0x00])
+ }
+ } else if value.is_nan() {
+ self.writer.write_all(&[0xf9, 0x7e, 0x00])
+ } else if f32::from(f16::from_f32(value)) == value {
+ let mut buf = [0xf9, 0, 0];
+ (&mut buf[1..]).copy_from_slice(&f16::from_f32(value).to_bits().to_be_bytes());
+ self.writer.write_all(&buf)
+ } else {
+ let mut buf = [0xfa, 0, 0, 0, 0];
+ (&mut buf[1..]).copy_from_slice(&value.to_bits().to_be_bytes());
+ self.writer.write_all(&buf)
+ }
+ .map_err(|e| e.into())
+ }
+
+ #[inline]
+ #[allow(clippy::float_cmp)]
+ fn serialize_f64(self, value: f64) -> Result<()> {
+ if !value.is_finite() || f64::from(value as f32) == value {
+ self.serialize_f32(value as f32)
+ } else {
+ let mut buf = [0xfb, 0, 0, 0, 0, 0, 0, 0, 0];
+ (&mut buf[1..]).copy_from_slice(&value.to_bits().to_be_bytes());
+ self.writer.write_all(&buf).map_err(|e| e.into())
+ }
+ }
+
+ #[inline]
+ fn serialize_char(self, value: char) -> Result<()> {
+ // A char encoded as UTF-8 takes 4 bytes at most.
+ let mut buf = [0; 4];
+ self.serialize_str(value.encode_utf8(&mut buf))
+ }
+
+ #[inline]
+ fn serialize_str(self, value: &str) -> Result<()> {
+ self.write_u64(3, value.len() as u64)?;
+ self.writer
+ .write_all(value.as_bytes())
+ .map_err(|e| e.into())
+ }
+
+ #[inline]
+ fn serialize_bytes(self, value: &[u8]) -> Result<()> {
+ self.write_u64(2, value.len() as u64)?;
+ self.writer.write_all(value).map_err(|e| e.into())
+ }
+
+ #[inline]
+ fn serialize_unit(self) -> Result<()> {
+ self.serialize_none()
+ }
+
+ #[inline]
+ fn serialize_some<T>(self, value: &T) -> Result<()>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ value.serialize(self)
+ }
+
+ #[inline]
+ fn serialize_none(self) -> Result<()> {
+ self.writer.write_all(&[0xf6]).map_err(|e| e.into())
+ }
+
+ #[inline]
+ fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
+ self.serialize_unit()
+ }
+
+ #[inline]
+ fn serialize_unit_variant(
+ self,
+ _name: &'static str,
+ variant_index: u32,
+ variant: &'static str,
+ ) -> Result<()> {
+ if self.packed {
+ self.serialize_u32(variant_index)
+ } else {
+ self.serialize_str(variant)
+ }
+ }
+
+ #[inline]
+ fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<()>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ if name == CBOR_NEWTYPE_NAME {
+ for tag in get_tag().into_iter() {
+ self.write_u64(6, tag)?;
+ }
+ }
+ value.serialize(self)
+ }
+
+ #[inline]
+ fn serialize_newtype_variant<T>(
+ self,
+ name: &'static str,
+ variant_index: u32,
+ variant: &'static str,
+ value: &T,
+ ) -> Result<()>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ if self.enum_as_map {
+ self.write_u64(5, 1u64)?;
+ variant.serialize(&mut *self)?;
+ } else {
+ self.writer.write_all(&[4 << 5 | 2]).map_err(|e| e.into())?;
+ self.serialize_unit_variant(name, variant_index, variant)?;
+ }
+ value.serialize(self)
+ }
+
+ #[inline]
+ fn serialize_seq(self, len: Option<usize>) -> Result<CollectionSerializer<'a, W>> {
+ self.serialize_collection(4, len)
+ }
+
+ #[inline]
+ fn serialize_tuple(self, len: usize) -> Result<&'a mut Serializer<W>> {
+ self.write_u64(4, len as u64)?;
+ Ok(self)
+ }
+
+ #[inline]
+ fn serialize_tuple_struct(
+ self,
+ _name: &'static str,
+ len: usize,
+ ) -> Result<&'a mut Serializer<W>> {
+ self.serialize_tuple(len)
+ }
+
+ #[inline]
+ fn serialize_tuple_variant(
+ self,
+ name: &'static str,
+ variant_index: u32,
+ variant: &'static str,
+ len: usize,
+ ) -> Result<&'a mut Serializer<W>> {
+ if self.enum_as_map {
+ self.write_u64(5, 1u64)?;
+ variant.serialize(&mut *self)?;
+ self.serialize_tuple(len)
+ } else {
+ self.write_u64(4, (len + 1) as u64)?;
+ self.serialize_unit_variant(name, variant_index, variant)?;
+ Ok(self)
+ }
+ }
+
+ #[inline]
+ fn serialize_map(self, len: Option<usize>) -> Result<CollectionSerializer<'a, W>> {
+ self.serialize_collection(5, len)
+ }
+
+ #[cfg(not(feature = "std"))]
+ fn collect_str<T: ?Sized>(self, value: &T) -> Result<()>
+ where
+ T: core::fmt::Display,
+ {
+ use crate::write::FmtWrite;
+ use core::fmt::Write;
+
+ let mut w = FmtWrite::new(&mut self.writer);
+ write!(w, "{}", value)?;
+ Ok(())
+ }
+
+ #[inline]
+ fn serialize_struct(self, _name: &'static str, len: usize) -> Result<StructSerializer<'a, W>> {
+ self.write_u64(5, len as u64)?;
+ Ok(StructSerializer { ser: self, idx: 0 })
+ }
+
+ #[inline]
+ fn serialize_struct_variant(
+ self,
+ name: &'static str,
+ variant_index: u32,
+ variant: &'static str,
+ len: usize,
+ ) -> Result<StructSerializer<'a, W>> {
+ if self.enum_as_map {
+ self.write_u64(5, 1u64)?;
+ } else {
+ self.writer.write_all(&[4 << 5 | 2]).map_err(|e| e.into())?;
+ }
+ self.serialize_unit_variant(name, variant_index, variant)?;
+ self.serialize_struct(name, len)
+ }
+
+ #[inline]
+ fn is_human_readable(&self) -> bool {
+ false
+ }
+}
+
+impl<'a, W> ser::SerializeTuple for &'a mut Serializer<W>
+where
+ W: Write,
+{
+ type Ok = ();
+ type Error = Error;
+
+ #[inline]
+ fn serialize_element<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ value.serialize(&mut **self)
+ }
+
+ #[inline]
+ fn end(self) -> Result<()> {
+ Ok(())
+ }
+}
+
+impl<'a, W> ser::SerializeTupleStruct for &'a mut Serializer<W>
+where
+ W: Write,
+{
+ type Ok = ();
+ type Error = Error;
+
+ #[inline]
+ fn serialize_field<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ value.serialize(&mut **self)
+ }
+
+ #[inline]
+ fn end(self) -> Result<()> {
+ Ok(())
+ }
+}
+
+impl<'a, W> ser::SerializeTupleVariant for &'a mut Serializer<W>
+where
+ W: Write,
+{
+ type Ok = ();
+ type Error = Error;
+
+ #[inline]
+ fn serialize_field<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ value.serialize(&mut **self)
+ }
+
+ #[inline]
+ fn end(self) -> Result<()> {
+ Ok(())
+ }
+}
+
+#[doc(hidden)]
+pub struct StructSerializer<'a, W> {
+ ser: &'a mut Serializer<W>,
+ idx: u32,
+}
+
+impl<'a, W> StructSerializer<'a, W>
+where
+ W: Write,
+{
+ #[inline]
+ fn serialize_field_inner<T>(&mut self, key: &'static str, value: &T) -> Result<()>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ if self.ser.packed {
+ self.idx.serialize(&mut *self.ser)?;
+ } else {
+ key.serialize(&mut *self.ser)?;
+ }
+ value.serialize(&mut *self.ser)?;
+ self.idx += 1;
+ Ok(())
+ }
+
+ #[inline]
+ fn skip_field_inner(&mut self, _: &'static str) -> Result<()> {
+ self.idx += 1;
+ Ok(())
+ }
+
+ #[inline]
+ fn end_inner(self) -> Result<()> {
+ Ok(())
+ }
+}
+
+impl<'a, W> ser::SerializeStruct for StructSerializer<'a, W>
+where
+ W: Write,
+{
+ type Ok = ();
+ type Error = Error;
+
+ #[inline]
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ self.serialize_field_inner(key, value)
+ }
+
+ #[inline]
+ fn skip_field(&mut self, key: &'static str) -> Result<()> {
+ self.skip_field_inner(key)
+ }
+
+ #[inline]
+ fn end(self) -> Result<()> {
+ self.end_inner()
+ }
+}
+
+impl<'a, W> ser::SerializeStructVariant for StructSerializer<'a, W>
+where
+ W: Write,
+{
+ type Ok = ();
+ type Error = Error;
+
+ #[inline]
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ self.serialize_field_inner(key, value)
+ }
+
+ #[inline]
+ fn skip_field(&mut self, key: &'static str) -> Result<()> {
+ self.skip_field_inner(key)
+ }
+
+ #[inline]
+ fn end(self) -> Result<()> {
+ self.end_inner()
+ }
+}
+
+#[doc(hidden)]
+pub struct CollectionSerializer<'a, W> {
+ ser: &'a mut Serializer<W>,
+ needs_eof: bool,
+}
+
+impl<'a, W> CollectionSerializer<'a, W>
+where
+ W: Write,
+{
+ #[inline]
+ fn end_inner(self) -> Result<()> {
+ if self.needs_eof {
+ self.ser.writer.write_all(&[0xff]).map_err(|e| e.into())
+ } else {
+ Ok(())
+ }
+ }
+}
+
+impl<'a, W> ser::SerializeSeq for CollectionSerializer<'a, W>
+where
+ W: Write,
+{
+ type Ok = ();
+ type Error = Error;
+
+ #[inline]
+ fn serialize_element<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ value.serialize(&mut *self.ser)
+ }
+
+ #[inline]
+ fn end(self) -> Result<()> {
+ self.end_inner()
+ }
+}
+
+impl<'a, W> ser::SerializeMap for CollectionSerializer<'a, W>
+where
+ W: Write,
+{
+ type Ok = ();
+ type Error = Error;
+
+ #[inline]
+ fn serialize_key<T>(&mut self, key: &T) -> Result<()>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ key.serialize(&mut *self.ser)
+ }
+
+ #[inline]
+ fn serialize_value<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ value.serialize(&mut *self.ser)
+ }
+
+ #[inline]
+ fn end(self) -> Result<()> {
+ self.end_inner()
+ }
+}
diff --git a/third_party/rust/serde_cbor/src/tags.rs b/third_party/rust/serde_cbor/src/tags.rs
new file mode 100644
index 0000000000..8adccb8ea8
--- /dev/null
+++ b/third_party/rust/serde_cbor/src/tags.rs
@@ -0,0 +1,220 @@
+//! Support for cbor tags
+use core::fmt;
+use core::marker::PhantomData;
+use serde::de::{
+ Deserialize, Deserializer, EnumAccess, IntoDeserializer, MapAccess, SeqAccess, Visitor,
+};
+use serde::forward_to_deserialize_any;
+use serde::ser::{Serialize, Serializer};
+
+/// signals that a newtype is from a CBOR tag
+pub(crate) const CBOR_NEWTYPE_NAME: &str = "\0cbor_tag";
+
+/// A value that is optionally tagged with a cbor tag
+///
+/// this only serves as an intermediate helper for tag serialization or deserialization
+pub struct Tagged<T> {
+ /// cbor tag
+ pub tag: Option<u64>,
+ /// value
+ pub value: T,
+}
+
+impl<T> Tagged<T> {
+ /// Create a new tagged value
+ pub fn new(tag: Option<u64>, value: T) -> Self {
+ Self { tag, value }
+ }
+}
+
+impl<T: Serialize> Serialize for Tagged<T> {
+ fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
+ set_tag(self.tag);
+ let r = s.serialize_newtype_struct(CBOR_NEWTYPE_NAME, &self.value);
+ set_tag(None);
+ r
+ }
+}
+
+fn untagged<T>(value: T) -> Tagged<T> {
+ Tagged::new(None, value)
+}
+
+macro_rules! delegate {
+ ($name: ident, $type: ty) => {
+ fn $name<E: serde::de::Error>(self, v: $type) -> Result<Self::Value, E> {
+ T::deserialize(v.into_deserializer()).map(untagged)
+ }
+ };
+}
+
+struct EnumDeserializer<A>(A);
+
+impl<'de, A> Deserializer<'de> for EnumDeserializer<A>
+where
+ A: EnumAccess<'de>,
+{
+ type Error = A::Error;
+
+ fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
+ visitor.visit_enum(self.0)
+ }
+
+ forward_to_deserialize_any! {
+ bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
+ bytes byte_buf option unit unit_struct newtype_struct seq tuple
+ tuple_struct map struct enum identifier ignored_any
+ }
+}
+
+struct NoneDeserializer<E>(PhantomData<E>);
+
+impl<'de, E> Deserializer<'de> for NoneDeserializer<E>
+where
+ E: serde::de::Error,
+{
+ type Error = E;
+
+ fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
+ visitor.visit_none()
+ }
+
+ forward_to_deserialize_any! {
+ bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
+ bytes byte_buf option unit unit_struct newtype_struct seq tuple
+ tuple_struct map struct enum identifier ignored_any
+ }
+}
+
+struct BytesDeserializer<'a, E>(&'a [u8], PhantomData<E>);
+
+impl<'de, 'a, E> Deserializer<'de> for BytesDeserializer<'a, E>
+where
+ E: serde::de::Error,
+{
+ type Error = E;
+
+ fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
+ visitor.visit_bytes(self.0)
+ }
+
+ forward_to_deserialize_any! {
+ bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
+ bytes byte_buf option unit unit_struct newtype_struct seq tuple
+ tuple_struct map struct enum identifier ignored_any
+ }
+}
+
+/// A visitor that intercepts *just* visit_newtype_struct and passes through everything else.
+struct MaybeTaggedVisitor<T>(PhantomData<T>);
+
+impl<'de, T: Deserialize<'de>> Visitor<'de> for MaybeTaggedVisitor<T> {
+ type Value = Tagged<T>;
+
+ fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt.write_str("a cbor tag newtype")
+ }
+
+ delegate!(visit_bool, bool);
+
+ delegate!(visit_i8, i8);
+ delegate!(visit_i16, i16);
+ delegate!(visit_i32, i32);
+ delegate!(visit_i64, i64);
+
+ delegate!(visit_u8, u8);
+ delegate!(visit_u16, u16);
+ delegate!(visit_u32, u32);
+ delegate!(visit_u64, u64);
+
+ delegate!(visit_f32, f32);
+ delegate!(visit_f64, f64);
+
+ delegate!(visit_char, char);
+ delegate!(visit_str, &str);
+ delegate!(visit_borrowed_str, &'de str);
+
+ #[cfg(feature = "std")]
+ delegate!(visit_byte_buf, Vec<u8>);
+
+ #[cfg(feature = "std")]
+ delegate!(visit_string, String);
+
+ fn visit_bytes<E: serde::de::Error>(self, value: &[u8]) -> Result<Self::Value, E> {
+ T::deserialize(BytesDeserializer(value, PhantomData)).map(untagged)
+ }
+
+ fn visit_borrowed_bytes<E: serde::de::Error>(self, value: &'de [u8]) -> Result<Self::Value, E> {
+ T::deserialize(serde::de::value::BorrowedBytesDeserializer::new(value)).map(untagged)
+ }
+
+ fn visit_unit<E: serde::de::Error>(self) -> Result<Self::Value, E> {
+ T::deserialize(().into_deserializer()).map(untagged)
+ }
+
+ fn visit_none<E: serde::de::Error>(self) -> Result<Self::Value, E> {
+ T::deserialize(NoneDeserializer(PhantomData)).map(untagged)
+ }
+
+ fn visit_some<D: Deserializer<'de>>(self, deserializer: D) -> Result<Self::Value, D::Error> {
+ T::deserialize(deserializer).map(untagged)
+ }
+
+ fn visit_seq<A: SeqAccess<'de>>(self, seq: A) -> Result<Self::Value, A::Error> {
+ T::deserialize(serde::de::value::SeqAccessDeserializer::new(seq)).map(untagged)
+ }
+
+ fn visit_map<V: MapAccess<'de>>(self, map: V) -> Result<Self::Value, V::Error> {
+ T::deserialize(serde::de::value::MapAccessDeserializer::new(map)).map(untagged)
+ }
+
+ fn visit_enum<A: EnumAccess<'de>>(self, data: A) -> Result<Self::Value, A::Error> {
+ T::deserialize(EnumDeserializer(data)).map(untagged)
+ }
+
+ fn visit_newtype_struct<D: serde::Deserializer<'de>>(
+ self,
+ deserializer: D,
+ ) -> Result<Self::Value, D::Error> {
+ let t = get_tag();
+ T::deserialize(deserializer).map(|v| Tagged::new(t, v))
+ }
+}
+
+impl<'de, T: serde::de::Deserialize<'de>> serde::de::Deserialize<'de> for Tagged<T> {
+ fn deserialize<D: serde::de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
+ deserializer.deserialize_any(MaybeTaggedVisitor::<T>(PhantomData))
+ }
+}
+
+/// function to get the current cbor tag
+///
+/// The only place where it makes sense to call this function is within visit_newtype_struct of a serde visitor.
+/// This is a low level API. In most cases it is preferable to use Tagged
+pub fn current_cbor_tag() -> Option<u64> {
+ get_tag()
+}
+
+#[cfg(feature = "tags")]
+pub(crate) fn set_tag(value: Option<u64>) {
+ CBOR_TAG.with(|f| *f.borrow_mut() = value);
+}
+
+#[cfg(feature = "tags")]
+pub(crate) fn get_tag() -> Option<u64> {
+ CBOR_TAG.with(|f| *f.borrow())
+}
+
+#[cfg(not(feature = "tags"))]
+pub(crate) fn set_tag(_value: Option<u64>) {}
+
+#[cfg(not(feature = "tags"))]
+pub(crate) fn get_tag() -> Option<u64> {
+ None
+}
+
+#[cfg(feature = "tags")]
+use std::cell::RefCell;
+
+#[cfg(feature = "tags")]
+thread_local!(static CBOR_TAG: RefCell<Option<u64>> = RefCell::new(None));
diff --git a/third_party/rust/serde_cbor/src/value/de.rs b/third_party/rust/serde_cbor/src/value/de.rs
new file mode 100644
index 0000000000..f5bdbb7467
--- /dev/null
+++ b/third_party/rust/serde_cbor/src/value/de.rs
@@ -0,0 +1,166 @@
+use std::collections::BTreeMap;
+use std::fmt;
+
+use crate::value::Value;
+use serde::de;
+
+impl<'de> de::Deserialize<'de> for Value {
+ #[inline]
+ fn deserialize<D>(deserializer: D) -> Result<Value, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ {
+ struct ValueVisitor;
+
+ impl<'de> de::Visitor<'de> for ValueVisitor {
+ type Value = Value;
+
+ fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt.write_str("any valid CBOR value")
+ }
+
+ #[inline]
+ fn visit_str<E>(self, value: &str) -> Result<Value, E>
+ where
+ E: de::Error,
+ {
+ self.visit_string(String::from(value))
+ }
+
+ #[inline]
+ fn visit_string<E>(self, value: String) -> Result<Value, E>
+ where
+ E: de::Error,
+ {
+ Ok(Value::Text(value))
+ }
+ #[inline]
+ fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
+ where
+ E: de::Error,
+ {
+ self.visit_byte_buf(v.to_owned())
+ }
+
+ #[inline]
+ fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
+ where
+ E: de::Error,
+ {
+ Ok(Value::Bytes(v))
+ }
+
+ #[inline]
+ fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
+ where
+ E: de::Error,
+ {
+ Ok(Value::Integer(v.into()))
+ }
+
+ #[inline]
+ fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
+ where
+ E: de::Error,
+ {
+ Ok(Value::Integer(v.into()))
+ }
+
+ #[inline]
+ fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
+ where
+ E: de::Error,
+ {
+ Ok(Value::Integer(v))
+ }
+
+ #[inline]
+ fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
+ where
+ E: de::Error,
+ {
+ Ok(Value::Bool(v))
+ }
+
+ #[inline]
+ fn visit_none<E>(self) -> Result<Self::Value, E>
+ where
+ E: de::Error,
+ {
+ self.visit_unit()
+ }
+
+ #[inline]
+ fn visit_unit<E>(self) -> Result<Self::Value, E>
+ where
+ E: de::Error,
+ {
+ Ok(Value::Null)
+ }
+
+ #[inline]
+ fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
+ where
+ V: de::SeqAccess<'de>,
+ {
+ let mut vec = Vec::new();
+
+ while let Some(elem) = visitor.next_element()? {
+ vec.push(elem);
+ }
+
+ Ok(Value::Array(vec))
+ }
+
+ #[inline]
+ fn visit_map<V>(self, mut visitor: V) -> Result<Value, V::Error>
+ where
+ V: de::MapAccess<'de>,
+ {
+ let mut values = BTreeMap::new();
+
+ while let Some((key, value)) = visitor.next_entry()? {
+ values.insert(key, value);
+ }
+
+ Ok(Value::Map(values))
+ }
+
+ #[inline]
+ fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
+ where
+ E: de::Error,
+ {
+ Ok(Value::Float(v))
+ }
+
+ fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ let tag = crate::tags::get_tag();
+ let inner = deserializer.deserialize_any(self);
+ match tag {
+ Some(tag) => inner.map(|v| Value::Tag(tag, Box::new(v))),
+ None => inner,
+ }
+ }
+ }
+
+ deserializer.deserialize_any(ValueVisitor)
+ }
+}
+
+/// Convert a `serde_cbor::Value` into a type `T`
+#[allow(clippy::needless_pass_by_value)]
+pub fn from_value<T>(value: Value) -> Result<T, crate::error::Error>
+where
+ T: de::DeserializeOwned,
+{
+ // TODO implement in a way that doesn't require
+ // roundtrip through buffer (i.e. by implementing
+ // `serde::de::Deserializer` for `Value` and then doing
+ // `T::deserialize(value)`).
+ let buf = crate::to_vec(&value)?;
+ crate::from_slice(buf.as_slice())
+}
diff --git a/third_party/rust/serde_cbor/src/value/mod.rs b/third_party/rust/serde_cbor/src/value/mod.rs
new file mode 100644
index 0000000000..7bd2255314
--- /dev/null
+++ b/third_party/rust/serde_cbor/src/value/mod.rs
@@ -0,0 +1,156 @@
+//! CBOR values, keys and serialization routines.
+
+mod de;
+mod ser;
+
+use std::cmp::{Ord, Ordering, PartialOrd};
+use std::collections::BTreeMap;
+
+#[doc(inline)]
+pub use self::de::from_value;
+#[doc(inline)]
+pub use self::ser::to_value;
+
+/// The `Value` enum, a loosely typed way of representing any valid CBOR value.
+///
+/// Maps are sorted according to the canonical ordering
+/// described in [RFC 7049 bis].
+/// Therefore values are unambiguously serialized
+/// to a canonical form of CBOR from the same RFC.
+///
+/// [RFC 7049 bis]: https://tools.ietf.org/html/draft-ietf-cbor-7049bis-04#section-2
+#[derive(Clone, Debug)]
+pub enum Value {
+ /// Represents the absence of a value or the value undefined.
+ Null,
+ /// Represents a boolean value.
+ Bool(bool),
+ /// Integer CBOR numbers.
+ ///
+ /// The biggest value that can be represented is 2^64 - 1.
+ /// While the smallest value is -2^64.
+ /// Values outside this range can't be serialized
+ /// and will cause an error.
+ Integer(i128),
+ /// Represents a floating point value.
+ Float(f64),
+ /// Represents a byte string.
+ Bytes(Vec<u8>),
+ /// Represents an UTF-8 encoded string.
+ Text(String),
+ /// Represents an array of values.
+ Array(Vec<Value>),
+ /// Represents a map.
+ ///
+ /// Maps are also called tables, dictionaries, hashes, or objects (in JSON).
+ /// While any value can be used as a CBOR key
+ /// it is better to use only one type of key in a map
+ /// to avoid ambiguity.
+ /// If floating point values are used as keys they are compared bit-by-bit for equality.
+ /// If arrays or maps are used as keys the comparisons
+ /// to establish canonical order may be slow and therefore insertion
+ /// and retrieval of values will be slow too.
+ Map(BTreeMap<Value, Value>),
+ /// Represents a tagged value
+ Tag(u64, Box<Value>),
+ // The hidden variant allows the enum to be extended
+ // with variants for tags and simple values.
+ #[doc(hidden)]
+ __Hidden,
+}
+
+impl PartialEq for Value {
+ fn eq(&self, other: &Value) -> bool {
+ self.cmp(other) == Ordering::Equal
+ }
+}
+
+impl Eq for Value {}
+
+impl PartialOrd for Value {
+ fn partial_cmp(&self, other: &Value) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for Value {
+ fn cmp(&self, other: &Value) -> Ordering {
+ // Determine the canonical order of two values:
+ // 1. Smaller major type sorts first.
+ // 2. Shorter sequence sorts first.
+ // 3. Compare integers by magnitude.
+ // 4. Compare byte and text sequences lexically.
+ // 5. Compare the serializations of both types. (expensive)
+ use self::Value::*;
+ if self.major_type() != other.major_type() {
+ return self.major_type().cmp(&other.major_type());
+ }
+ match (self, other) {
+ (Integer(a), Integer(b)) => a.abs().cmp(&b.abs()),
+ (Bytes(a), Bytes(b)) if a.len() != b.len() => a.len().cmp(&b.len()),
+ (Text(a), Text(b)) if a.len() != b.len() => a.len().cmp(&b.len()),
+ (Array(a), Array(b)) if a.len() != b.len() => a.len().cmp(&b.len()),
+ (Map(a), Map(b)) if a.len() != b.len() => a.len().cmp(&b.len()),
+ (Bytes(a), Bytes(b)) => a.cmp(b),
+ (Text(a), Text(b)) => a.cmp(b),
+ (a, b) => {
+ let a = crate::to_vec(a).expect("self is serializable");
+ let b = crate::to_vec(b).expect("other is serializable");
+ a.cmp(&b)
+ }
+ }
+ }
+}
+
+macro_rules! impl_from {
+ ($variant:path, $for_type:ty) => {
+ impl From<$for_type> for Value {
+ fn from(v: $for_type) -> Value {
+ $variant(v.into())
+ }
+ }
+ };
+}
+
+impl_from!(Value::Bool, bool);
+impl_from!(Value::Integer, i8);
+impl_from!(Value::Integer, i16);
+impl_from!(Value::Integer, i32);
+impl_from!(Value::Integer, i64);
+// i128 omitted because not all numbers fit in CBOR serialization
+impl_from!(Value::Integer, u8);
+impl_from!(Value::Integer, u16);
+impl_from!(Value::Integer, u32);
+impl_from!(Value::Integer, u64);
+// u128 omitted because not all numbers fit in CBOR serialization
+impl_from!(Value::Float, f32);
+impl_from!(Value::Float, f64);
+impl_from!(Value::Bytes, Vec<u8>);
+impl_from!(Value::Text, String);
+// TODO: figure out if these impls should be more generic or removed.
+impl_from!(Value::Array, Vec<Value>);
+impl_from!(Value::Map, BTreeMap<Value, Value>);
+
+impl Value {
+ fn major_type(&self) -> u8 {
+ use self::Value::*;
+ match self {
+ Null => 7,
+ Bool(_) => 7,
+ Integer(v) => {
+ if *v >= 0 {
+ 0
+ } else {
+ 1
+ }
+ }
+ Tag(_, _) => 6,
+ Float(_) => 7,
+ Bytes(_) => 2,
+ Text(_) => 3,
+ Array(_) => 4,
+ Map(_) => 5,
+ __Hidden => unreachable!(),
+ }
+ }
+}
diff --git a/third_party/rust/serde_cbor/src/value/ser.rs b/third_party/rust/serde_cbor/src/value/ser.rs
new file mode 100644
index 0000000000..347aae9601
--- /dev/null
+++ b/third_party/rust/serde_cbor/src/value/ser.rs
@@ -0,0 +1,443 @@
+// Copyright 2017 Serde Developers
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::collections::BTreeMap;
+
+use crate::error::Error;
+use serde::{self, Serialize};
+
+use crate::tags::Tagged;
+use crate::value::Value;
+
+impl serde::Serialize for Value {
+ #[inline]
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::Serializer,
+ {
+ match *self {
+ Value::Integer(v) => serializer.serialize_i128(v),
+ Value::Bytes(ref v) => serializer.serialize_bytes(&v),
+ Value::Text(ref v) => serializer.serialize_str(&v),
+ Value::Array(ref v) => v.serialize(serializer),
+ Value::Map(ref v) => v.serialize(serializer),
+ Value::Tag(tag, ref v) => Tagged::new(Some(tag), v).serialize(serializer),
+ Value::Float(v) => serializer.serialize_f64(v),
+ Value::Bool(v) => serializer.serialize_bool(v),
+ Value::Null => serializer.serialize_unit(),
+ Value::__Hidden => unreachable!(),
+ }
+ }
+}
+
+struct Serializer;
+
+impl serde::Serializer for Serializer {
+ type Ok = Value;
+ type Error = Error;
+
+ type SerializeSeq = SerializeVec;
+ type SerializeTuple = SerializeVec;
+ type SerializeTupleStruct = SerializeVec;
+ type SerializeTupleVariant = SerializeTupleVariant;
+ type SerializeMap = SerializeMap;
+ type SerializeStruct = SerializeMap;
+ type SerializeStructVariant = SerializeStructVariant;
+
+ #[inline]
+ fn serialize_bool(self, value: bool) -> Result<Value, Error> {
+ Ok(Value::Bool(value))
+ }
+
+ #[inline]
+ fn serialize_i8(self, value: i8) -> Result<Value, Error> {
+ self.serialize_i64(i64::from(value))
+ }
+
+ #[inline]
+ fn serialize_i16(self, value: i16) -> Result<Value, Error> {
+ self.serialize_i64(i64::from(value))
+ }
+
+ #[inline]
+ fn serialize_i32(self, value: i32) -> Result<Value, Error> {
+ self.serialize_i64(i64::from(value))
+ }
+
+ #[inline]
+ fn serialize_i64(self, value: i64) -> Result<Value, Error> {
+ self.serialize_i128(i128::from(value))
+ }
+
+ fn serialize_i128(self, value: i128) -> Result<Value, Error> {
+ Ok(Value::Integer(value))
+ }
+
+ #[inline]
+ fn serialize_u8(self, value: u8) -> Result<Value, Error> {
+ self.serialize_u64(u64::from(value))
+ }
+
+ #[inline]
+ fn serialize_u16(self, value: u16) -> Result<Value, Error> {
+ self.serialize_u64(u64::from(value))
+ }
+
+ #[inline]
+ fn serialize_u32(self, value: u32) -> Result<Value, Error> {
+ self.serialize_u64(u64::from(value))
+ }
+
+ #[inline]
+ fn serialize_u64(self, value: u64) -> Result<Value, Error> {
+ Ok(Value::Integer(value.into()))
+ }
+
+ #[inline]
+ fn serialize_f32(self, value: f32) -> Result<Value, Error> {
+ self.serialize_f64(f64::from(value))
+ }
+
+ #[inline]
+ fn serialize_f64(self, value: f64) -> Result<Value, Error> {
+ Ok(Value::Float(value))
+ }
+
+ #[inline]
+ fn serialize_char(self, value: char) -> Result<Value, Error> {
+ let mut s = String::new();
+ s.push(value);
+ self.serialize_str(&s)
+ }
+
+ #[inline]
+ fn serialize_str(self, value: &str) -> Result<Value, Error> {
+ Ok(Value::Text(value.to_owned()))
+ }
+
+ fn serialize_bytes(self, value: &[u8]) -> Result<Value, Error> {
+ Ok(Value::Bytes(value.to_vec()))
+ }
+
+ #[inline]
+ fn serialize_unit(self) -> Result<Value, Error> {
+ Ok(Value::Null)
+ }
+
+ #[inline]
+ fn serialize_unit_struct(self, _name: &'static str) -> Result<Value, Error> {
+ self.serialize_unit()
+ }
+
+ #[inline]
+ fn serialize_unit_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ variant: &'static str,
+ ) -> Result<Value, Error> {
+ self.serialize_str(variant)
+ }
+
+ #[inline]
+ fn serialize_newtype_struct<T: ?Sized>(
+ self,
+ _name: &'static str,
+ value: &T,
+ ) -> Result<Value, Error>
+ where
+ T: Serialize,
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_newtype_variant<T: ?Sized>(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ variant: &'static str,
+ value: &T,
+ ) -> Result<Value, Error>
+ where
+ T: Serialize,
+ {
+ let mut values = BTreeMap::new();
+ values.insert(Value::from(variant.to_owned()), to_value(&value)?);
+ Ok(Value::Map(values))
+ }
+
+ #[inline]
+ fn serialize_none(self) -> Result<Value, Error> {
+ self.serialize_unit()
+ }
+
+ #[inline]
+ fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Value, Error>
+ where
+ T: Serialize,
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Error> {
+ Ok(SerializeVec {
+ vec: Vec::with_capacity(len.unwrap_or(0)),
+ })
+ }
+
+ fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Error> {
+ self.serialize_seq(Some(len))
+ }
+
+ fn serialize_tuple_struct(
+ self,
+ _name: &'static str,
+ len: usize,
+ ) -> Result<Self::SerializeTupleStruct, Error> {
+ self.serialize_tuple(len)
+ }
+
+ fn serialize_tuple_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ variant: &'static str,
+ len: usize,
+ ) -> Result<Self::SerializeTupleVariant, Error> {
+ Ok(SerializeTupleVariant {
+ name: String::from(variant),
+ vec: Vec::with_capacity(len),
+ })
+ }
+
+ fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Error> {
+ Ok(SerializeMap {
+ map: BTreeMap::new(),
+ next_key: None,
+ })
+ }
+
+ fn serialize_struct(
+ self,
+ _name: &'static str,
+ len: usize,
+ ) -> Result<Self::SerializeStruct, Error> {
+ self.serialize_map(Some(len))
+ }
+
+ fn serialize_struct_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ variant: &'static str,
+ _len: usize,
+ ) -> Result<Self::SerializeStructVariant, Error> {
+ Ok(SerializeStructVariant {
+ name: String::from(variant),
+ map: BTreeMap::new(),
+ })
+ }
+
+ #[inline]
+ fn is_human_readable(&self) -> bool {
+ false
+ }
+}
+
+pub struct SerializeVec {
+ vec: Vec<Value>,
+}
+
+pub struct SerializeTupleVariant {
+ name: String,
+ vec: Vec<Value>,
+}
+
+pub struct SerializeMap {
+ map: BTreeMap<Value, Value>,
+ next_key: Option<Value>,
+}
+
+pub struct SerializeStructVariant {
+ name: String,
+ map: BTreeMap<Value, Value>,
+}
+
+impl serde::ser::SerializeSeq for SerializeVec {
+ type Ok = Value;
+ type Error = Error;
+
+ fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+ where
+ T: Serialize,
+ {
+ self.vec.push(to_value(&value)?);
+ Ok(())
+ }
+
+ fn end(self) -> Result<Value, Error> {
+ Ok(Value::Array(self.vec))
+ }
+}
+
+impl serde::ser::SerializeTuple for SerializeVec {
+ type Ok = Value;
+ type Error = Error;
+
+ fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+ where
+ T: Serialize,
+ {
+ serde::ser::SerializeSeq::serialize_element(self, value)
+ }
+
+ fn end(self) -> Result<Value, Error> {
+ serde::ser::SerializeSeq::end(self)
+ }
+}
+
+impl serde::ser::SerializeTupleStruct for SerializeVec {
+ type Ok = Value;
+ type Error = Error;
+
+ fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+ where
+ T: Serialize,
+ {
+ serde::ser::SerializeSeq::serialize_element(self, value)
+ }
+
+ fn end(self) -> Result<Value, Error> {
+ serde::ser::SerializeSeq::end(self)
+ }
+}
+
+impl serde::ser::SerializeTupleVariant for SerializeTupleVariant {
+ type Ok = Value;
+ type Error = Error;
+
+ fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+ where
+ T: Serialize,
+ {
+ self.vec.push(to_value(&value)?);
+ Ok(())
+ }
+
+ fn end(self) -> Result<Value, Error> {
+ let mut object = BTreeMap::new();
+
+ object.insert(Value::from(self.name), Value::Array(self.vec));
+
+ Ok(Value::Map(object))
+ }
+}
+
+impl serde::ser::SerializeMap for SerializeMap {
+ type Ok = Value;
+ type Error = Error;
+
+ fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Error>
+ where
+ T: Serialize,
+ {
+ self.next_key = Some(to_value(&key)?);
+ Ok(())
+ }
+
+ fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+ where
+ T: Serialize,
+ {
+ let key = self.next_key.take();
+ // Panic because this indicates a bug in the program rather than an
+ // expected failure.
+ let key = key.expect("serialize_value called before serialize_key");
+ self.map.insert(key, to_value(&value)?);
+ Ok(())
+ }
+
+ fn end(self) -> Result<Value, Error> {
+ Ok(Value::Map(self.map))
+ }
+}
+
+impl serde::ser::SerializeStruct for SerializeMap {
+ type Ok = Value;
+ type Error = Error;
+
+ fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
+ where
+ T: Serialize,
+ {
+ serde::ser::SerializeMap::serialize_key(self, key)?;
+ serde::ser::SerializeMap::serialize_value(self, value)
+ }
+
+ fn end(self) -> Result<Value, Error> {
+ serde::ser::SerializeMap::end(self)
+ }
+}
+
+impl serde::ser::SerializeStructVariant for SerializeStructVariant {
+ type Ok = Value;
+ type Error = Error;
+
+ fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
+ where
+ T: Serialize,
+ {
+ self.map
+ .insert(Value::from(String::from(key)), to_value(&value)?);
+ Ok(())
+ }
+
+ fn end(self) -> Result<Value, Error> {
+ let mut object = BTreeMap::new();
+
+ object.insert(Value::from(self.name), Value::Map(self.map));
+
+ Ok(Value::Map(object))
+ }
+}
+
+/// Convert a `T` into `serde_cbor::Value` which is an enum that can represent
+/// any valid CBOR data.
+///
+/// ```rust
+/// extern crate serde;
+///
+/// #[macro_use]
+/// extern crate serde_derive;
+/// extern crate serde_cbor;
+///
+/// use std::error::Error;
+///
+/// #[derive(Serialize)]
+/// struct User {
+/// fingerprint: String,
+/// location: String,
+/// }
+///
+/// fn main() {
+/// let u = User {
+/// fingerprint: "0xF9BA143B95FF6D82".to_owned(),
+/// location: "Menlo Park, CA".to_owned(),
+/// };
+///
+/// let v = serde_cbor::value::to_value(u).unwrap();
+/// }
+/// ```
+#[allow(clippy::needless_pass_by_value)]
+// Taking by value is more friendly to iterator adapters, option and result
+pub fn to_value<T>(value: T) -> Result<Value, Error>
+where
+ T: Serialize,
+{
+ value.serialize(Serializer)
+}
diff --git a/third_party/rust/serde_cbor/src/write.rs b/third_party/rust/serde_cbor/src/write.rs
new file mode 100644
index 0000000000..94c326ef96
--- /dev/null
+++ b/third_party/rust/serde_cbor/src/write.rs
@@ -0,0 +1,175 @@
+#[cfg(feature = "alloc")]
+use alloc::vec::Vec;
+#[cfg(not(feature = "std"))]
+use core::fmt;
+#[cfg(feature = "std")]
+use std::io;
+
+use crate::error;
+
+#[cfg(not(feature = "unsealed_read_write"))]
+/// A sink for serialized CBOR.
+///
+/// This trait is similar to the [`Write`]() trait in the standard library,
+/// but has a smaller and more general API.
+///
+/// Any object implementing `std::io::Write`
+/// can be wrapped in an [`IoWrite`](../write/struct.IoWrite.html) that implements
+/// this trait for the underlying object.
+pub trait Write: private::Sealed {
+ /// The type of error returned when a write operation fails.
+ #[doc(hidden)]
+ type Error: Into<error::Error>;
+
+ /// Attempts to write an entire buffer into this write.
+ #[doc(hidden)]
+ fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>;
+}
+
+#[cfg(feature = "unsealed_read_write")]
+/// A sink for serialized CBOR.
+///
+/// This trait is similar to the [`Write`]() trait in the standard library,
+/// but has a smaller and more general API.
+///
+/// Any object implementing `std::io::Write`
+/// can be wrapped in an [`IoWrite`](../write/struct.IoWrite.html) that implements
+/// this trait for the underlying object.
+///
+/// This trait is sealed by default, enabling the `unsealed_read_write` feature removes this bound
+/// to allow objects outside of this crate to implement this trait.
+pub trait Write {
+ /// The type of error returned when a write operation fails.
+ type Error: Into<error::Error>;
+
+ /// Attempts to write an entire buffer into this write.
+ fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>;
+}
+
+#[cfg(not(feature = "unsealed_read_write"))]
+mod private {
+ pub trait Sealed {}
+}
+
+impl<W> Write for &mut W
+where
+ W: Write,
+{
+ type Error = W::Error;
+
+ fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
+ (*self).write_all(buf)
+ }
+}
+
+#[cfg(not(feature = "unsealed_read_write"))]
+impl<W> private::Sealed for &mut W where W: Write {}
+
+#[cfg(feature = "std")]
+/// A wrapper for types that implement
+/// [`std::io::Write`](https://doc.rust-lang.org/std/io/trait.Write.html) to implement the local
+/// [`Write`](trait.Write.html) trait.
+#[derive(Debug)]
+pub struct IoWrite<W>(W);
+
+#[cfg(feature = "std")]
+impl<W: io::Write> IoWrite<W> {
+ /// Wraps an `io::Write` writer to make it compatible with [`Write`](trait.Write.html)
+ pub fn new(w: W) -> IoWrite<W> {
+ IoWrite(w)
+ }
+}
+
+#[cfg(feature = "std")]
+impl<W: io::Write> Write for IoWrite<W> {
+ type Error = io::Error;
+
+ fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
+ self.0.write_all(buf)
+ }
+}
+
+#[cfg(all(feature = "std", not(feature = "unsealed_read_write")))]
+impl<W> private::Sealed for IoWrite<W> where W: io::Write {}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl Write for Vec<u8> {
+ type Error = error::Error;
+
+ fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
+ self.extend_from_slice(buf);
+ Ok(())
+ }
+}
+
+#[cfg(all(
+ any(feature = "std", feature = "alloc"),
+ not(feature = "unsealed_read_write")
+))]
+impl private::Sealed for Vec<u8> {}
+
+#[cfg(not(feature = "std"))]
+#[derive(Debug)]
+pub struct FmtWrite<'a, W: Write>(&'a mut W);
+
+#[cfg(not(feature = "std"))]
+impl<'a, W: Write> FmtWrite<'a, W> {
+ /// Wraps an `fmt::Write` writer to make it compatible with [`Write`](trait.Write.html)
+ pub fn new(w: &'a mut W) -> FmtWrite<'a, W> {
+ FmtWrite(w)
+ }
+}
+
+#[cfg(not(feature = "std"))]
+impl<'a, W: Write> fmt::Write for FmtWrite<'a, W> {
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ self.0.write_all(s.as_bytes()).map_err(|_| fmt::Error)
+ }
+}
+
+#[cfg(all(not(feature = "std"), not(feature = "unsealed_read_write")))]
+impl<'a, W> private::Sealed for FmtWrite<'a, W> where W: Write {}
+
+/// Implements [`Write`](trait.Write.html) for mutable byte slices (`&mut [u8]`).
+///
+/// Returns an error if the value to serialize is too large to fit in the slice.
+#[derive(Debug)]
+pub struct SliceWrite<'a> {
+ slice: &'a mut [u8],
+ index: usize,
+}
+
+impl<'a> SliceWrite<'a> {
+ /// Wraps a mutable slice so it can be used as a `Write`.
+ pub fn new(slice: &'a mut [u8]) -> SliceWrite<'a> {
+ SliceWrite { slice, index: 0 }
+ }
+
+ /// Returns the number of bytes written to the underlying slice.
+ pub fn bytes_written(&self) -> usize {
+ self.index
+ }
+
+ /// Returns the underlying slice.
+ pub fn into_inner(self) -> &'a mut [u8] {
+ self.slice
+ }
+}
+
+impl<'a> Write for SliceWrite<'a> {
+ type Error = error::Error;
+
+ fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
+ if self.slice.len() - self.index < buf.len() {
+ // This buffer will not fit in our slice
+ return Err(error::Error::scratch_too_small(self.index as u64));
+ }
+ let end = self.index + buf.len();
+ self.slice[self.index..end].copy_from_slice(buf);
+ self.index = end;
+ Ok(())
+ }
+}
+
+#[cfg(not(feature = "unsealed_read_write"))]
+impl<'a> private::Sealed for SliceWrite<'a> {}
diff --git a/third_party/rust/serde_cbor/tests/bennofs.rs b/third_party/rust/serde_cbor/tests/bennofs.rs
new file mode 100644
index 0000000000..1b289f40d4
--- /dev/null
+++ b/third_party/rust/serde_cbor/tests/bennofs.rs
@@ -0,0 +1,60 @@
+#[macro_use]
+extern crate serde_derive;
+
+use serde::Serialize;
+use serde_cbor::ser::SliceWrite;
+use serde_cbor::{self, Serializer};
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+struct Example {
+ foo: Foo,
+ payload: u8,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+struct Foo {
+ x: u8,
+ color: Color,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+enum Color {
+ Red,
+ Blue,
+ Yellow(u8),
+}
+
+const EXAMPLE: Example = Example {
+ foo: Foo {
+ x: 0xAA,
+ color: Color::Yellow(40),
+ },
+ payload: 0xCC,
+};
+
+#[cfg(feature = "std")]
+mod std_tests {
+ use super::*;
+
+ #[test]
+ fn test() {
+ let serialized = serde_cbor::ser::to_vec_packed(&EXAMPLE).expect("bennofs 1");
+ println!("{:?}", serialized);
+ let deserialized: Example = serde_cbor::from_slice(&serialized).expect("bennofs 2");
+ assert_eq!(EXAMPLE, deserialized);
+ }
+}
+
+#[test]
+fn test() {
+ let mut slice = [0u8; 64];
+ let writer = SliceWrite::new(&mut slice);
+ let mut serializer = Serializer::new(writer).packed_format();
+ EXAMPLE.serialize(&mut serializer).unwrap();
+ let writer = serializer.into_inner();
+ let end = writer.bytes_written();
+ let slice = writer.into_inner();
+ let deserialized: Example =
+ serde_cbor::de::from_slice_with_scratch(&slice[..end], &mut []).unwrap();
+ assert_eq!(EXAMPLE, deserialized);
+}
diff --git a/third_party/rust/serde_cbor/tests/canonical.rs b/third_party/rust/serde_cbor/tests/canonical.rs
new file mode 100644
index 0000000000..438e29e7d4
--- /dev/null
+++ b/third_party/rust/serde_cbor/tests/canonical.rs
@@ -0,0 +1,104 @@
+#[cfg(feature = "std")]
+mod std_tests {
+ use serde_cbor::value::Value;
+
+ #[test]
+ fn integer_canonical_sort_order() {
+ let expected = [
+ 0,
+ 23,
+ 24,
+ 255,
+ 256,
+ 65535,
+ 65536,
+ 4294967295,
+ -1,
+ -24,
+ -25,
+ -256,
+ -257,
+ -65536,
+ -65537,
+ -4294967296,
+ ]
+ .iter()
+ .map(|i| Value::Integer(*i))
+ .collect::<Vec<_>>();
+
+ let mut sorted = expected.clone();
+ sorted.sort();
+
+ assert_eq!(expected, sorted);
+ }
+
+ #[test]
+ fn string_canonical_sort_order() {
+ let expected = ["", "a", "b", "aa"]
+ .iter()
+ .map(|s| Value::Text(s.to_string()))
+ .collect::<Vec<_>>();
+
+ let mut sorted = expected.clone();
+ sorted.sort();
+
+ assert_eq!(expected, sorted);
+ }
+
+ #[test]
+ fn bytes_canonical_sort_order() {
+ let expected = vec![vec![], vec![0u8], vec![1u8], vec![0u8, 0u8]]
+ .into_iter()
+ .map(|v| Value::Bytes(v))
+ .collect::<Vec<_>>();
+
+ let mut sorted = expected.clone();
+ sorted.sort();
+
+ assert_eq!(expected, sorted);
+ }
+
+ #[test]
+ fn simple_data_canonical_sort_order() {
+ let expected = vec![Value::Bool(false), Value::Bool(true), Value::Null];
+
+ let mut sorted = expected.clone();
+ sorted.sort();
+
+ assert_eq!(expected, sorted);
+ }
+
+ #[test]
+ fn major_type_canonical_sort_order() {
+ let expected = vec![
+ Value::Integer(0),
+ Value::Integer(-1),
+ Value::Bytes(vec![]),
+ Value::Text("".to_string()),
+ Value::Null,
+ ];
+
+ let mut sorted = expected.clone();
+ sorted.sort();
+
+ assert_eq!(expected, sorted);
+ }
+
+ #[test]
+ fn test_rfc_example() {
+ // See: https://tools.ietf.org/html/draft-ietf-cbor-7049bis-04#section-4.10
+ let expected = vec![
+ Value::Integer(10),
+ Value::Integer(100),
+ Value::Integer(-1),
+ Value::Text("z".to_owned()),
+ Value::Text("aa".to_owned()),
+ Value::Array(vec![Value::Integer(100)]),
+ Value::Array(vec![Value::Integer(-1)]),
+ Value::Bool(false),
+ ];
+ let mut sorted = expected.clone();
+ sorted.sort();
+ assert_eq!(expected, sorted);
+ }
+}
diff --git a/third_party/rust/serde_cbor/tests/crash.cbor b/third_party/rust/serde_cbor/tests/crash.cbor
new file mode 100644
index 0000000000..a3bc785ca3
--- /dev/null
+++ b/third_party/rust/serde_cbor/tests/crash.cbor
Binary files differ
diff --git a/third_party/rust/serde_cbor/tests/de.rs b/third_party/rust/serde_cbor/tests/de.rs
new file mode 100644
index 0000000000..01d7914502
--- /dev/null
+++ b/third_party/rust/serde_cbor/tests/de.rs
@@ -0,0 +1,747 @@
+#[macro_use]
+extern crate serde_derive;
+
+use serde_cbor;
+use serde_cbor::de;
+
+#[test]
+fn test_str() {
+ let s: &str =
+ de::from_slice_with_scratch(&[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72], &mut []).unwrap();
+ assert_eq!(s, "foobar");
+}
+
+#[test]
+fn test_bytes() {
+ let s: &[u8] =
+ de::from_slice_with_scratch(&[0x46, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72], &mut []).unwrap();
+ assert_eq!(s, b"foobar");
+}
+
+#[test]
+fn test_int() {
+ let num: i64 = de::from_slice_with_scratch(&[0x39, 0x07, 0xde], &mut []).unwrap();
+ assert_eq!(num, -2015);
+}
+
+#[test]
+fn test_float() {
+ let float: f64 = de::from_slice_with_scratch(b"\xfa\x47\xc3\x50\x00", &mut []).unwrap();
+ assert_eq!(float, 100000.0);
+}
+
+#[test]
+fn test_indefinite_object() {
+ #[derive(Debug, Deserialize, PartialEq)]
+ struct Foo {
+ a: u64,
+ b: [u64; 2],
+ }
+ let expected = Foo { a: 1, b: [2, 3] };
+ let actual: Foo =
+ de::from_slice_with_scratch(b"\xbfaa\x01ab\x9f\x02\x03\xff\xff", &mut []).unwrap();
+ assert_eq!(expected, actual);
+}
+
+#[cfg(feature = "std")]
+mod std_tests {
+ use std::collections::BTreeMap;
+
+ use serde::de as serde_de;
+ use serde_cbor::value::Value;
+ use serde_cbor::{de, error, to_vec, Deserializer};
+
+ #[test]
+ fn test_string1() {
+ let value: error::Result<Value> =
+ de::from_slice(&[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]);
+ assert_eq!(value.unwrap(), Value::Text("foobar".to_owned()));
+ }
+
+ #[test]
+ fn test_string2() {
+ let value: error::Result<Value> = de::from_slice(&[
+ 0x71, 0x49, 0x20, 0x6d, 0x65, 0x74, 0x20, 0x61, 0x20, 0x74, 0x72, 0x61, 0x76, 0x65,
+ 0x6c, 0x6c, 0x65, 0x72,
+ ]);
+ assert_eq!(value.unwrap(), Value::Text("I met a traveller".to_owned()));
+ }
+
+ #[test]
+ fn test_string3() {
+ let slice = b"\x78\x2fI met a traveller from an antique land who said";
+ let value: error::Result<Value> = de::from_slice(slice);
+ assert_eq!(
+ value.unwrap(),
+ Value::Text("I met a traveller from an antique land who said".to_owned())
+ );
+ }
+
+ #[test]
+ fn test_byte_string() {
+ let value: error::Result<Value> =
+ de::from_slice(&[0x46, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]);
+ assert_eq!(value.unwrap(), Value::Bytes(b"foobar".to_vec()));
+ }
+
+ #[test]
+ fn test_numbers1() {
+ let value: error::Result<Value> = de::from_slice(&[0x00]);
+ assert_eq!(value.unwrap(), Value::Integer(0));
+ }
+
+ #[test]
+ fn test_numbers2() {
+ let value: error::Result<Value> = de::from_slice(&[0x1a, 0x00, 0xbc, 0x61, 0x4e]);
+ assert_eq!(value.unwrap(), Value::Integer(12345678));
+ }
+
+ #[test]
+ fn test_numbers3() {
+ let value: error::Result<Value> = de::from_slice(&[0x39, 0x07, 0xde]);
+ assert_eq!(value.unwrap(), Value::Integer(-2015));
+ }
+
+ #[test]
+ fn test_bool() {
+ let value: error::Result<Value> = de::from_slice(b"\xf4");
+ assert_eq!(value.unwrap(), Value::Bool(false));
+ }
+
+ #[test]
+ fn test_trailing_bytes() {
+ let value: error::Result<Value> = de::from_slice(b"\xf4trailing");
+ assert!(value.is_err());
+ }
+
+ #[test]
+ fn test_list1() {
+ let value: error::Result<Value> = de::from_slice(b"\x83\x01\x02\x03");
+ assert_eq!(
+ value.unwrap(),
+ Value::Array(vec![
+ Value::Integer(1),
+ Value::Integer(2),
+ Value::Integer(3)
+ ])
+ );
+ }
+
+ #[test]
+ fn test_list2() {
+ let value: error::Result<Value> = de::from_slice(b"\x82\x01\x82\x02\x81\x03");
+ assert_eq!(
+ value.unwrap(),
+ Value::Array(vec![
+ Value::Integer(1),
+ Value::Array(vec![
+ Value::Integer(2),
+ Value::Array(vec![Value::Integer(3)])
+ ])
+ ])
+ );
+ }
+
+ #[test]
+ fn test_object() {
+ let value: error::Result<Value> = de::from_slice(b"\xa5aaaAabaBacaCadaDaeaE");
+ let mut object = BTreeMap::new();
+ object.insert(Value::Text("a".to_owned()), Value::Text("A".to_owned()));
+ object.insert(Value::Text("b".to_owned()), Value::Text("B".to_owned()));
+ object.insert(Value::Text("c".to_owned()), Value::Text("C".to_owned()));
+ object.insert(Value::Text("d".to_owned()), Value::Text("D".to_owned()));
+ object.insert(Value::Text("e".to_owned()), Value::Text("E".to_owned()));
+ assert_eq!(value.unwrap(), Value::Map(object));
+ }
+
+ #[test]
+ fn test_indefinite_object() {
+ let value: error::Result<Value> = de::from_slice(b"\xbfaa\x01ab\x9f\x02\x03\xff\xff");
+ let mut object = BTreeMap::new();
+ object.insert(Value::Text("a".to_owned()), Value::Integer(1));
+ object.insert(
+ Value::Text("b".to_owned()),
+ Value::Array(vec![Value::Integer(2), Value::Integer(3)]),
+ );
+ assert_eq!(value.unwrap(), Value::Map(object));
+ }
+
+ #[test]
+ fn test_indefinite_list() {
+ let value: error::Result<Value> = de::from_slice(b"\x9f\x01\x02\x03\xff");
+ assert_eq!(
+ value.unwrap(),
+ Value::Array(vec![
+ Value::Integer(1),
+ Value::Integer(2),
+ Value::Integer(3)
+ ])
+ );
+ }
+
+ #[test]
+ fn test_indefinite_string() {
+ let value: error::Result<Value> =
+ de::from_slice(b"\x7f\x65Mary \x64Had \x62a \x67Little \x60\x64Lamb\xff");
+ assert_eq!(
+ value.unwrap(),
+ Value::Text("Mary Had a Little Lamb".to_owned())
+ );
+ }
+
+ #[test]
+ fn test_indefinite_byte_string() {
+ let value: error::Result<Value> = de::from_slice(b"\x5f\x42\x01\x23\x42\x45\x67\xff");
+ assert_eq!(value.unwrap(), Value::Bytes(b"\x01#Eg".to_vec()));
+ }
+
+ #[test]
+ fn test_multiple_indefinite_strings() {
+ let input = b"\x82\x7f\x65Mary \x64Had \x62a \x67Little \x60\x64Lamb\xff\x5f\x42\x01\x23\x42\x45\x67\xff";
+ _test_multiple_indefinite_strings(de::from_slice(input));
+ _test_multiple_indefinite_strings(de::from_mut_slice(input.to_vec().as_mut()));
+ let mut buf = [0u8; 64];
+ _test_multiple_indefinite_strings(de::from_slice_with_scratch(input, &mut buf));
+ }
+ fn _test_multiple_indefinite_strings(value: error::Result<Value>) {
+ // This assures that buffer rewinding in infinite buffers works as intended.
+ assert_eq!(
+ value.unwrap(),
+ Value::Array(vec![
+ Value::Text("Mary Had a Little Lamb".to_owned()),
+ Value::Bytes(b"\x01#Eg".to_vec())
+ ])
+ );
+ }
+
+ #[test]
+ fn test_float() {
+ let value: error::Result<Value> = de::from_slice(b"\xfa\x47\xc3\x50\x00");
+ assert_eq!(value.unwrap(), Value::Float(100000.0));
+ }
+
+ #[test]
+ fn test_self_describing() {
+ let value: error::Result<Value> =
+ de::from_slice(&[0xd9, 0xd9, 0xf7, 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]);
+ let expected = Value::Text("foobar".to_owned());
+ let strip_tags = |x: Value| {
+ if let Value::Tag(_, inner) = x {
+ *inner
+ } else {
+ x
+ }
+ };
+ assert_eq!(strip_tags(value.unwrap()), expected);
+ }
+
+ #[test]
+ fn test_f16() {
+ let mut x: Value = de::from_slice(&[0xf9, 0x41, 0x00]).unwrap();
+ assert_eq!(x, Value::Float(2.5));
+ x = de::from_slice(&[0xf9, 0x41, 0x90]).unwrap();
+ assert_eq!(x, Value::Float(2.78125));
+ x = de::from_slice(&[0xf9, 0x50, 0x90]).unwrap();
+ assert_eq!(x, Value::Float(36.5));
+ x = de::from_slice(&[0xf9, 0xd0, 0x90]).unwrap();
+ assert_eq!(x, Value::Float(-36.5));
+ }
+
+ #[test]
+ fn test_crazy_list() {
+ let slice = b"\x88\x1b\x00\x00\x00\x1c\xbe\x99\x1d\xc7\x3b\x00\x7a\xcf\x51\xdc\x51\x70\xdb\x3a\x1b\x3a\x06\xdd\xf5\xf6\xf7\xfb\x41\x76\x5e\xb1\xf8\x00\x00\x00\xf9\x7c\x00";
+ let value: Vec<Value> = de::from_slice(slice).unwrap();
+ assert_eq!(
+ value,
+ vec![
+ Value::Integer(123456789959),
+ Value::Integer(-34567897654325468),
+ Value::Integer(-456787678),
+ Value::Bool(true),
+ Value::Null,
+ Value::Null,
+ Value::Float(23456543.5),
+ Value::Float(::std::f64::INFINITY)
+ ]
+ );
+ }
+
+ #[test]
+ fn test_nan() {
+ let value: f64 = de::from_slice(b"\xf9\x7e\x00").unwrap();
+ assert!(value.is_nan());
+ }
+
+ #[test]
+ fn test_32f16() {
+ let value: f32 = de::from_slice(b"\xf9\x50\x00").unwrap();
+ assert_eq!(value, 32.0f32);
+ }
+
+ #[test]
+ // The file was reported as not working by user kie0tauB
+ // but it parses to a cbor value.
+ fn test_kietaub_file() {
+ let file = include_bytes!("kietaub.cbor");
+ let value_result: error::Result<Value> = de::from_slice(file);
+ value_result.unwrap();
+ }
+
+ #[test]
+ fn test_option_roundtrip() {
+ let obj1 = Some(10u32);
+
+ let v = to_vec(&obj1).unwrap();
+ let obj2: Result<Option<u32>, _> = serde_cbor::de::from_reader(&v[..]);
+ println!("{:?}", obj2);
+
+ assert_eq!(obj1, obj2.unwrap());
+ }
+
+ #[test]
+ fn test_option_none_roundtrip() {
+ let obj1 = None;
+
+ let v = to_vec(&obj1).unwrap();
+ println!("{:?}", v);
+ let obj2: Result<Option<u32>, _> = serde_cbor::de::from_reader(&v[..]);
+
+ assert_eq!(obj1, obj2.unwrap());
+ }
+
+ #[test]
+ fn test_variable_length_map() {
+ let slice = b"\xbf\x67\x6d\x65\x73\x73\x61\x67\x65\x64\x70\x6f\x6e\x67\xff";
+ let value: Value = de::from_slice(slice).unwrap();
+ let mut map = BTreeMap::new();
+ map.insert(
+ Value::Text("message".to_string()),
+ Value::Text("pong".to_string()),
+ );
+ assert_eq!(value, Value::Map(map))
+ }
+
+ #[test]
+ fn test_object_determinism_roundtrip() {
+ let expected = b"\xa2aa\x01ab\x82\x02\x03";
+
+ // 0.1% chance of not catching failure
+ for _ in 0..10 {
+ assert_eq!(
+ &to_vec(&de::from_slice::<Value>(expected).unwrap()).unwrap(),
+ expected
+ );
+ }
+ }
+
+ #[test]
+ fn stream_deserializer() {
+ let slice = b"\x01\x66foobar";
+ let mut it = Deserializer::from_slice(slice).into_iter::<Value>();
+ assert_eq!(Value::Integer(1), it.next().unwrap().unwrap());
+ assert_eq!(
+ Value::Text("foobar".to_string()),
+ it.next().unwrap().unwrap()
+ );
+ assert!(it.next().is_none());
+ }
+
+ #[test]
+ fn stream_deserializer_eof() {
+ let slice = b"\x01\x66foob";
+ let mut it = Deserializer::from_slice(slice).into_iter::<Value>();
+ assert_eq!(Value::Integer(1), it.next().unwrap().unwrap());
+ assert!(it.next().unwrap().unwrap_err().is_eof());
+ }
+
+ #[test]
+ fn stream_deserializer_eof_in_indefinite() {
+ let slice = b"\x7f\x65Mary \x64Had \x62a \x60\x67Little \x60\x64Lamb\xff";
+ let indices: &[usize] = &[
+ 2, // announcement but no data
+ 10, // mid-buffer EOF
+ 12, // neither new element nor end marker
+ ];
+ for end_of_slice in indices {
+ let mut it = Deserializer::from_slice(&slice[..*end_of_slice]).into_iter::<Value>();
+ assert!(it.next().unwrap().unwrap_err().is_eof());
+
+ let mut mutcopy = slice[..*end_of_slice].to_vec();
+ let mut it = Deserializer::from_mut_slice(mutcopy.as_mut()).into_iter::<Value>();
+ assert!(it.next().unwrap().unwrap_err().is_eof());
+
+ let mut buf = [0u8; 64];
+ let mut it = Deserializer::from_slice_with_scratch(&slice[..*end_of_slice], &mut buf)
+ .into_iter::<Value>();
+ assert!(it.next().unwrap().unwrap_err().is_eof());
+ }
+ }
+
+ #[test]
+ fn crash() {
+ let file = include_bytes!("crash.cbor");
+ let value_result: error::Result<Value> = de::from_slice(file);
+ assert_eq!(
+ value_result.unwrap_err().classify(),
+ serde_cbor::error::Category::Syntax
+ );
+ }
+
+ fn from_slice_stream<'a, T>(slice: &'a [u8]) -> error::Result<(&'a [u8], T)>
+ where
+ T: serde_de::Deserialize<'a>,
+ {
+ let mut deserializer = Deserializer::from_slice(slice);
+ let value = serde_de::Deserialize::deserialize(&mut deserializer)?;
+ let rest = &slice[deserializer.byte_offset()..];
+
+ Ok((rest, value))
+ }
+
+ #[test]
+ fn test_slice_offset() {
+ let v: Vec<u8> = vec![
+ 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72,
+ ];
+ let (rest, value): (&[u8], String) = from_slice_stream(&v[..]).unwrap();
+ assert_eq!(value, "foobar");
+ assert_eq!(rest, &[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]);
+ let (rest, value): (&[u8], String) = from_slice_stream(rest).unwrap();
+ assert_eq!(value, "foobar");
+ assert_eq!(rest, &[]);
+ }
+
+ #[derive(Debug, Copy, Clone)]
+ struct Options {
+ standard: bool,
+ legacy: bool,
+ packed: bool,
+ named: bool,
+ }
+
+ impl Default for Options {
+ fn default() -> Self {
+ Options {
+ standard: true,
+ legacy: true,
+ packed: true,
+ named: true,
+ }
+ }
+ }
+
+ impl Options {
+ fn no_standard(self) -> Self {
+ Options {
+ standard: false,
+ ..self
+ }
+ }
+
+ fn no_legacy(self) -> Self {
+ Options {
+ legacy: false,
+ ..self
+ }
+ }
+
+ fn no_packed(self) -> Self {
+ Options {
+ packed: false,
+ ..self
+ }
+ }
+
+ fn no_named(self) -> Self {
+ Options {
+ named: false,
+ ..self
+ }
+ }
+ }
+
+ fn from_slice_stream_options<'a, T>(
+ slice: &'a [u8],
+ options: Options,
+ ) -> error::Result<(&'a [u8], T)>
+ where
+ T: serde_de::Deserialize<'a>,
+ {
+ let deserializer = Deserializer::from_slice(slice);
+ let deserializer = if !options.packed {
+ deserializer.disable_packed_format()
+ } else {
+ deserializer
+ };
+ let deserializer = if !options.named {
+ deserializer.disable_named_format()
+ } else {
+ deserializer
+ };
+ let deserializer = if !options.standard {
+ deserializer.disable_standard_enums()
+ } else {
+ deserializer
+ };
+ let mut deserializer = if !options.legacy {
+ deserializer.disable_legacy_enums()
+ } else {
+ deserializer
+ };
+ let value = serde_de::Deserialize::deserialize(&mut deserializer)?;
+ let rest = &slice[deserializer.byte_offset()..];
+
+ Ok((rest, value))
+ }
+
+ #[test]
+ fn test_deserializer_enums() {
+ #[derive(Debug, PartialEq, Deserialize)]
+ enum Enum {
+ Unit,
+ NewType(i32),
+ Tuple(String, bool),
+ Struct { x: i32, y: i32 },
+ }
+
+ // This is the format used in serde >= 0.10
+ //
+ // Serialization of Enum::NewType(10)
+ let v: Vec<u8> = vec![
+ 0xa1, // map 1pair
+ 0x67, 0x4e, 0x65, 0x77, 0x54, 0x79, 0x70, 0x65, // utf8 string: NewType
+ 0x1a, // u32
+ 0x00, 0x00, 0x00, 0x0a, // 10 (dec)
+ ];
+ let (_rest, value): (&[u8], Enum) = from_slice_stream(&v[..]).unwrap();
+ assert_eq!(value, Enum::NewType(10));
+ let (_rest, value): (&[u8], Enum) =
+ from_slice_stream_options(&v[..], Options::default().no_legacy()).unwrap();
+ assert_eq!(value, Enum::NewType(10));
+ let value: error::Result<(&[u8], Enum)> =
+ from_slice_stream_options(&v[..], Options::default().no_standard());
+ assert_eq!(
+ value.unwrap_err().classify(),
+ serde_cbor::error::Category::Syntax
+ );
+ let value: error::Result<(&[u8], Enum)> =
+ from_slice_stream_options(&v[..], Options::default().no_standard().no_legacy());
+ assert_eq!(
+ value.unwrap_err().classify(),
+ serde_cbor::error::Category::Syntax
+ );
+ // Serialization of Enum::Unit
+ let v: Vec<u8> = vec![
+ 0x64, 0x55, 0x6e, 0x69, 0x74, // utf8 string: Unit
+ ];
+ let (_rest, value): (&[u8], Enum) = from_slice_stream(&v[..]).unwrap();
+ assert_eq!(value, Enum::Unit);
+ let (_rest, value): (&[u8], Enum) =
+ from_slice_stream_options(&v[..], Options::default().no_legacy()).unwrap();
+ assert_eq!(value, Enum::Unit);
+ let (_rest, value): (&[u8], Enum) =
+ from_slice_stream_options(&v[..], Options::default().no_standard()).unwrap();
+ assert_eq!(value, Enum::Unit);
+ let value: error::Result<(&[u8], Enum)> =
+ from_slice_stream_options(&v[..], Options::default().no_legacy().no_standard());
+ assert_eq!(
+ value.unwrap_err().classify(),
+ serde_cbor::error::Category::Syntax
+ );
+
+ // This is the format used in serde <= 0.9
+ let v: Vec<u8> = vec![
+ 0x82, // array 2 items
+ 0x67, 0x4e, 0x65, 0x77, 0x54, 0x79, 0x70, 0x65, // utf8 string: NewType
+ 0x1a, // u32
+ 0x00, 0x00, 0x00, 0x0a, // 10 (dec)
+ ];
+ let (_rest, value): (&[u8], Enum) = from_slice_stream(&v[..]).unwrap();
+ assert_eq!(value, Enum::NewType(10));
+ let value: error::Result<(&[u8], Enum)> =
+ from_slice_stream_options(&v[..], Options::default().no_legacy());
+ assert_eq!(
+ value.unwrap_err().classify(),
+ serde_cbor::error::Category::Syntax
+ );
+ let value: error::Result<(&[u8], Enum)> =
+ from_slice_stream_options(&v[..], Options::default().no_standard());
+ assert_eq!(value.unwrap().1, Enum::NewType(10));
+ let value: error::Result<(&[u8], Enum)> =
+ from_slice_stream_options(&v[..], Options::default().no_standard().no_legacy());
+ assert_eq!(
+ value.unwrap_err().classify(),
+ serde_cbor::error::Category::Syntax
+ );
+ }
+
+ #[test]
+ fn test_packed_deserialization() {
+ #[derive(Debug, PartialEq, Deserialize)]
+ struct User {
+ user_id: u32,
+ password_hash: [u8; 4],
+ }
+
+ // unpacked
+ let v: Vec<u8> = vec![
+ 0xa2, // map 2pair
+ 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, // utf8 string: user_id
+ 0x0a, // integer: 10
+ // utf8 string: password_hash
+ 0x6d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68,
+ 0x84, 0x01, 0x02, 0x03, 0x04, // 4 byte array [1, 2, 3, 4]
+ ];
+
+ let (_rest, value): (&[u8], User) = from_slice_stream(&v[..]).unwrap();
+ assert_eq!(
+ value,
+ User {
+ user_id: 10,
+ password_hash: [1, 2, 3, 4],
+ }
+ );
+ let (_rest, value): (&[u8], User) =
+ from_slice_stream_options(&v[..], Options::default().no_packed()).unwrap();
+ assert_eq!(
+ value,
+ User {
+ user_id: 10,
+ password_hash: [1, 2, 3, 4],
+ }
+ );
+ let value: error::Result<(&[u8], User)> =
+ from_slice_stream_options(&v[..], Options::default().no_named());
+ assert_eq!(
+ value.unwrap_err().classify(),
+ serde_cbor::error::Category::Syntax
+ );
+
+ // unpacked - indefinite length
+ let v: Vec<u8> = vec![
+ 0xbf, // map to be followed by a break
+ 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, // utf8 string: user_id
+ 0x0a, // integer: 10
+ // utf8 string: password_hash
+ 0x6d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68,
+ 0x84, 0x01, 0x02, 0x03, 0x04, // 4 byte array [1, 2, 3, 4]
+ 0xff, // break
+ ];
+
+ let (_rest, value): (&[u8], User) = from_slice_stream(&v[..]).unwrap();
+ assert_eq!(
+ value,
+ User {
+ user_id: 10,
+ password_hash: [1, 2, 3, 4],
+ }
+ );
+ let (_rest, value): (&[u8], User) =
+ from_slice_stream_options(&v[..], Options::default().no_packed()).unwrap();
+ assert_eq!(
+ value,
+ User {
+ user_id: 10,
+ password_hash: [1, 2, 3, 4],
+ }
+ );
+ let value: error::Result<(&[u8], User)> =
+ from_slice_stream_options(&v[..], Options::default().no_named());
+ assert_eq!(
+ value.unwrap_err().classify(),
+ serde_cbor::error::Category::Syntax
+ );
+
+ // packed
+ let v: Vec<u8> = vec![
+ 0xa2, // map 2pair
+ 0x00, // index 0
+ 0x0a, // integer: 10
+ 0x01, // index 1
+ 0x84, 0x01, 0x02, 0x03, 0x04, // 4 byte array [1, 2, 3, 4]
+ ];
+
+ let (_rest, value): (&[u8], User) = from_slice_stream(&v[..]).unwrap();
+ assert_eq!(
+ value,
+ User {
+ user_id: 10,
+ password_hash: [1, 2, 3, 4],
+ }
+ );
+ let (_rest, value): (&[u8], User) =
+ from_slice_stream_options(&v[..], Options::default().no_named()).unwrap();
+ assert_eq!(
+ value,
+ User {
+ user_id: 10,
+ password_hash: [1, 2, 3, 4],
+ }
+ );
+ let value: error::Result<(&[u8], User)> =
+ from_slice_stream_options(&v[..], Options::default().no_packed());
+ assert_eq!(
+ value.unwrap_err().classify(),
+ serde_cbor::error::Category::Syntax
+ );
+
+ // packed - indefinite length
+ let v: Vec<u8> = vec![
+ 0xbf, // map, to be followed by a break
+ 0x00, // index 0
+ 0x0a, // integer: 10
+ 0x01, // index 1
+ 0x84, 0x01, 0x02, 0x03, 0x04, // 4 byte array [1, 2, 3, 4]
+ 0xff, // break
+ ];
+
+ let (_rest, value): (&[u8], User) = from_slice_stream(&v[..]).unwrap();
+ assert_eq!(
+ value,
+ User {
+ user_id: 10,
+ password_hash: [1, 2, 3, 4],
+ }
+ );
+ let (_rest, value): (&[u8], User) =
+ from_slice_stream_options(&v[..], Options::default().no_named()).unwrap();
+ assert_eq!(
+ value,
+ User {
+ user_id: 10,
+ password_hash: [1, 2, 3, 4],
+ }
+ );
+ let value: error::Result<(&[u8], User)> =
+ from_slice_stream_options(&v[..], Options::default().no_packed());
+ assert_eq!(
+ value.unwrap_err().classify(),
+ serde_cbor::error::Category::Syntax
+ );
+ }
+
+ use serde_cbor::{de::from_slice, ser::to_vec_packed};
+ use std::net::{IpAddr, Ipv4Addr};
+ #[test]
+ fn test_ipaddr_deserialization() {
+ let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
+ let buf = to_vec_packed(&ip).unwrap();
+ let deserialized_ip = from_slice::<IpAddr>(&buf).unwrap();
+ assert_eq!(ip, deserialized_ip);
+
+ let buf = to_vec(&ip).unwrap();
+ let deserialized_ip = from_slice::<IpAddr>(&buf).unwrap();
+ assert_eq!(ip, deserialized_ip);
+ }
+
+ #[test]
+ fn attempt_stack_overflow() {
+ // Create a tag 17, followed by 999 more tag 17:
+ // 17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(...
+ // This causes deep recursion in the decoder and may
+ // exhaust the stack and therfore result in a stack overflow.
+ let input = vec![0xd1; 1000];
+ let err = serde_cbor::from_slice::<serde_cbor::Value>(&input).expect_err("recursion limit");
+ assert!(err.is_syntax());
+ }
+}
diff --git a/third_party/rust/serde_cbor/tests/enum.rs b/third_party/rust/serde_cbor/tests/enum.rs
new file mode 100644
index 0000000000..630500d6b5
--- /dev/null
+++ b/third_party/rust/serde_cbor/tests/enum.rs
@@ -0,0 +1,236 @@
+use serde::Serialize;
+use serde_cbor;
+use serde_cbor::ser::{Serializer, SliceWrite};
+
+#[macro_use]
+extern crate serde_derive;
+
+#[test]
+fn test_simple_data_enum_roundtrip() {
+ #[derive(Debug, Serialize, Deserialize, PartialEq)]
+ enum DataEnum {
+ A(u32),
+ B(f32),
+ }
+
+ let a = DataEnum::A(42);
+
+ let mut slice = [0u8; 64];
+ let writer = SliceWrite::new(&mut slice);
+ let mut serializer = Serializer::new(writer);
+ a.serialize(&mut serializer).unwrap();
+ let writer = serializer.into_inner();
+ let end = writer.bytes_written();
+ let slice = writer.into_inner();
+ let deserialized: DataEnum =
+ serde_cbor::de::from_slice_with_scratch(&slice[..end], &mut []).unwrap();
+ assert_eq!(a, deserialized);
+}
+
+#[cfg(feature = "std")]
+mod std_tests {
+ use std::collections::BTreeMap;
+
+ use serde_cbor::ser::{IoWrite, Serializer};
+ use serde_cbor::value::Value;
+ use serde_cbor::{from_slice, to_vec};
+
+ pub fn to_vec_legacy<T>(value: &T) -> serde_cbor::Result<Vec<u8>>
+ where
+ T: serde::ser::Serialize,
+ {
+ let mut vec = Vec::new();
+ value.serialize(&mut Serializer::new(&mut IoWrite::new(&mut vec)).legacy_enums())?;
+ Ok(vec)
+ }
+
+ #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
+ enum Enum {
+ A,
+ B,
+ }
+
+ #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
+ struct EnumStruct {
+ e: Enum,
+ }
+
+ #[test]
+ fn test_enum() {
+ let enum_struct = EnumStruct { e: Enum::B };
+ let raw = &to_vec(&enum_struct).unwrap();
+ println!("raw enum {:?}", raw);
+ let re: EnumStruct = from_slice(raw).unwrap();
+ assert_eq!(enum_struct, re);
+ }
+
+ #[repr(u16)]
+ #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
+ enum ReprEnum {
+ A,
+ B,
+ }
+
+ #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
+ struct ReprEnumStruct {
+ e: ReprEnum,
+ }
+
+ #[test]
+ fn test_repr_enum() {
+ let repr_enum_struct = ReprEnumStruct { e: ReprEnum::B };
+ let re: ReprEnumStruct = from_slice(&to_vec(&repr_enum_struct).unwrap()).unwrap();
+ assert_eq!(repr_enum_struct, re);
+ }
+
+ #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
+ enum DataEnum {
+ A(u32),
+ B(bool, u8),
+ C { x: u8, y: String },
+ }
+
+ #[test]
+ fn test_data_enum() {
+ let data_enum_a = DataEnum::A(4);
+ let re_a: DataEnum = from_slice(&to_vec(&data_enum_a).unwrap()).unwrap();
+ assert_eq!(data_enum_a, re_a);
+ let data_enum_b = DataEnum::B(true, 42);
+ let re_b: DataEnum = from_slice(&to_vec(&data_enum_b).unwrap()).unwrap();
+ assert_eq!(data_enum_b, re_b);
+ let data_enum_c = DataEnum::C {
+ x: 3,
+ y: "foo".to_owned(),
+ };
+ println!("{:?}", &to_vec(&data_enum_c).unwrap());
+ let re_c: DataEnum = from_slice(&to_vec(&data_enum_c).unwrap()).unwrap();
+ assert_eq!(data_enum_c, re_c);
+ }
+
+ #[test]
+ fn test_serialize() {
+ assert_eq!(to_vec_legacy(&Enum::A).unwrap(), &[97, 65]);
+ assert_eq!(to_vec_legacy(&Enum::B).unwrap(), &[97, 66]);
+ assert_eq!(
+ to_vec_legacy(&DataEnum::A(42)).unwrap(),
+ &[130, 97, 65, 24, 42]
+ );
+ assert_eq!(
+ to_vec_legacy(&DataEnum::B(true, 9)).unwrap(),
+ &[131, 97, 66, 245, 9]
+ );
+ }
+
+ #[test]
+ fn test_newtype_struct() {
+ #[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
+ pub struct Newtype(u8);
+ assert_eq!(to_vec(&142u8).unwrap(), to_vec(&Newtype(142u8)).unwrap());
+ assert_eq!(from_slice::<Newtype>(&[24, 142]).unwrap(), Newtype(142));
+ }
+
+ #[derive(Deserialize, PartialEq, Debug)]
+ enum Foo {
+ #[serde(rename = "require")]
+ Require,
+ }
+
+ #[test]
+ fn test_variable_length_array() {
+ let slice = b"\x9F\x67\x72\x65\x71\x75\x69\x72\x65\xFF";
+ let value: Vec<Foo> = from_slice(slice).unwrap();
+ assert_eq!(value, [Foo::Require]);
+ }
+
+ #[derive(Serialize, Deserialize, PartialEq, Debug)]
+ enum Bar {
+ Empty,
+ Number(i32),
+ Flag(String, bool),
+ Point { x: i32, y: i32 },
+ }
+
+ #[test]
+ fn test_enum_as_map() {
+ // unit variants serialize like bare strings
+ let empty_s = to_vec_legacy(&Bar::Empty).unwrap();
+ let empty_str_s = to_vec_legacy(&"Empty").unwrap();
+ assert_eq!(empty_s, empty_str_s);
+
+ // tuple-variants serialize like ["<variant>", values..]
+ let number_s = to_vec_legacy(&Bar::Number(42)).unwrap();
+ let number_vec = vec![Value::Text("Number".to_string()), Value::Integer(42)];
+ let number_vec_s = to_vec_legacy(&number_vec).unwrap();
+ assert_eq!(number_s, number_vec_s);
+
+ let flag_s = to_vec_legacy(&Bar::Flag("foo".to_string(), true)).unwrap();
+ let flag_vec = vec![
+ Value::Text("Flag".to_string()),
+ Value::Text("foo".to_string()),
+ Value::Bool(true),
+ ];
+ let flag_vec_s = to_vec_legacy(&flag_vec).unwrap();
+ assert_eq!(flag_s, flag_vec_s);
+
+ // struct-variants serialize like ["<variant>", {struct..}]
+ let point_s = to_vec_legacy(&Bar::Point { x: 5, y: -5 }).unwrap();
+ let mut struct_map = BTreeMap::new();
+ struct_map.insert(Value::Text("x".to_string()), Value::Integer(5));
+ struct_map.insert(Value::Text("y".to_string()), Value::Integer(-5));
+ let point_vec = vec![
+ Value::Text("Point".to_string()),
+ Value::Map(struct_map.clone()),
+ ];
+ let point_vec_s = to_vec_legacy(&point_vec).unwrap();
+ assert_eq!(point_s, point_vec_s);
+
+ // enum_as_map matches serde_json's default serialization for enums.
+
+ // unit variants still serialize like bare strings
+ let empty_s = to_vec(&Bar::Empty).unwrap();
+ assert_eq!(empty_s, empty_str_s);
+
+ // 1-element tuple variants serialize like {"<variant>": value}
+ let number_s = to_vec(&Bar::Number(42)).unwrap();
+ let mut number_map = BTreeMap::new();
+ number_map.insert("Number", 42);
+ let number_map_s = to_vec(&number_map).unwrap();
+ assert_eq!(number_s, number_map_s);
+
+ // multi-element tuple variants serialize like {"<variant>": [values..]}
+ let flag_s = to_vec(&Bar::Flag("foo".to_string(), true)).unwrap();
+ let mut flag_map = BTreeMap::new();
+ flag_map.insert(
+ "Flag",
+ vec![Value::Text("foo".to_string()), Value::Bool(true)],
+ );
+ let flag_map_s = to_vec(&flag_map).unwrap();
+ assert_eq!(flag_s, flag_map_s);
+
+ // struct-variants serialize like {"<variant>", {struct..}}
+ let point_s = to_vec(&Bar::Point { x: 5, y: -5 }).unwrap();
+ let mut point_map = BTreeMap::new();
+ point_map.insert("Point", Value::Map(struct_map));
+ let point_map_s = to_vec(&point_map).unwrap();
+ assert_eq!(point_s, point_map_s);
+
+ // deserialization of all encodings should just work
+ let empty_str_ds = from_slice(&empty_str_s).unwrap();
+ assert_eq!(Bar::Empty, empty_str_ds);
+
+ let number_vec_ds = from_slice(&number_vec_s).unwrap();
+ assert_eq!(Bar::Number(42), number_vec_ds);
+ let number_map_ds = from_slice(&number_map_s).unwrap();
+ assert_eq!(Bar::Number(42), number_map_ds);
+
+ let flag_vec_ds = from_slice(&flag_vec_s).unwrap();
+ assert_eq!(Bar::Flag("foo".to_string(), true), flag_vec_ds);
+ let flag_map_ds = from_slice(&flag_map_s).unwrap();
+ assert_eq!(Bar::Flag("foo".to_string(), true), flag_map_ds);
+
+ let point_vec_ds = from_slice(&point_vec_s).unwrap();
+ assert_eq!(Bar::Point { x: 5, y: -5 }, point_vec_ds);
+ let point_map_ds = from_slice(&point_map_s).unwrap();
+ assert_eq!(Bar::Point { x: 5, y: -5 }, point_map_ds);
+ }
+}
diff --git a/third_party/rust/serde_cbor/tests/kietaub.cbor b/third_party/rust/serde_cbor/tests/kietaub.cbor
new file mode 100644
index 0000000000..866a093132
--- /dev/null
+++ b/third_party/rust/serde_cbor/tests/kietaub.cbor
Binary files differ
diff --git a/third_party/rust/serde_cbor/tests/ser.rs b/third_party/rust/serde_cbor/tests/ser.rs
new file mode 100644
index 0000000000..d374ce2faf
--- /dev/null
+++ b/third_party/rust/serde_cbor/tests/ser.rs
@@ -0,0 +1,254 @@
+use serde::Serialize;
+use serde_cbor::ser::{Serializer, SliceWrite};
+
+#[test]
+fn test_str() {
+ serialize_and_compare("foobar", b"ffoobar");
+}
+
+#[test]
+fn test_list() {
+ serialize_and_compare(&[1, 2, 3], b"\x83\x01\x02\x03");
+}
+
+#[test]
+fn test_float() {
+ serialize_and_compare(12.3f64, b"\xfb@(\x99\x99\x99\x99\x99\x9a");
+}
+
+#[test]
+fn test_integer() {
+ // u8
+ serialize_and_compare(24, b"\x18\x18");
+ // i8
+ serialize_and_compare(-5, b"\x24");
+ // i16
+ serialize_and_compare(-300, b"\x39\x01\x2b");
+ // i32
+ serialize_and_compare(-23567997, b"\x3a\x01\x67\x9e\x7c");
+ // u64
+ serialize_and_compare(::core::u64::MAX, b"\x1b\xff\xff\xff\xff\xff\xff\xff\xff");
+}
+
+fn serialize_and_compare<T: Serialize>(value: T, expected: &[u8]) {
+ let mut slice = [0u8; 64];
+ let writer = SliceWrite::new(&mut slice);
+ let mut serializer = Serializer::new(writer);
+ value.serialize(&mut serializer).unwrap();
+ let writer = serializer.into_inner();
+ let end = writer.bytes_written();
+ let slice = writer.into_inner();
+ assert_eq!(&slice[..end], expected);
+}
+
+#[cfg(feature = "std")]
+mod std_tests {
+ use serde::Serializer;
+ use serde_cbor::ser;
+ use serde_cbor::{from_slice, to_vec};
+ use std::collections::BTreeMap;
+
+ #[test]
+ fn test_string() {
+ let value = "foobar".to_owned();
+ assert_eq!(&to_vec(&value).unwrap()[..], b"ffoobar");
+ }
+
+ #[test]
+ fn test_list() {
+ let value = vec![1, 2, 3];
+ assert_eq!(&to_vec(&value).unwrap()[..], b"\x83\x01\x02\x03");
+ }
+
+ #[test]
+ fn test_object() {
+ let mut object = BTreeMap::new();
+ object.insert("a".to_owned(), "A".to_owned());
+ object.insert("b".to_owned(), "B".to_owned());
+ object.insert("c".to_owned(), "C".to_owned());
+ object.insert("d".to_owned(), "D".to_owned());
+ object.insert("e".to_owned(), "E".to_owned());
+ let vec = to_vec(&object).unwrap();
+ let test_object = from_slice(&vec[..]).unwrap();
+ assert_eq!(object, test_object);
+ }
+
+ #[test]
+ fn test_object_list_keys() {
+ let mut object = BTreeMap::new();
+ object.insert(vec![0i64], ());
+ object.insert(vec![100i64], ());
+ object.insert(vec![-1i64], ());
+ object.insert(vec![-2i64], ());
+ object.insert(vec![0i64, 0i64], ());
+ object.insert(vec![0i64, -1i64], ());
+ let vec = to_vec(&serde_cbor::value::to_value(object.clone()).unwrap()).unwrap();
+ assert_eq!(
+ vec![
+ 166, 129, 0, 246, 129, 24, 100, 246, 129, 32, 246, 129, 33, 246, 130, 0, 0, 246,
+ 130, 0, 32, 246
+ ],
+ vec
+ );
+ let test_object = from_slice(&vec[..]).unwrap();
+ assert_eq!(object, test_object);
+ }
+
+ #[test]
+ fn test_object_object_keys() {
+ use std::iter::FromIterator;
+ let mut object = BTreeMap::new();
+ let keys = vec![
+ vec!["a"],
+ vec!["b"],
+ vec!["c"],
+ vec!["d"],
+ vec!["aa"],
+ vec!["a", "aa"],
+ ]
+ .into_iter()
+ .map(|v| BTreeMap::from_iter(v.into_iter().map(|s| (s.to_owned(), ()))));
+
+ for key in keys {
+ object.insert(key, ());
+ }
+ let vec = to_vec(&serde_cbor::value::to_value(object.clone()).unwrap()).unwrap();
+ assert_eq!(
+ vec![
+ 166, 161, 97, 97, 246, 246, 161, 97, 98, 246, 246, 161, 97, 99, 246, 246, 161, 97,
+ 100, 246, 246, 161, 98, 97, 97, 246, 246, 162, 97, 97, 246, 98, 97, 97, 246, 246
+ ],
+ vec
+ );
+ let test_object = from_slice(&vec[..]).unwrap();
+ assert_eq!(object, test_object);
+ }
+
+ #[test]
+ fn test_float() {
+ let vec = to_vec(&12.3f64).unwrap();
+ assert_eq!(vec, b"\xfb@(\x99\x99\x99\x99\x99\x9a");
+ }
+
+ #[test]
+ fn test_f32() {
+ let vec = to_vec(&4000.5f32).unwrap();
+ assert_eq!(vec, b"\xfa\x45\x7a\x08\x00");
+ }
+
+ #[test]
+ fn test_infinity() {
+ let vec = to_vec(&::std::f64::INFINITY).unwrap();
+ assert_eq!(vec, b"\xf9|\x00");
+ }
+
+ #[test]
+ fn test_neg_infinity() {
+ let vec = to_vec(&::std::f64::NEG_INFINITY).unwrap();
+ assert_eq!(vec, b"\xf9\xfc\x00");
+ }
+
+ #[test]
+ fn test_nan() {
+ let vec = to_vec(&::std::f32::NAN).unwrap();
+ assert_eq!(vec, b"\xf9\x7e\x00");
+ }
+
+ #[test]
+ fn test_integer() {
+ // u8
+ let vec = to_vec(&24).unwrap();
+ assert_eq!(vec, b"\x18\x18");
+ // i8
+ let vec = to_vec(&-5).unwrap();
+ assert_eq!(vec, b"\x24");
+ // i16
+ let vec = to_vec(&-300).unwrap();
+ assert_eq!(vec, b"\x39\x01\x2b");
+ // i32
+ let vec = to_vec(&-23567997).unwrap();
+ assert_eq!(vec, b"\x3a\x01\x67\x9e\x7c");
+ // u64
+ let vec = to_vec(&::std::u64::MAX).unwrap();
+ assert_eq!(vec, b"\x1b\xff\xff\xff\xff\xff\xff\xff\xff");
+ }
+
+ #[test]
+ fn test_self_describing() {
+ let mut vec = Vec::new();
+ {
+ let mut serializer = ser::Serializer::new(&mut vec);
+ serializer.self_describe().unwrap();
+ serializer.serialize_u64(9).unwrap();
+ }
+ assert_eq!(vec, b"\xd9\xd9\xf7\x09");
+ }
+
+ #[test]
+ fn test_ip_addr() {
+ use std::net::Ipv4Addr;
+
+ let addr = Ipv4Addr::new(8, 8, 8, 8);
+ let vec = to_vec(&addr).unwrap();
+ println!("{:?}", vec);
+ assert_eq!(vec.len(), 5);
+ let test_addr: Ipv4Addr = from_slice(&vec).unwrap();
+ assert_eq!(addr, test_addr);
+ }
+
+ /// Test all of CBOR's fixed-length byte string types
+ #[test]
+ fn test_byte_string() {
+ // Very short byte strings have 1-byte headers
+ let short = vec![0, 1, 2, 255];
+ let mut short_s = Vec::new();
+ serde_cbor::Serializer::new(&mut short_s)
+ .serialize_bytes(&short)
+ .unwrap();
+ assert_eq!(&short_s[..], [0x44, 0, 1, 2, 255]);
+
+ // byte strings > 23 bytes have 2-byte headers
+ let medium = vec![
+ 0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 255,
+ ];
+ let mut medium_s = Vec::new();
+ serde_cbor::Serializer::new(&mut medium_s)
+ .serialize_bytes(&medium)
+ .unwrap();
+ assert_eq!(
+ &medium_s[..],
+ [
+ 0x58, 24, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 255
+ ]
+ );
+
+ // byte strings > 256 bytes have 3-byte headers
+ let long_vec = (0..256).map(|i| (i & 0xFF) as u8).collect::<Vec<_>>();
+ let mut long_s = Vec::new();
+ serde_cbor::Serializer::new(&mut long_s)
+ .serialize_bytes(&long_vec)
+ .unwrap();
+ assert_eq!(&long_s[0..3], [0x59, 1, 0]);
+ assert_eq!(&long_s[3..], &long_vec[..]);
+
+ // byte strings > 2^16 bytes have 5-byte headers
+ let very_long_vec = (0..65536).map(|i| (i & 0xFF) as u8).collect::<Vec<_>>();
+ let mut very_long_s = Vec::new();
+ serde_cbor::Serializer::new(&mut very_long_s)
+ .serialize_bytes(&very_long_vec)
+ .unwrap();
+ assert_eq!(&very_long_s[0..5], [0x5a, 0, 1, 0, 0]);
+ assert_eq!(&very_long_s[5..], &very_long_vec[..]);
+
+ // byte strings > 2^32 bytes have 9-byte headers, but they take too much RAM
+ // to test in Travis.
+ }
+
+ #[test]
+ fn test_half() {
+ let vec = to_vec(&42.5f32).unwrap();
+ assert_eq!(vec, b"\xF9\x51\x50");
+ assert_eq!(from_slice::<f32>(&vec[..]).unwrap(), 42.5f32);
+ }
+}
diff --git a/third_party/rust/serde_cbor/tests/std_types.rs b/third_party/rust/serde_cbor/tests/std_types.rs
new file mode 100644
index 0000000000..7a7ded484c
--- /dev/null
+++ b/third_party/rust/serde_cbor/tests/std_types.rs
@@ -0,0 +1,186 @@
+#[macro_use]
+extern crate serde_derive;
+
+#[cfg(feature = "std")]
+mod std_tests {
+ use std::u8;
+
+ use serde_cbor::de::from_mut_slice;
+ use serde_cbor::ser::{to_vec, to_vec_packed};
+ use serde_cbor::{from_reader, from_slice};
+
+ fn to_binary(s: &'static str) -> Vec<u8> {
+ assert!(s.len() % 2 == 0);
+ let mut b = Vec::with_capacity(s.len() / 2);
+ for i in 0..s.len() / 2 {
+ b.push(u8::from_str_radix(&s[i * 2..(i + 1) * 2], 16).unwrap());
+ }
+ b
+ }
+
+ macro_rules! testcase {
+ ($name:ident, f64, $expr:expr, $s:expr) => {
+ #[test]
+ fn $name() {
+ let expr: f64 = $expr;
+ let mut serialized = to_binary($s);
+ assert_eq!(to_vec(&expr).unwrap(), serialized);
+ let parsed: f64 = from_slice(&serialized[..]).unwrap();
+ if !expr.is_nan() {
+ assert_eq!(expr, parsed);
+ } else {
+ assert!(parsed.is_nan())
+ }
+
+ let parsed: f64 = from_reader(&mut &serialized[..]).unwrap();
+ if !expr.is_nan() {
+ assert_eq!(expr, parsed);
+ } else {
+ assert!(parsed.is_nan())
+ }
+
+ let parsed: f64 = from_mut_slice(&mut serialized[..]).unwrap();
+ if !expr.is_nan() {
+ assert_eq!(expr, parsed);
+ } else {
+ assert!(parsed.is_nan())
+ }
+ }
+ };
+ ($name:ident, $ty:ty, $expr:expr, $s:expr) => {
+ #[test]
+ fn $name() {
+ let expr: $ty = $expr;
+ let mut serialized = to_binary($s);
+ assert_eq!(
+ to_vec(&expr).expect("ser1 works"),
+ serialized,
+ "serialization differs"
+ );
+ let parsed: $ty = from_slice(&serialized[..]).expect("de1 works");
+ assert_eq!(parsed, expr, "parsed result differs");
+ let packed = &to_vec_packed(&expr).expect("serializing packed")[..];
+ let parsed_from_packed: $ty = from_slice(packed).expect("parsing packed");
+ assert_eq!(parsed_from_packed, expr, "packed roundtrip fail");
+
+ let parsed: $ty = from_reader(&mut &serialized[..]).unwrap();
+ assert_eq!(parsed, expr, "parsed result differs");
+ let mut packed = to_vec_packed(&expr).expect("serializing packed");
+ let parsed_from_packed: $ty =
+ from_reader(&mut &packed[..]).expect("parsing packed");
+ assert_eq!(parsed_from_packed, expr, "packed roundtrip fail");
+
+ let parsed: $ty = from_mut_slice(&mut serialized[..]).unwrap();
+ assert_eq!(parsed, expr, "parsed result differs");
+ let parsed_from_packed: $ty =
+ from_mut_slice(&mut packed[..]).expect("parsing packed");
+ assert_eq!(parsed_from_packed, expr, "packed roundtrip fail");
+ }
+ };
+ }
+
+ testcase!(test_bool_false, bool, false, "f4");
+ testcase!(test_bool_true, bool, true, "f5");
+ testcase!(test_isize_neg_256, isize, -256, "38ff");
+ testcase!(test_isize_neg_257, isize, -257, "390100");
+ testcase!(test_isize_255, isize, 255, "18ff");
+ testcase!(test_i8_5, i8, 5, "05");
+ testcase!(test_i8_23, i8, 23, "17");
+ testcase!(test_i8_24, i8, 24, "1818");
+ testcase!(test_i8_neg_128, i8, -128, "387f");
+ testcase!(test_u32_98745874, u32, 98745874, "1a05e2be12");
+ testcase!(test_f32_1234_point_5, f32, 1234.5, "fa449a5000");
+ testcase!(test_f64_12345_point_6, f64, 12345.6, "fb40c81ccccccccccd");
+ testcase!(test_f64_nan, f64, ::std::f64::NAN, "f97e00");
+ testcase!(test_f64_infinity, f64, ::std::f64::INFINITY, "f97c00");
+ testcase!(test_f64_neg_infinity, f64, -::std::f64::INFINITY, "f9fc00");
+ testcase!(test_char_null, char, '\x00', "6100");
+ testcase!(test_char_broken_heart, char, '💔', "64f09f9294");
+ testcase!(
+ test_str_pangram_de,
+ String,
+ "aâø↓é".to_owned(),
+ "6a61c3a2c3b8e28693c3a9"
+ );
+ testcase!(test_unit, (), (), "f6");
+
+ #[derive(Debug, PartialEq, Deserialize, Serialize)]
+ struct UnitStruct;
+ testcase!(test_unit_struct, UnitStruct, UnitStruct, "f6");
+
+ #[derive(Debug, PartialEq, Deserialize, Serialize)]
+ struct NewtypeStruct(bool);
+ testcase!(
+ test_newtype_struct,
+ NewtypeStruct,
+ NewtypeStruct(true),
+ "f5"
+ );
+
+ testcase!(test_option_none, Option<u8>, None, "f6");
+ testcase!(test_option_some, Option<u8>, Some(42), "182a");
+
+ #[derive(Debug, PartialEq, Deserialize, Serialize)]
+ struct Person {
+ name: String,
+ year_of_birth: u16,
+ profession: Option<String>,
+ }
+
+ testcase!(test_person_struct,
+ Person,
+ Person {
+ name: "Grace Hopper".to_string(),
+ year_of_birth: 1906,
+ profession: Some("computer scientist".to_string()),
+ },
+ "a3646e616d656c477261636520486f707065726d796561725f6f665f62697274681907726a70726f66657373696f6e72636f6d707574657220736369656e74697374");
+
+ #[derive(Debug, PartialEq, Deserialize, Serialize)]
+ struct OptionalPerson {
+ name: String,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ year_of_birth: Option<u16>,
+ profession: Option<String>,
+ }
+
+ testcase!(test_optional_person_struct,
+ OptionalPerson,
+ OptionalPerson {
+ name: "Grace Hopper".to_string(),
+ year_of_birth: None,
+ profession: Some("computer scientist".to_string()),
+ },
+ "a2646e616d656c477261636520486f707065726a70726f66657373696f6e72636f6d707574657220736369656e74697374");
+
+ #[derive(Debug, PartialEq, Deserialize, Serialize)]
+ enum Color {
+ Red,
+ Blue,
+ Yellow,
+ Other(u64),
+ Alpha(u64, u8),
+ }
+
+ testcase!(test_color_enum, Color, Color::Blue, "64426c7565");
+ testcase!(
+ test_color_enum_transparent,
+ Color,
+ Color::Other(42),
+ "a1654f74686572182a"
+ );
+ testcase!(
+ test_color_enum_with_alpha,
+ Color,
+ Color::Alpha(234567, 60),
+ "a165416c706861821a00039447183c"
+ );
+ testcase!(test_i128_a, i128, -1i128, "20");
+ testcase!(
+ test_i128_b,
+ i128,
+ -18446744073709551616i128,
+ "3BFFFFFFFFFFFFFFFF"
+ );
+ testcase!(test_u128, u128, 17, "11");
+}
diff --git a/third_party/rust/serde_cbor/tests/tags.rs b/third_party/rust/serde_cbor/tests/tags.rs
new file mode 100644
index 0000000000..92534c023d
--- /dev/null
+++ b/third_party/rust/serde_cbor/tests/tags.rs
@@ -0,0 +1,48 @@
+#[cfg(feature = "tags")]
+mod tagtests {
+ use serde_cbor::value::Value;
+ use serde_cbor::{from_slice, to_vec};
+
+ fn decode_hex(s: &str) -> std::result::Result<Vec<u8>, std::num::ParseIntError> {
+ (0..s.len())
+ .step_by(2)
+ .map(|i| u8::from_str_radix(&s[i..i + 2], 16))
+ .collect()
+ }
+
+ // get bytes from http://cbor.me/ trees
+ fn parse_cbor_me(example: &str) -> std::result::Result<Vec<u8>, std::num::ParseIntError> {
+ let hex = example
+ .split("\n")
+ .flat_map(|line| line.split("#").take(1))
+ .collect::<Vec<&str>>()
+ .join("")
+ .replace(" ", "");
+ decode_hex(&hex)
+ }
+
+ #[test]
+ fn tagged_cbor_roundtrip() {
+ let data = r#"
+C1 # tag(1)
+ 82 # array(2)
+ C2 # tag(2)
+ 63 # text(3)
+ 666F6F # "foo"
+ C3 # tag(3)
+ A1 # map(1)
+ C4 # tag(4)
+ 61 # text(1)
+ 61 # "a"
+ C5 # tag(5)
+ 61 # text(1)
+ 62 # "b"
+ "#;
+ let bytes1 = parse_cbor_me(&data).unwrap();
+ let value1: Value = from_slice(&bytes1).unwrap();
+ let bytes2 = to_vec(&value1).unwrap();
+ let value2: Value = from_slice(&bytes2).unwrap();
+ assert_eq!(bytes1, bytes2);
+ assert_eq!(value1, value2);
+ }
+}
diff --git a/third_party/rust/serde_cbor/tests/value.rs b/third_party/rust/serde_cbor/tests/value.rs
new file mode 100644
index 0000000000..554d74266c
--- /dev/null
+++ b/third_party/rust/serde_cbor/tests/value.rs
@@ -0,0 +1,100 @@
+#[macro_use]
+extern crate serde_derive;
+
+#[cfg(feature = "std")]
+mod std_tests {
+ use serde_cbor;
+
+ use std::collections::BTreeMap;
+
+ #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
+ struct TupleStruct(String, i32, u64);
+
+ #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
+ struct UnitStruct;
+
+ #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
+ struct Struct<'a> {
+ tuple_struct: TupleStruct,
+ tuple: (String, f32, f64),
+ map: BTreeMap<String, String>,
+ bytes: &'a [u8],
+ array: Vec<String>,
+ unit_array: Vec<UnitStruct>,
+ }
+
+ use serde_cbor::value::Value;
+ use std::iter::FromIterator;
+
+ #[test]
+ fn serde() {
+ let tuple_struct = TupleStruct(format!("test"), -60, 3000);
+
+ let tuple = (format!("hello"), -50.0040957, -12.094635556478);
+
+ let map = BTreeMap::from_iter(
+ [
+ (format!("key1"), format!("value1")),
+ (format!("key2"), format!("value2")),
+ (format!("key3"), format!("value3")),
+ (format!("key4"), format!("value4")),
+ ]
+ .iter()
+ .cloned(),
+ );
+
+ let bytes = b"test byte string";
+
+ let array = vec![format!("one"), format!("two"), format!("three")];
+ let unit_array = vec![UnitStruct, UnitStruct, UnitStruct];
+
+ let data = Struct {
+ tuple_struct,
+ tuple,
+ map,
+ bytes,
+ array,
+ unit_array,
+ };
+
+ let value = serde_cbor::value::to_value(data.clone()).unwrap();
+ println!("{:?}", value);
+
+ let data_ser = serde_cbor::to_vec(&value).unwrap();
+ let data_de_value: Value = serde_cbor::from_slice(&data_ser).unwrap();
+
+ fn as_object(value: &Value) -> &BTreeMap<Value, Value> {
+ if let Value::Map(ref v) = value {
+ return v;
+ }
+ panic!()
+ }
+
+ for ((k1, v1), (k2, v2)) in as_object(&value)
+ .iter()
+ .zip(as_object(&data_de_value).iter())
+ {
+ assert_eq!(k1, k2);
+ assert_eq!(v1, v2);
+ }
+
+ assert_eq!(value, data_de_value);
+ }
+
+ #[derive(Debug, Deserialize, Serialize)]
+ struct SmallStruct {
+ spam: u32,
+ eggs: u32,
+ }
+
+ #[test]
+ fn small_struct() {
+ // Test whether the packed format works.
+ // Field names should not be serialized,
+ // instead field indizes are serialized.
+ let value = SmallStruct { spam: 17, eggs: 42 };
+ let data = serde_cbor::ser::to_vec_packed(&value).unwrap();
+ let reference = b"\xa2\x00\x11\x01\x18\x2a";
+ assert_eq!(data, reference);
+ }
+}