diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
commit | d1b2d29528b7794b41e66fc2136e395a02f8529b (patch) | |
tree | a4a17504b260206dec3cf55b2dca82929a348ac2 /vendor/ciborium | |
parent | Releasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.tar.xz rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.zip |
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/ciborium')
24 files changed, 5775 insertions, 0 deletions
diff --git a/vendor/ciborium/.cargo-checksum.json b/vendor/ciborium/.cargo-checksum.json new file mode 100644 index 000000000..05c0c6dec --- /dev/null +++ b/vendor/ciborium/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"734adffb8db7ebc7b62c8280a240e8dfb66ddcb9da083be7fe32a4bacf114e0c","LICENSE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","README.md":"3ed22336e9c4f8c537588fda015009ad31259876fbfa4a427d10563cc82e0058","src/de/error.rs":"ac412e444bcb7ce0f924a7a53b2454cfa7a399b8c8d7eddc5665bb44925b6263","src/de/mod.rs":"d4d8a504407204ee95384369f240b41aacbdb88f4f1ea3e773ecfafb9878ed4e","src/lib.rs":"31da0b81bed4bf32d88fc0a874a1346d2b1f3f4a71c75b498943e9abdd50d1da","src/ser/error.rs":"ba6f98ced22e1778c2ae4b422814fd4bf56dda19c6e24684b95ec37748170df2","src/ser/mod.rs":"bc30087a231f962664d9a48f4a3446ff936ab8dc20fbc9e95ec1dc19622109a3","src/tag.rs":"9f64d74512cbbadce2abeff5c08c6dde7e9f4312da1cc028683503559e6a186d","src/value/canonical.rs":"c7b61ff248d4a3ce899839b7dbd721bd0f9842ff08338611bbfe215f68167499","src/value/de.rs":"0dca80a60ca94da12f7ac382254c419907ec340257592b0c7c0416d02e754ddb","src/value/error.rs":"e94cdb78dfa5168719e6f698103f6a47c7501bb3d27848e83cccec70e871b1b0","src/value/integer.rs":"da0176e415a31841f6c6f8f9e2c8e9a7841690cfd7680d6fb753c25f7747bd04","src/value/mod.rs":"3e02f8e5c29d43404339150d2f8e898c7d6430d4b3025bb172e8bd6498cc92ca","src/value/ser.rs":"dddfaa162c920a029ffb78069418e569f76d8d7b54529bc9f33e1502e4200ead","tests/canonical.rs":"f15c3c7465941eba4f61862ab794bee896f1b8c6420e13ce48be1ccbfbc7a1c5","tests/codec.rs":"db20401a9c719a54615327010d74baf5d603f848465968cbc336cc981a8053f8","tests/error.rs":"d84e9dd66dfab485db6ddceea4b6850e9714aee7832e588ebbc5555e424674f8","tests/fuzz.rs":"fca0f7c875957bfff4a3cfa25188e70eba536dd0071d12aa2478511c0aeafc85","tests/macro.rs":"227fb0fbf2c9e832ebfc87e5f110135cd00eb136fbed4a973fd786eb9e5536d6","tests/no_std.rs":"c302efd394c0296b692e1ca4df2aaa3944632f44c0087152d463a2ce8a49f2bc","tests/recursion.rs":"64b352be06098d4cfb43f03c95f8c2b53e38be7e86930824a399638c99c8173b","tests/tag.rs":"4eb03d53bd5ee3d7dd10f4d38ae071d47fc83090a9b1cd8425cd8cfa89dbc0a4"},"package":"effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926"}
\ No newline at end of file diff --git a/vendor/ciborium/Cargo.toml b/vendor/ciborium/Cargo.toml new file mode 100644 index 000000000..f82b8b903 --- /dev/null +++ b/vendor/ciborium/Cargo.toml @@ -0,0 +1,64 @@ +# 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 are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.56" +name = "ciborium" +version = "0.2.1" +authors = ["Nathaniel McCallum <npmccallum@profian.com>"] +description = "serde implementation of CBOR using ciborium-basic" +homepage = "https://github.com/enarx/ciborium" +readme = "README.md" +keywords = ["cbor", "serde"] +categories = ["data-structures", "embedded", "encoding", "no-std", "parsing"] +license = "Apache-2.0" +repository = "https://github.com/enarx/ciborium" +[package.metadata.docs.rs] +all-features = true +[dependencies.ciborium-io] +version = "0.2.1" +features = ["alloc"] + +[dependencies.ciborium-ll] +version = "0.2.1" + +[dependencies.serde] +version = "1.0" +features = ["alloc", "derive"] +default-features = false +[dev-dependencies.hex] +version = "0.4" + +[dev-dependencies.rand] +version = "0.8" + +[dev-dependencies.rstest] +version = "0.11" + +[dev-dependencies.serde_bytes] +version = "0.11" + +[features] +default = ["std"] +std = ["ciborium-io/std", "serde/std"] +[badges.github] +repository = "enarx/ciborium" +workflow = "test" + +[badges.is-it-maintained-issue-resolution] +repository = "enarx/ciborium" + +[badges.is-it-maintained-open-issues] +repository = "enarx/ciborium" + +[badges.maintenance] +status = "actively-developed" diff --git a/vendor/ciborium/LICENSE b/vendor/ciborium/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/vendor/ciborium/LICENSE @@ -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/vendor/ciborium/README.md b/vendor/ciborium/README.md new file mode 100644 index 000000000..b60c35e52 --- /dev/null +++ b/vendor/ciborium/README.md @@ -0,0 +1,92 @@ +[![Workflow Status](https://github.com/enarx/ciborium/workflows/test/badge.svg)](https://github.com/enarx/ciborium/actions?query=workflow%3A%22test%22) +[![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/enarx/ciborium.svg)](https://isitmaintained.com/project/enarx/ciborium "Average time to resolve an issue") +[![Percentage of issues still open](https://isitmaintained.com/badge/open/enarx/ciborium.svg)](https://isitmaintained.com/project/enarx/ciborium "Percentage of issues still open") +![Maintenance](https://img.shields.io/badge/maintenance-activly--developed-brightgreen.svg) + +# ciborium + +Welcome to Ciborium! + +Ciborium contains CBOR serialization and deserialization implementations for serde. + +## Quick Start + +You're probably looking for [`from_reader()`](crate::de::from_reader) +and [`into_writer()`](crate::ser::into_writer), which are +the main functions. Note that byte slices are also readers and writers and can be +passed to these functions just as streams can. + +For dynamic CBOR value creation/inspection, see [`Value`](crate::value::Value). + +## Design Decisions + +### Always Serialize Numeric Values to the Smallest Size + +Although the CBOR specification has differing numeric widths, this is only +a form of compression on the wire and is not intended to directly +represent an "integer width" or "float width." Therefore, ciborium always +serializes numbers to the smallest possible lossless encoding. For example, +we serialize `1u128` as a single byte (`01`). Likewise, we will also freely +decode that single byte into a `u128`. + +While there is some minor performance cost for this, there are several +reasons for this choice. First, the specification seems to imply it by +using a separate bit for the sign. Second, the specification requires +that implementations handle leading zeroes; a liberal reading of which +implies a requirement for lossless coercion. Third, dynamic languages like +Python have no notion of "integer width," making this is a practical +choice for maximizing wire compatibility with those languages. + +This coercion is **always** lossless. For floats, this implies that we +only coerce to a smaller size if coercion back to the original size has +the same raw bits as the original. + +### Compatibility with Other Implementations + +The ciborium project follows the [Robustness Principle](https://en.wikipedia.org/wiki/Robustness_principle). +Therefore, we aim to be liberal in what we accept. This implies that we +aim to be wire-compatible with other implementations in decoding, but +not necessarily encoding. + +One notable example of this is that `serde_cbor` uses fixed-width encoding +of numbers and doesn't losslessly coerce. This implies that `ciborium` will +successfully decode `serde_cbor` encodings, but the opposite may not be the +case. + +### Representing Map as a Sequence of Values + +Other serde parsers have generally taken the route of using `BTreeMap` or +`HashMap` to implement their encoding's underlying `Map` type. This crate +chooses to represent the `Map` type using `Vec<(Value, Value)>` instead. + +This decision was made because this type preserves the order of the pairs +on the wire. Further, for those that need the properties of `BTreeMap` or +`HashMap`, you can simply `collect()` the values into the respective type. +This provides maximum flexibility. + +### Low-level Library + +The ciborium crate has the beginnings of a low-level library in the +(private) `basic` module. We may extend this to be more robust and expose +it for application consumption once we have it in a good state. If you'd +like to collaborate with us on that, please contact us. Alternatively, +we might fork this code into a separate crate with no serde dependency. + +### Internal Types + +The ciborium crate contains a number of internal types that implement +useful serde traits. While these are not currently exposed, we might +choose to expose them in the future if there is demand. Generally, this +crate takes a conservative approach to exposing APIs to avoid breakage. + +### Packed Encoding? + +Packed encoding uses numerical offsets to represent structure field names +and enum variant names. This can save significant space on the wire. + +While the authors of this crate like packed encoding, it should generally +be avoided because it can be fragile as it exposes invariants of your Rust +code to remote actors. We might consider adding this in the future. If you +are interested in this, please contact us. + +License: Apache-2.0 diff --git a/vendor/ciborium/src/de/error.rs b/vendor/ciborium/src/de/error.rs new file mode 100644 index 000000000..3334f8121 --- /dev/null +++ b/vendor/ciborium/src/de/error.rs @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: Apache-2.0 + +use alloc::string::{String, ToString}; +use core::fmt::{Debug, Display, Formatter, Result}; + +use serde::de::{Error as DeError, StdError}; + +/// An error occurred during deserialization +#[derive(Debug)] +pub enum Error<T> { + /// An error occurred while reading bytes + /// + /// Contains the underlying error reaturned while reading. + Io(T), + + /// An error occurred while parsing bytes + /// + /// Contains the offset into the stream where the syntax error occurred. + Syntax(usize), + + /// An error occurred while processing a parsed value + /// + /// Contains a description of the error that occurred and (optionally) + /// the offset into the stream indicating the start of the item being + /// processed when the error occurred. + Semantic(Option<usize>, String), + + /// The input caused serde to recurse too much + /// + /// This error prevents a stack overflow. + RecursionLimitExceeded, +} + +impl<T> Error<T> { + /// A helper method for composing a semantic error + #[inline] + pub fn semantic(offset: impl Into<Option<usize>>, msg: impl Into<String>) -> Self { + Self::Semantic(offset.into(), msg.into()) + } +} + +impl<T> From<T> for Error<T> { + #[inline] + fn from(value: T) -> Self { + Error::Io(value) + } +} + +impl<T> From<ciborium_ll::Error<T>> for Error<T> { + #[inline] + fn from(value: ciborium_ll::Error<T>) -> Self { + match value { + ciborium_ll::Error::Io(x) => Self::Io(x), + ciborium_ll::Error::Syntax(x) => Self::Syntax(x), + } + } +} + +impl<T: Debug> Display for Error<T> { + #[inline] + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + write!(f, "{:?}", self) + } +} + +impl<T: Debug> StdError for Error<T> {} + +impl<T: Debug> DeError for Error<T> { + #[inline] + fn custom<U: Display>(msg: U) -> Self { + Self::Semantic(None, msg.to_string()) + } +} diff --git a/vendor/ciborium/src/de/mod.rs b/vendor/ciborium/src/de/mod.rs new file mode 100644 index 000000000..f59a319de --- /dev/null +++ b/vendor/ciborium/src/de/mod.rs @@ -0,0 +1,833 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! Serde deserialization support for CBOR + +mod error; + +pub use error::Error; + +use alloc::{string::String, vec::Vec}; + +use ciborium_io::Read; +use ciborium_ll::*; +use serde::{de, de::Deserializer as _, forward_to_deserialize_any}; + +trait Expected<E: de::Error> { + fn expected(self, kind: &'static str) -> E; +} + +impl<E: de::Error> Expected<E> for Header { + #[inline] + fn expected(self, kind: &'static str) -> E { + de::Error::invalid_type( + match self { + Header::Positive(x) => de::Unexpected::Unsigned(x), + Header::Negative(x) => de::Unexpected::Signed(x as i64 ^ !0), + Header::Bytes(..) => de::Unexpected::Other("bytes"), + Header::Text(..) => de::Unexpected::Other("string"), + + Header::Array(..) => de::Unexpected::Seq, + Header::Map(..) => de::Unexpected::Map, + + Header::Tag(..) => de::Unexpected::Other("tag"), + + Header::Simple(simple::FALSE) => de::Unexpected::Bool(false), + Header::Simple(simple::TRUE) => de::Unexpected::Bool(true), + Header::Simple(simple::NULL) => de::Unexpected::Other("null"), + Header::Simple(simple::UNDEFINED) => de::Unexpected::Other("undefined"), + Header::Simple(..) => de::Unexpected::Other("simple"), + + Header::Float(x) => de::Unexpected::Float(x), + Header::Break => de::Unexpected::Other("break"), + }, + &kind, + ) + } +} + +struct Deserializer<'b, R: Read> { + decoder: Decoder<R>, + scratch: &'b mut [u8], + recurse: usize, +} + +impl<'a, R: Read> Deserializer<'a, R> +where + R::Error: core::fmt::Debug, +{ + #[inline] + fn recurse<V, F: FnOnce(&mut Self) -> Result<V, Error<R::Error>>>( + &mut self, + func: F, + ) -> Result<V, Error<R::Error>> { + if self.recurse == 0 { + return Err(Error::RecursionLimitExceeded); + } + + self.recurse -= 1; + let result = func(self); + self.recurse += 1; + result + } + + #[inline] + fn integer(&mut self, mut header: Option<Header>) -> Result<(bool, u128), Error<R::Error>> { + loop { + let header = match header.take() { + Some(h) => h, + None => self.decoder.pull()?, + }; + + let neg = match header { + Header::Positive(x) => return Ok((false, x.into())), + Header::Negative(x) => return Ok((true, x.into())), + Header::Tag(tag::BIGPOS) => false, + Header::Tag(tag::BIGNEG) => true, + Header::Tag(..) => continue, + header => return Err(header.expected("integer")), + }; + + let mut buffer = [0u8; 16]; + let mut value = [0u8; 16]; + let mut index = 0usize; + + return match self.decoder.pull()? { + Header::Bytes(len) => { + let mut segments = self.decoder.bytes(len); + while let Some(mut segment) = segments.pull()? { + while let Some(chunk) = segment.pull(&mut buffer)? { + for b in chunk { + match index { + 16 => return Err(de::Error::custom("bigint too large")), + 0 if *b == 0 => continue, // Skip leading zeros + _ => value[index] = *b, + } + + index += 1; + } + } + } + + value[..index].reverse(); + Ok((neg, u128::from_le_bytes(value))) + } + + h => Err(h.expected("bytes")), + }; + } + } +} + +impl<'de, 'a, 'b, R: Read> de::Deserializer<'de> for &'a mut Deserializer<'b, R> +where + R::Error: core::fmt::Debug, +{ + type Error = Error<R::Error>; + + #[inline] + fn deserialize_any<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + let header = self.decoder.pull()?; + self.decoder.push(header); + + match header { + Header::Positive(..) => self.deserialize_u64(visitor), + Header::Negative(x) => match i64::try_from(x) { + Ok(..) => self.deserialize_i64(visitor), + Err(..) => self.deserialize_i128(visitor), + }, + + Header::Bytes(len) => match len { + Some(len) if len <= self.scratch.len() => self.deserialize_bytes(visitor), + _ => self.deserialize_byte_buf(visitor), + }, + + Header::Text(len) => match len { + Some(len) if len <= self.scratch.len() => self.deserialize_str(visitor), + _ => self.deserialize_string(visitor), + }, + + Header::Array(..) => self.deserialize_seq(visitor), + Header::Map(..) => self.deserialize_map(visitor), + + Header::Tag(tag) => { + let _: Header = self.decoder.pull()?; + + // Peek at the next item. + let header = self.decoder.pull()?; + self.decoder.push(header); + + // If it is bytes, capture the length. + let len = match header { + Header::Bytes(x) => x, + _ => None, + }; + + match (tag, len) { + (tag::BIGPOS, Some(len)) | (tag::BIGNEG, Some(len)) if len <= 16 => { + let result = match self.integer(Some(Header::Tag(tag)))? { + (false, raw) => return visitor.visit_u128(raw), + (true, raw) => i128::try_from(raw).map(|x| x ^ !0), + }; + + match result { + Ok(x) => visitor.visit_i128(x), + Err(..) => Err(de::Error::custom("integer too large")), + } + } + + _ => self.recurse(|me| { + let access = crate::tag::TagAccess::new(me, Some(tag)); + visitor.visit_enum(access) + }), + } + } + + Header::Float(..) => self.deserialize_f64(visitor), + + Header::Simple(simple::FALSE) => self.deserialize_bool(visitor), + Header::Simple(simple::TRUE) => self.deserialize_bool(visitor), + Header::Simple(simple::NULL) => self.deserialize_option(visitor), + Header::Simple(simple::UNDEFINED) => self.deserialize_option(visitor), + h @ Header::Simple(..) => Err(h.expected("known simple value")), + + h @ Header::Break => Err(h.expected("non-break")), + } + } + + #[inline] + fn deserialize_bool<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + loop { + let offset = self.decoder.offset(); + + return match self.decoder.pull()? { + Header::Tag(..) => continue, + Header::Simple(simple::FALSE) => visitor.visit_bool(false), + Header::Simple(simple::TRUE) => visitor.visit_bool(true), + _ => Err(Error::semantic(offset, "expected bool")), + }; + } + } + + #[inline] + fn deserialize_f32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + self.deserialize_f64(visitor) + } + + #[inline] + fn deserialize_f64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + loop { + return match self.decoder.pull()? { + Header::Tag(..) => continue, + Header::Float(x) => visitor.visit_f64(x), + h => Err(h.expected("float")), + }; + } + } + + fn deserialize_i8<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + self.deserialize_i64(visitor) + } + + fn deserialize_i16<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + self.deserialize_i64(visitor) + } + + fn deserialize_i32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + self.deserialize_i64(visitor) + } + + fn deserialize_i64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + let result = match self.integer(None)? { + (false, raw) => i64::try_from(raw), + (true, raw) => i64::try_from(raw).map(|x| x ^ !0), + }; + + match result { + Ok(x) => visitor.visit_i64(x), + Err(..) => Err(de::Error::custom("integer too large")), + } + } + + fn deserialize_i128<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + let result = match self.integer(None)? { + (false, raw) => i128::try_from(raw), + (true, raw) => i128::try_from(raw).map(|x| x ^ !0), + }; + + match result { + Ok(x) => visitor.visit_i128(x), + Err(..) => Err(de::Error::custom("integer too large")), + } + } + + fn deserialize_u8<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + self.deserialize_u64(visitor) + } + + fn deserialize_u16<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + self.deserialize_u64(visitor) + } + + fn deserialize_u32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + self.deserialize_u64(visitor) + } + + fn deserialize_u64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + let result = match self.integer(None)? { + (false, raw) => u64::try_from(raw), + (true, ..) => return Err(de::Error::custom("unexpected negative integer")), + }; + + match result { + Ok(x) => visitor.visit_u64(x), + Err(..) => Err(de::Error::custom("integer too large")), + } + } + + fn deserialize_u128<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + match self.integer(None)? { + (false, raw) => visitor.visit_u128(raw), + (true, ..) => Err(de::Error::custom("unexpected negative integer")), + } + } + + fn deserialize_char<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + loop { + let offset = self.decoder.offset(); + let header = self.decoder.pull()?; + + return match header { + Header::Tag(..) => continue, + + Header::Text(Some(len)) if len <= 4 => { + let mut buf = [0u8; 4]; + self.decoder.read_exact(&mut buf[..len])?; + + match core::str::from_utf8(&buf[..len]) { + Ok(s) => match s.chars().count() { + 1 => visitor.visit_char(s.chars().next().unwrap()), + _ => Err(header.expected("char")), + }, + Err(..) => Err(Error::Syntax(offset)), + } + } + + _ => Err(header.expected("char")), + }; + } + } + + fn deserialize_str<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + loop { + let offset = self.decoder.offset(); + + return match self.decoder.pull()? { + Header::Tag(..) => continue, + + Header::Text(Some(len)) if len <= self.scratch.len() => { + self.decoder.read_exact(&mut self.scratch[..len])?; + + match core::str::from_utf8(&self.scratch[..len]) { + Ok(s) => visitor.visit_str(s), + Err(..) => Err(Error::Syntax(offset)), + } + } + + header => Err(header.expected("str")), + }; + } + } + + fn deserialize_string<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + loop { + return match self.decoder.pull()? { + Header::Tag(..) => continue, + + Header::Text(len) => { + let mut buffer = String::new(); + + let mut segments = self.decoder.text(len); + while let Some(mut segment) = segments.pull()? { + while let Some(chunk) = segment.pull(self.scratch)? { + buffer.push_str(chunk); + } + } + + visitor.visit_string(buffer) + } + + header => Err(header.expected("string")), + }; + } + } + + fn deserialize_bytes<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + loop { + return match self.decoder.pull()? { + Header::Tag(..) => continue, + + Header::Bytes(Some(len)) if len <= self.scratch.len() => { + self.decoder.read_exact(&mut self.scratch[..len])?; + visitor.visit_bytes(&self.scratch[..len]) + } + + Header::Array(len) => self.recurse(|me| { + let access = Access(me, len); + visitor.visit_seq(access) + }), + + header => Err(header.expected("bytes")), + }; + } + } + + fn deserialize_byte_buf<V: de::Visitor<'de>>( + self, + visitor: V, + ) -> Result<V::Value, Self::Error> { + loop { + return match self.decoder.pull()? { + Header::Tag(..) => continue, + + Header::Bytes(len) => { + let mut buffer = Vec::new(); + + let mut segments = self.decoder.bytes(len); + while let Some(mut segment) = segments.pull()? { + while let Some(chunk) = segment.pull(self.scratch)? { + buffer.extend_from_slice(chunk); + } + } + + visitor.visit_byte_buf(buffer) + } + + Header::Array(len) => self.recurse(|me| { + let access = Access(me, len); + visitor.visit_seq(access) + }), + + header => Err(header.expected("byte buffer")), + }; + } + } + + fn deserialize_seq<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + loop { + return match self.decoder.pull()? { + Header::Tag(..) => continue, + + Header::Array(len) => self.recurse(|me| { + let access = Access(me, len); + visitor.visit_seq(access) + }), + + Header::Bytes(len) => { + let mut buffer = Vec::new(); + + let mut segments = self.decoder.bytes(len); + while let Some(mut segment) = segments.pull()? { + while let Some(chunk) = segment.pull(self.scratch)? { + buffer.extend_from_slice(chunk); + } + } + + visitor.visit_seq(BytesAccess::<R>(0, buffer, core::marker::PhantomData)) + } + + header => Err(header.expected("array")), + }; + } + } + + fn deserialize_map<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + loop { + return match self.decoder.pull()? { + Header::Tag(..) => continue, + + Header::Map(len) => self.recurse(|me| { + let access = Access(me, len); + visitor.visit_map(access) + }), + + header => Err(header.expected("map")), + }; + } + } + + fn deserialize_struct<V: de::Visitor<'de>>( + self, + _name: &'static str, + _fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Self::Error> { + self.deserialize_map(visitor) + } + + fn deserialize_tuple<V: de::Visitor<'de>>( + self, + _len: usize, + visitor: V, + ) -> Result<V::Value, Self::Error> { + self.deserialize_seq(visitor) + } + + fn deserialize_tuple_struct<V: de::Visitor<'de>>( + self, + _name: &'static str, + _len: usize, + visitor: V, + ) -> Result<V::Value, Self::Error> { + self.deserialize_seq(visitor) + } + + fn deserialize_identifier<V: de::Visitor<'de>>( + self, + visitor: V, + ) -> Result<V::Value, Self::Error> { + loop { + let offset = self.decoder.offset(); + + return match self.decoder.pull()? { + Header::Tag(..) => continue, + + Header::Text(Some(len)) if len <= self.scratch.len() => { + self.decoder.read_exact(&mut self.scratch[..len])?; + + match core::str::from_utf8(&self.scratch[..len]) { + Ok(s) => visitor.visit_str(s), + Err(..) => Err(Error::Syntax(offset)), + } + } + Header::Bytes(Some(len)) if len <= self.scratch.len() => { + self.decoder.read_exact(&mut self.scratch[..len])?; + visitor.visit_bytes(&self.scratch[..len]) + } + + header => Err(header.expected("str or bytes")), + }; + } + } + + fn deserialize_ignored_any<V: de::Visitor<'de>>( + self, + visitor: V, + ) -> Result<V::Value, Self::Error> { + self.deserialize_any(visitor) + } + + #[inline] + fn deserialize_option<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + match self.decoder.pull()? { + Header::Simple(simple::UNDEFINED) => visitor.visit_none(), + Header::Simple(simple::NULL) => visitor.visit_none(), + header => { + self.decoder.push(header); + visitor.visit_some(self) + } + } + } + + #[inline] + fn deserialize_unit<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + loop { + return match self.decoder.pull()? { + Header::Simple(simple::UNDEFINED) => visitor.visit_unit(), + Header::Simple(simple::NULL) => visitor.visit_unit(), + Header::Tag(..) => continue, + header => Err(header.expected("unit")), + }; + } + } + + #[inline] + fn deserialize_unit_struct<V: de::Visitor<'de>>( + self, + _name: &'static str, + visitor: V, + ) -> Result<V::Value, Self::Error> { + self.deserialize_unit(visitor) + } + + #[inline] + fn deserialize_newtype_struct<V: de::Visitor<'de>>( + self, + _name: &'static str, + visitor: V, + ) -> Result<V::Value, Self::Error> { + visitor.visit_newtype_struct(self) + } + + #[inline] + fn deserialize_enum<V: de::Visitor<'de>>( + self, + name: &'static str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Self::Error> { + if name == "@@TAG@@" { + let tag = match self.decoder.pull()? { + Header::Tag(x) => Some(x), + header => { + self.decoder.push(header); + None + } + }; + + return self.recurse(|me| { + let access = crate::tag::TagAccess::new(me, tag); + visitor.visit_enum(access) + }); + } + + loop { + match self.decoder.pull()? { + Header::Tag(..) => continue, + Header::Map(Some(1)) => (), + header @ Header::Text(..) => self.decoder.push(header), + header => return Err(header.expected("enum")), + } + + return self.recurse(|me| { + let access = Access(me, Some(0)); + visitor.visit_enum(access) + }); + } + } + + #[inline] + fn is_human_readable(&self) -> bool { + false + } +} + +struct Access<'a, 'b, R: Read>(&'a mut Deserializer<'b, R>, Option<usize>); + +impl<'de, 'a, 'b, R: Read> de::SeqAccess<'de> for Access<'a, 'b, R> +where + R::Error: core::fmt::Debug, +{ + type Error = Error<R::Error>; + + #[inline] + fn next_element_seed<U: de::DeserializeSeed<'de>>( + &mut self, + seed: U, + ) -> Result<Option<U::Value>, Self::Error> { + match self.1 { + Some(0) => return Ok(None), + Some(x) => self.1 = Some(x - 1), + None => match self.0.decoder.pull()? { + Header::Break => return Ok(None), + header => self.0.decoder.push(header), + }, + } + + seed.deserialize(&mut *self.0).map(Some) + } + + #[inline] + fn size_hint(&self) -> Option<usize> { + self.1 + } +} + +impl<'de, 'a, 'b, R: Read> de::MapAccess<'de> for Access<'a, 'b, R> +where + R::Error: core::fmt::Debug, +{ + type Error = Error<R::Error>; + + #[inline] + fn next_key_seed<K: de::DeserializeSeed<'de>>( + &mut self, + seed: K, + ) -> Result<Option<K::Value>, Self::Error> { + match self.1 { + Some(0) => return Ok(None), + Some(x) => self.1 = Some(x - 1), + None => match self.0.decoder.pull()? { + Header::Break => return Ok(None), + header => self.0.decoder.push(header), + }, + } + + seed.deserialize(&mut *self.0).map(Some) + } + + #[inline] + fn next_value_seed<V: de::DeserializeSeed<'de>>( + &mut self, + seed: V, + ) -> Result<V::Value, Self::Error> { + seed.deserialize(&mut *self.0) + } + + #[inline] + fn size_hint(&self) -> Option<usize> { + self.1 + } +} + +impl<'de, 'a, 'b, R: Read> de::EnumAccess<'de> for Access<'a, 'b, R> +where + R::Error: core::fmt::Debug, +{ + type Error = Error<R::Error>; + type Variant = Self; + + #[inline] + fn variant_seed<V: de::DeserializeSeed<'de>>( + self, + seed: V, + ) -> Result<(V::Value, Self::Variant), Self::Error> { + let variant = seed.deserialize(&mut *self.0)?; + Ok((variant, self)) + } +} + +impl<'de, 'a, 'b, R: Read> de::VariantAccess<'de> for Access<'a, 'b, R> +where + R::Error: core::fmt::Debug, +{ + type Error = Error<R::Error>; + + #[inline] + fn unit_variant(self) -> Result<(), Self::Error> { + Ok(()) + } + + #[inline] + fn newtype_variant_seed<U: de::DeserializeSeed<'de>>( + self, + seed: U, + ) -> Result<U::Value, Self::Error> { + seed.deserialize(&mut *self.0) + } + + #[inline] + fn tuple_variant<V: de::Visitor<'de>>( + self, + _len: usize, + visitor: V, + ) -> Result<V::Value, Self::Error> { + self.0.deserialize_any(visitor) + } + + #[inline] + fn struct_variant<V: de::Visitor<'de>>( + self, + _fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Self::Error> { + self.0.deserialize_any(visitor) + } +} + +struct BytesAccess<R: Read>(usize, Vec<u8>, core::marker::PhantomData<R>); + +impl<'de, R: Read> de::SeqAccess<'de> for BytesAccess<R> +where + R::Error: core::fmt::Debug, +{ + type Error = Error<R::Error>; + + #[inline] + fn next_element_seed<U: de::DeserializeSeed<'de>>( + &mut self, + seed: U, + ) -> Result<Option<U::Value>, Self::Error> { + use de::IntoDeserializer; + + if self.0 < self.1.len() { + let byte = self.1[self.0]; + self.0 += 1; + seed.deserialize(byte.into_deserializer()).map(Some) + } else { + Ok(None) + } + } + + #[inline] + fn size_hint(&self) -> Option<usize> { + Some(self.1.len() - self.0) + } +} + +struct TagAccess<'a, 'b, R: Read>(&'a mut Deserializer<'b, R>, usize); + +impl<'de, 'a, 'b, R: Read> de::Deserializer<'de> for &mut TagAccess<'a, 'b, R> +where + R::Error: core::fmt::Debug, +{ + type Error = Error<R::Error>; + + #[inline] + fn deserialize_any<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + let offset = self.0.decoder.offset(); + + match self.0.decoder.pull()? { + Header::Tag(x) => visitor.visit_u64(x), + _ => Err(Error::semantic(offset, "expected tag")), + } + } + + forward_to_deserialize_any! { + i8 i16 i32 i64 i128 + u8 u16 u32 u64 u128 + bool f32 f64 + char str string + bytes byte_buf + seq map + struct tuple tuple_struct + identifier ignored_any + option unit unit_struct newtype_struct enum + } +} + +impl<'de, 'a, 'b, R: Read> de::SeqAccess<'de> for TagAccess<'a, 'b, R> +where + R::Error: core::fmt::Debug, +{ + type Error = Error<R::Error>; + + #[inline] + fn next_element_seed<U: de::DeserializeSeed<'de>>( + &mut self, + seed: U, + ) -> Result<Option<U::Value>, Self::Error> { + self.1 += 1; + + match self.1 { + 1 => seed.deserialize(self).map(Some), + 2 => seed.deserialize(&mut *self.0).map(Some), + _ => Ok(None), + } + } + + #[inline] + fn size_hint(&self) -> Option<usize> { + Some(match self.1 { + 0 => 2, + 1 => 1, + _ => 0, + }) + } +} + +/// Deserializes as CBOR from a type with [`impl ciborium_io::Read`](ciborium_io::Read) +#[inline] +pub fn from_reader<T: de::DeserializeOwned, R: Read>(reader: R) -> Result<T, Error<R::Error>> +where + R::Error: core::fmt::Debug, +{ + let mut scratch = [0; 4096]; + + let mut reader = Deserializer { + decoder: reader.into(), + scratch: &mut scratch, + recurse: 256, + }; + + T::deserialize(&mut reader) +} diff --git a/vendor/ciborium/src/lib.rs b/vendor/ciborium/src/lib.rs new file mode 100644 index 000000000..9696e5ffa --- /dev/null +++ b/vendor/ciborium/src/lib.rs @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! Welcome to Ciborium! +//! +//! Ciborium contains CBOR serialization and deserialization implementations for serde. +//! +//! # Quick Start +//! +//! You're probably looking for [`from_reader()`](crate::de::from_reader) +//! and [`into_writer()`](crate::ser::into_writer), which are +//! the main functions. Note that byte slices are also readers and writers and can be +//! passed to these functions just as streams can. +//! +//! For dynamic CBOR value creation/inspection, see [`Value`](crate::value::Value). +//! +//! # Design Decisions +//! +//! ## Always Serialize Numeric Values to the Smallest Size +//! +//! Although the CBOR specification has differing numeric widths, this is only +//! a form of compression on the wire and is not intended to directly +//! represent an "integer width" or "float width." Therefore, ciborium always +//! serializes numbers to the smallest possible lossless encoding. For example, +//! we serialize `1u128` as a single byte (`01`). Likewise, we will also freely +//! decode that single byte into a `u128`. +//! +//! While there is some minor performance cost for this, there are several +//! reasons for this choice. First, the specification seems to imply it by +//! using a separate bit for the sign. Second, the specification requires +//! that implementations handle leading zeroes; a liberal reading of which +//! implies a requirement for lossless coercion. Third, dynamic languages like +//! Python have no notion of "integer width," making this is a practical +//! choice for maximizing wire compatibility with those languages. +//! +//! This coercion is **always** lossless. For floats, this implies that we +//! only coerce to a smaller size if coercion back to the original size has +//! the same raw bits as the original. +//! +//! ## Compatibility with Other Implementations +//! +//! The ciborium project follows the [Robustness Principle](https://en.wikipedia.org/wiki/Robustness_principle). +//! Therefore, we aim to be liberal in what we accept. This implies that we +//! aim to be wire-compatible with other implementations in decoding, but +//! not necessarily encoding. +//! +//! One notable example of this is that `serde_cbor` uses fixed-width encoding +//! of numbers and doesn't losslessly coerce. This implies that `ciborium` will +//! successfully decode `serde_cbor` encodings, but the opposite may not be the +//! case. +//! +//! ## Representing Map as a Sequence of Values +//! +//! Other serde parsers have generally taken the route of using `BTreeMap` or +//! `HashMap` to implement their encoding's underlying `Map` type. This crate +//! chooses to represent the `Map` type using `Vec<(Value, Value)>` instead. +//! +//! This decision was made because this type preserves the order of the pairs +//! on the wire. Further, for those that need the properties of `BTreeMap` or +//! `HashMap`, you can simply `collect()` the values into the respective type. +//! This provides maximum flexibility. +//! +//! ## Low-level Library +//! +//! The ciborium crate has the beginnings of a low-level library in the +//! (private) `basic` module. We may extend this to be more robust and expose +//! it for application consumption once we have it in a good state. If you'd +//! like to collaborate with us on that, please contact us. Alternatively, +//! we might fork this code into a separate crate with no serde dependency. +//! +//! ## Internal Types +//! +//! The ciborium crate contains a number of internal types that implement +//! useful serde traits. While these are not currently exposed, we might +//! choose to expose them in the future if there is demand. Generally, this +//! crate takes a conservative approach to exposing APIs to avoid breakage. +//! +//! ## Packed Encoding? +//! +//! Packed encoding uses numerical offsets to represent structure field names +//! and enum variant names. This can save significant space on the wire. +//! +//! While the authors of this crate like packed encoding, it should generally +//! be avoided because it can be fragile as it exposes invariants of your Rust +//! code to remote actors. We might consider adding this in the future. If you +//! are interested in this, please contact us. + +#![cfg_attr(not(feature = "std"), no_std)] +#![deny(missing_docs)] +#![deny(clippy::all)] +#![deny(clippy::cargo)] +#![allow(clippy::unit_arg)] + +extern crate alloc; + +pub mod de; +pub mod ser; +pub mod tag; +pub mod value; + +// Re-export the [items recommended by serde](https://serde.rs/conventions.html). +#[doc(inline)] +pub use crate::de::from_reader; + +#[doc(inline)] +pub use crate::ser::into_writer; + +#[doc(inline)] +pub use crate::value::Value; + +/// Build a `Value` conveniently. +/// +/// The syntax should be intuitive if you are familiar with JSON. You can also +/// inline simple Rust expressions, including custom values that implement +/// `serde::Serialize`. Note that this macro returns `Result<Value, Error>`, +/// so you should handle the error appropriately. +/// +/// ``` +/// use ciborium::cbor; +/// +/// let value = cbor!({ +/// "code" => 415, +/// "message" => null, +/// "continue" => false, +/// "extra" => { "numbers" => [8.2341e+4, 0.251425] }, +/// }).unwrap(); +/// ``` +#[macro_export] +macro_rules! cbor { + (@map {$($key:expr => $val:expr),*} $(,)?) => {{ + $crate::value::Value::Map(vec![ + $( + (cbor!( $key )?, cbor!( $val )?) + ),* + ]) + }}; + + (@map {$($key:expr => $val:expr),*} { $($nkey:tt)* } => $($next:tt)*) => { + cbor!( + @map + { $($key => $val),* } + cbor!({ $($nkey)* })? => + $($next)* + ) + }; + + (@map {$($key:expr => $val:expr),*} [ $($nkey:tt)* ] => $($next:tt)*) => { + cbor!( + @map + { $($key => $val),* } + cbor!([ $($nkey)* ])? => + $($next)* + ) + }; + + (@map {$($key:expr => $val:expr),*} $nkey:expr => { $($nval:tt)* }, $($next:tt)*) => { + cbor!( + @map + { $($key => $val,)* $nkey => cbor!({ $($nval)* })? } + $($next)* + ) + }; + + (@map {$($key:expr => $val:expr),*} $nkey:expr => [ $($nval:tt)* ], $($next:tt)*) => { + cbor!( + @map + { $($key => $val,)* $nkey => cbor!([ $($nval)* ])? } + $($next)* + ) + }; + + (@map {$($key:expr => $val:expr),*} $nkey:expr => $nval:expr, $($next:tt)*) => { + cbor!( + @map + { $($key => $val,)* $nkey => cbor!($nval)? } + $($next)* + ) + }; + + (@seq [$($val:expr),*] $(,)?) => { + $crate::value::Value::Array( + vec![$( cbor!($val)? ),*] + ) + }; + + (@seq [$($val:expr),*] { $($item:tt)* }, $($next:tt)*) => { + cbor!( + @seq + [ $($val,)* cbor!({ $($item)* })? ] + $($next)* + ) + }; + + (@seq [$($val:expr),*] [ $($item:tt)* ], $($next:tt)*) => { + cbor!( + @seq + [ $($val,)* cbor!([ $($item)* ])? ] + $($next)* + ) + }; + + (@seq [$($val:expr),*] $item:expr, $($next:tt)*) => { + cbor!( + @seq + [ $($val,)* $item ] + $($next)* + ) + }; + + ({ $($next:tt)* }) => {(||{ + ::core::result::Result::<_, $crate::value::Error>::from(Ok(cbor!(@map {} $($next)* ,))) + })()}; + + ([ $($next:tt)* ]) => {(||{ + ::core::result::Result::<_, $crate::value::Error>::from(Ok(cbor!(@seq [] $($next)* ,))) + })()}; + + ($val:expr) => {{ + #[allow(unused_imports)] + use $crate::value::Value::Null as null; + $crate::value::Value::serialized(&$val) + }}; +} diff --git a/vendor/ciborium/src/ser/error.rs b/vendor/ciborium/src/ser/error.rs new file mode 100644 index 000000000..e90862845 --- /dev/null +++ b/vendor/ciborium/src/ser/error.rs @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: Apache-2.0 + +use alloc::string::{String, ToString}; +use core::fmt::{Debug, Display, Formatter, Result}; + +use serde::ser::{Error as SerError, StdError}; + +/// An error occurred during serialization +#[derive(Debug)] +pub enum Error<T> { + /// An error occurred while writing bytes + /// + /// Contains the underlying error reaturned while writing. + Io(T), + + /// An error indicating a value that cannot be serialized + /// + /// Contains a description of the problem. + Value(String), +} + +impl<T> From<T> for Error<T> { + #[inline] + fn from(value: T) -> Self { + Error::Io(value) + } +} + +impl<T: Debug> Display for Error<T> { + #[inline] + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + write!(f, "{:?}", self) + } +} + +impl<T: Debug> StdError for Error<T> {} + +impl<T: Debug> SerError for Error<T> { + fn custom<U: Display>(msg: U) -> Self { + Error::Value(msg.to_string()) + } +} diff --git a/vendor/ciborium/src/ser/mod.rs b/vendor/ciborium/src/ser/mod.rs new file mode 100644 index 000000000..ff3d11846 --- /dev/null +++ b/vendor/ciborium/src/ser/mod.rs @@ -0,0 +1,499 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! Serde serialization support for CBOR + +mod error; + +pub use error::Error; + +use alloc::string::ToString; + +use ciborium_io::Write; +use ciborium_ll::*; +use serde::{ser, Serialize as _}; + +struct Serializer<W: Write>(Encoder<W>); + +impl<W: Write> From<W> for Serializer<W> { + #[inline] + fn from(writer: W) -> Self { + Self(writer.into()) + } +} + +impl<W: Write> From<Encoder<W>> for Serializer<W> { + #[inline] + fn from(writer: Encoder<W>) -> Self { + Self(writer) + } +} + +impl<'a, W: Write> ser::Serializer for &'a mut Serializer<W> +where + W::Error: core::fmt::Debug, +{ + type Ok = (); + type Error = Error<W::Error>; + + type SerializeSeq = CollectionSerializer<'a, W>; + type SerializeTuple = CollectionSerializer<'a, W>; + type SerializeTupleStruct = CollectionSerializer<'a, W>; + type SerializeTupleVariant = CollectionSerializer<'a, W>; + type SerializeMap = CollectionSerializer<'a, W>; + type SerializeStruct = CollectionSerializer<'a, W>; + type SerializeStructVariant = CollectionSerializer<'a, W>; + + #[inline] + fn serialize_bool(self, v: bool) -> Result<(), Self::Error> { + Ok(self.0.push(match v { + false => Header::Simple(simple::FALSE), + true => Header::Simple(simple::TRUE), + })?) + } + + #[inline] + fn serialize_i8(self, v: i8) -> Result<(), Self::Error> { + self.serialize_i64(v.into()) + } + + #[inline] + fn serialize_i16(self, v: i16) -> Result<(), Self::Error> { + self.serialize_i64(v.into()) + } + + #[inline] + fn serialize_i32(self, v: i32) -> Result<(), Self::Error> { + self.serialize_i64(v.into()) + } + + #[inline] + fn serialize_i64(self, v: i64) -> Result<(), Self::Error> { + Ok(self.0.push(match v.is_negative() { + false => Header::Positive(v as u64), + true => Header::Negative(v as u64 ^ !0), + })?) + } + + #[inline] + fn serialize_i128(self, v: i128) -> Result<(), Self::Error> { + let (tag, raw) = match v.is_negative() { + false => (tag::BIGPOS, v as u128), + true => (tag::BIGNEG, v as u128 ^ !0), + }; + + match (tag, u64::try_from(raw)) { + (tag::BIGPOS, Ok(x)) => return Ok(self.0.push(Header::Positive(x))?), + (tag::BIGNEG, Ok(x)) => return Ok(self.0.push(Header::Negative(x))?), + _ => {} + } + + let bytes = raw.to_be_bytes(); + + // Skip leading zeros. + let mut slice = &bytes[..]; + while !slice.is_empty() && slice[0] == 0 { + slice = &slice[1..]; + } + + self.0.push(Header::Tag(tag))?; + self.0.push(Header::Bytes(Some(slice.len())))?; + Ok(self.0.write_all(slice)?) + } + + #[inline] + fn serialize_u8(self, v: u8) -> Result<(), Self::Error> { + self.serialize_u64(v.into()) + } + + #[inline] + fn serialize_u16(self, v: u16) -> Result<(), Self::Error> { + self.serialize_u64(v.into()) + } + + #[inline] + fn serialize_u32(self, v: u32) -> Result<(), Self::Error> { + self.serialize_u64(v.into()) + } + + #[inline] + fn serialize_u64(self, v: u64) -> Result<(), Self::Error> { + Ok(self.0.push(Header::Positive(v))?) + } + + #[inline] + fn serialize_u128(self, v: u128) -> Result<(), Self::Error> { + if let Ok(x) = u64::try_from(v) { + return self.serialize_u64(x); + } + + let bytes = v.to_be_bytes(); + + // Skip leading zeros. + let mut slice = &bytes[..]; + while !slice.is_empty() && slice[0] == 0 { + slice = &slice[1..]; + } + + self.0.push(Header::Tag(tag::BIGPOS))?; + self.0.push(Header::Bytes(Some(slice.len())))?; + Ok(self.0.write_all(slice)?) + } + + #[inline] + fn serialize_f32(self, v: f32) -> Result<(), Self::Error> { + self.serialize_f64(v.into()) + } + + #[inline] + fn serialize_f64(self, v: f64) -> Result<(), Self::Error> { + Ok(self.0.push(Header::Float(v))?) + } + + #[inline] + fn serialize_char(self, v: char) -> Result<(), Self::Error> { + self.serialize_str(&v.to_string()) + } + + #[inline] + fn serialize_str(self, v: &str) -> Result<(), Self::Error> { + let bytes = v.as_bytes(); + self.0.push(Header::Text(bytes.len().into()))?; + Ok(self.0.write_all(bytes)?) + } + + #[inline] + fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> { + self.0.push(Header::Bytes(v.len().into()))?; + Ok(self.0.write_all(v)?) + } + + #[inline] + fn serialize_none(self) -> Result<(), Self::Error> { + Ok(self.0.push(Header::Simple(simple::NULL))?) + } + + #[inline] + fn serialize_some<U: ?Sized + ser::Serialize>(self, value: &U) -> Result<(), Self::Error> { + value.serialize(self) + } + + #[inline] + fn serialize_unit(self) -> Result<(), Self::Error> { + self.serialize_none() + } + + #[inline] + fn serialize_unit_struct(self, _name: &'static str) -> Result<(), Self::Error> { + self.serialize_unit() + } + + #[inline] + fn serialize_unit_variant( + self, + _name: &'static str, + _index: u32, + variant: &'static str, + ) -> Result<(), Self::Error> { + self.serialize_str(variant) + } + + #[inline] + fn serialize_newtype_struct<U: ?Sized + ser::Serialize>( + self, + _name: &'static str, + value: &U, + ) -> Result<(), Self::Error> { + value.serialize(self) + } + + #[inline] + fn serialize_newtype_variant<U: ?Sized + ser::Serialize>( + self, + name: &'static str, + _index: u32, + variant: &'static str, + value: &U, + ) -> Result<(), Self::Error> { + if name != "@@TAG@@" || variant != "@@UNTAGGED@@" { + self.0.push(Header::Map(Some(1)))?; + self.serialize_str(variant)?; + } + + value.serialize(self) + } + + #[inline] + fn serialize_seq(self, length: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + self.0.push(Header::Array(length))?; + Ok(CollectionSerializer { + encoder: self, + ending: length.is_none(), + tag: false, + }) + } + + #[inline] + fn serialize_tuple(self, length: usize) -> Result<Self::SerializeTuple, Self::Error> { + self.serialize_seq(Some(length)) + } + + #[inline] + fn serialize_tuple_struct( + self, + _name: &'static str, + length: usize, + ) -> Result<Self::SerializeTupleStruct, Self::Error> { + self.serialize_seq(Some(length)) + } + + #[inline] + fn serialize_tuple_variant( + self, + name: &'static str, + _index: u32, + variant: &'static str, + length: usize, + ) -> Result<Self::SerializeTupleVariant, Self::Error> { + match (name, variant) { + ("@@TAG@@", "@@TAGGED@@") => Ok(CollectionSerializer { + encoder: self, + ending: false, + tag: true, + }), + + _ => { + self.0.push(Header::Map(Some(1)))?; + self.serialize_str(variant)?; + self.0.push(Header::Array(Some(length)))?; + Ok(CollectionSerializer { + encoder: self, + ending: false, + tag: false, + }) + } + } + } + + #[inline] + fn serialize_map(self, length: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { + self.0.push(Header::Map(length))?; + Ok(CollectionSerializer { + encoder: self, + ending: length.is_none(), + tag: false, + }) + } + + #[inline] + fn serialize_struct( + self, + _name: &'static str, + length: usize, + ) -> Result<Self::SerializeStruct, Self::Error> { + self.0.push(Header::Map(Some(length)))?; + Ok(CollectionSerializer { + encoder: self, + ending: false, + tag: false, + }) + } + + #[inline] + fn serialize_struct_variant( + self, + _name: &'static str, + _index: u32, + variant: &'static str, + length: usize, + ) -> Result<Self::SerializeStructVariant, Self::Error> { + self.0.push(Header::Map(Some(1)))?; + self.serialize_str(variant)?; + self.0.push(Header::Map(Some(length)))?; + Ok(CollectionSerializer { + encoder: self, + ending: false, + tag: false, + }) + } + + #[inline] + fn is_human_readable(&self) -> bool { + false + } +} + +macro_rules! end { + () => { + #[inline] + fn end(self) -> Result<(), Self::Error> { + if self.ending { + self.encoder.0.push(Header::Break)?; + } + + Ok(()) + } + }; +} + +struct CollectionSerializer<'a, W: Write> { + encoder: &'a mut Serializer<W>, + ending: bool, + tag: bool, +} + +impl<'a, W: Write> ser::SerializeSeq for CollectionSerializer<'a, W> +where + W::Error: core::fmt::Debug, +{ + type Ok = (); + type Error = Error<W::Error>; + + #[inline] + fn serialize_element<U: ?Sized + ser::Serialize>( + &mut self, + value: &U, + ) -> Result<(), Self::Error> { + value.serialize(&mut *self.encoder) + } + + end!(); +} + +impl<'a, W: Write> ser::SerializeTuple for CollectionSerializer<'a, W> +where + W::Error: core::fmt::Debug, +{ + type Ok = (); + type Error = Error<W::Error>; + + #[inline] + fn serialize_element<U: ?Sized + ser::Serialize>( + &mut self, + value: &U, + ) -> Result<(), Self::Error> { + value.serialize(&mut *self.encoder) + } + + end!(); +} + +impl<'a, W: Write> ser::SerializeTupleStruct for CollectionSerializer<'a, W> +where + W::Error: core::fmt::Debug, +{ + type Ok = (); + type Error = Error<W::Error>; + + #[inline] + fn serialize_field<U: ?Sized + ser::Serialize>( + &mut self, + value: &U, + ) -> Result<(), Self::Error> { + value.serialize(&mut *self.encoder) + } + + end!(); +} + +impl<'a, W: Write> ser::SerializeTupleVariant for CollectionSerializer<'a, W> +where + W::Error: core::fmt::Debug, +{ + type Ok = (); + type Error = Error<W::Error>; + + #[inline] + fn serialize_field<U: ?Sized + ser::Serialize>( + &mut self, + value: &U, + ) -> Result<(), Self::Error> { + if !self.tag { + return value.serialize(&mut *self.encoder); + } + + self.tag = false; + match value.serialize(crate::tag::Serializer) { + Ok(x) => Ok(self.encoder.0.push(Header::Tag(x))?), + _ => Err(Error::Value("expected tag".into())), + } + } + + end!(); +} + +impl<'a, W: Write> ser::SerializeMap for CollectionSerializer<'a, W> +where + W::Error: core::fmt::Debug, +{ + type Ok = (); + type Error = Error<W::Error>; + + #[inline] + fn serialize_key<U: ?Sized + ser::Serialize>(&mut self, key: &U) -> Result<(), Self::Error> { + key.serialize(&mut *self.encoder) + } + + #[inline] + fn serialize_value<U: ?Sized + ser::Serialize>( + &mut self, + value: &U, + ) -> Result<(), Self::Error> { + value.serialize(&mut *self.encoder) + } + + end!(); +} + +impl<'a, W: Write> ser::SerializeStruct for CollectionSerializer<'a, W> +where + W::Error: core::fmt::Debug, +{ + type Ok = (); + type Error = Error<W::Error>; + + #[inline] + fn serialize_field<U: ?Sized + ser::Serialize>( + &mut self, + key: &'static str, + value: &U, + ) -> Result<(), Self::Error> { + key.serialize(&mut *self.encoder)?; + value.serialize(&mut *self.encoder)?; + Ok(()) + } + + end!(); +} + +impl<'a, W: Write> ser::SerializeStructVariant for CollectionSerializer<'a, W> +where + W::Error: core::fmt::Debug, +{ + type Ok = (); + type Error = Error<W::Error>; + + #[inline] + fn serialize_field<U: ?Sized + ser::Serialize>( + &mut self, + key: &'static str, + value: &U, + ) -> Result<(), Self::Error> { + key.serialize(&mut *self.encoder)?; + value.serialize(&mut *self.encoder) + } + + end!(); +} + +/// Serializes as CBOR into a type with [`impl ciborium_io::Write`](ciborium_io::Write) +#[inline] +pub fn into_writer<T: ?Sized + ser::Serialize, W: Write>( + value: &T, + writer: W, +) -> Result<(), Error<W::Error>> +where + W::Error: core::fmt::Debug, +{ + let mut encoder = Serializer::from(writer); + value.serialize(&mut encoder) +} diff --git a/vendor/ciborium/src/tag.rs b/vendor/ciborium/src/tag.rs new file mode 100644 index 000000000..11965758d --- /dev/null +++ b/vendor/ciborium/src/tag.rs @@ -0,0 +1,545 @@ +//! Contains helper types for dealing with CBOR tags + +use serde::{de, de::Error as _, forward_to_deserialize_any, ser, Deserialize, Serialize}; + +#[derive(Deserialize, Serialize)] +#[serde(rename = "@@TAG@@")] +enum Internal<T> { + #[serde(rename = "@@UNTAGGED@@")] + Untagged(T), + + #[serde(rename = "@@TAGGED@@")] + Tagged(u64, T), +} + +/// An optional CBOR tag and its data item +/// +/// No semantic evaluation of the tag is made. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Captured<V>(pub Option<u64>, pub V); + +impl<'de, V: Deserialize<'de>> Deserialize<'de> for Captured<V> { + #[inline] + fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { + match Internal::deserialize(deserializer)? { + Internal::Tagged(t, v) => Ok(Captured(Some(t), v)), + Internal::Untagged(v) => Ok(Captured(None, v)), + } + } +} + +impl<V: Serialize> Serialize for Captured<V> { + #[inline] + fn serialize<S: ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + match self.0 { + Some(tag) => Internal::Tagged(tag, &self.1).serialize(serializer), + None => Internal::Untagged(&self.1).serialize(serializer), + } + } +} + +/// A required CBOR tag +/// +/// This data type indicates that the specified tag, and **only** that tag, +/// is required during deserialization. If the tag is missing, deserialization +/// will fail. The tag will always be emitted during serialization. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Required<V, const TAG: u64>(pub V); + +impl<'de, V: Deserialize<'de>, const TAG: u64> Deserialize<'de> for Required<V, TAG> { + #[inline] + fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { + match Internal::deserialize(deserializer)? { + Internal::Tagged(t, v) if t == TAG => Ok(Required(v)), + _ => Err(de::Error::custom("required tag not found")), + } + } +} + +impl<V: Serialize, const TAG: u64> Serialize for Required<V, TAG> { + #[inline] + fn serialize<S: ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + Internal::Tagged(TAG, &self.0).serialize(serializer) + } +} + +/// An optional CBOR tag +/// +/// This data type indicates that the specified tag, and **only** that tag, +/// is accepted, but not required, during deserialization. The tag will always +/// be emitted during serialization. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Accepted<V, const TAG: u64>(pub V); + +impl<'de, V: Deserialize<'de>, const TAG: u64> Deserialize<'de> for Accepted<V, TAG> { + #[inline] + fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { + match Internal::deserialize(deserializer)? { + Internal::Tagged(t, v) if t == TAG => Ok(Accepted(v)), + Internal::Untagged(v) => Ok(Accepted(v)), + _ => Err(de::Error::custom("required tag not found")), + } + } +} + +impl<V: Serialize, const TAG: u64> Serialize for Accepted<V, TAG> { + #[inline] + fn serialize<S: ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + Internal::Tagged(TAG, &self.0).serialize(serializer) + } +} + +pub(crate) struct TagAccess<D> { + parent: Option<D>, + state: usize, + tag: Option<u64>, +} + +impl<D> TagAccess<D> { + pub fn new(parent: D, tag: Option<u64>) -> Self { + Self { + parent: Some(parent), + state: 0, + tag, + } + } +} + +impl<'de, D: de::Deserializer<'de>> de::Deserializer<'de> for &mut TagAccess<D> { + type Error = D::Error; + + #[inline] + fn deserialize_any<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + self.state += 1; + + match self.state { + 1 => visitor.visit_str(match self.tag { + Some(..) => "@@TAGGED@@", + None => "@@UNTAGGED@@", + }), + + _ => visitor.visit_u64(self.tag.unwrap()), + } + } + + forward_to_deserialize_any! { + i8 i16 i32 i64 i128 + u8 u16 u32 u64 u128 + bool f32 f64 + char str string + bytes byte_buf + seq map + struct tuple tuple_struct + identifier ignored_any + option unit unit_struct newtype_struct enum + } +} + +impl<'de, D: de::Deserializer<'de>> de::EnumAccess<'de> for TagAccess<D> { + type Error = D::Error; + type Variant = Self; + + #[inline] + fn variant_seed<V: de::DeserializeSeed<'de>>( + mut self, + seed: V, + ) -> Result<(V::Value, Self::Variant), Self::Error> { + let variant = seed.deserialize(&mut self)?; + Ok((variant, self)) + } +} + +impl<'de, D: de::Deserializer<'de>> de::VariantAccess<'de> for TagAccess<D> { + type Error = D::Error; + + #[inline] + fn unit_variant(self) -> Result<(), Self::Error> { + Err(Self::Error::custom("expected tag")) + } + + #[inline] + fn newtype_variant_seed<U: de::DeserializeSeed<'de>>( + mut self, + seed: U, + ) -> Result<U::Value, Self::Error> { + seed.deserialize(self.parent.take().unwrap()) + } + + #[inline] + fn tuple_variant<V: de::Visitor<'de>>( + self, + _len: usize, + visitor: V, + ) -> Result<V::Value, Self::Error> { + visitor.visit_seq(self) + } + + #[inline] + fn struct_variant<V: de::Visitor<'de>>( + self, + _fields: &'static [&'static str], + _visitor: V, + ) -> Result<V::Value, Self::Error> { + Err(Self::Error::custom("expected tag")) + } +} + +impl<'de, D: de::Deserializer<'de>> de::SeqAccess<'de> for TagAccess<D> { + type Error = D::Error; + + #[inline] + fn next_element_seed<T: de::DeserializeSeed<'de>>( + &mut self, + seed: T, + ) -> Result<Option<T::Value>, Self::Error> { + if self.state < 2 { + return Ok(Some(seed.deserialize(self)?)); + } + + Ok(match self.parent.take() { + Some(x) => Some(seed.deserialize(x)?), + None => None, + }) + } +} + +#[derive(Debug)] +pub(crate) struct Error; + +impl core::fmt::Display for Error { + #[inline] + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:?}", self) + } +} + +impl ser::StdError for Error {} + +impl ser::Error for Error { + fn custom<U: core::fmt::Display>(_msg: U) -> Self { + Error + } +} + +pub(crate) struct Serializer; + +impl ser::Serializer for Serializer { + type Ok = u64; + type Error = Error; + + type SerializeSeq = Self; + type SerializeTuple = Self; + type SerializeTupleStruct = Self; + type SerializeTupleVariant = Self; + type SerializeMap = Self; + type SerializeStruct = Self; + type SerializeStructVariant = Self; + + #[inline] + fn serialize_bool(self, _: bool) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_i8(self, _: i8) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_i16(self, _: i16) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_i32(self, _: i32) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_i64(self, _: i64) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_i128(self, _: i128) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_u8(self, v: u8) -> Result<u64, Self::Error> { + Ok(v.into()) + } + + #[inline] + fn serialize_u16(self, v: u16) -> Result<u64, Self::Error> { + Ok(v.into()) + } + + #[inline] + fn serialize_u32(self, v: u32) -> Result<u64, Self::Error> { + Ok(v.into()) + } + + #[inline] + fn serialize_u64(self, v: u64) -> Result<u64, Self::Error> { + Ok(v) + } + + #[inline] + fn serialize_u128(self, _: u128) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_f32(self, _: f32) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_f64(self, _: f64) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_char(self, _: char) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_str(self, _: &str) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_bytes(self, _: &[u8]) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_none(self) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_some<U: ?Sized + ser::Serialize>(self, _: &U) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_unit(self) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_unit_struct(self, _name: &'static str) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_unit_variant( + self, + _name: &'static str, + _index: u32, + _variant: &'static str, + ) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_newtype_struct<U: ?Sized + ser::Serialize>( + self, + _name: &'static str, + _value: &U, + ) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_newtype_variant<U: ?Sized + ser::Serialize>( + self, + _name: &'static str, + _index: u32, + _variant: &'static str, + _value: &U, + ) -> Result<u64, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_seq(self, _length: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_tuple(self, _length: usize) -> Result<Self::SerializeTuple, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_tuple_struct( + self, + _name: &'static str, + _length: usize, + ) -> Result<Self::SerializeTupleStruct, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_tuple_variant( + self, + _name: &'static str, + _index: u32, + _variant: &'static str, + _length: usize, + ) -> Result<Self::SerializeTupleVariant, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_map(self, _length: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_struct( + self, + _name: &'static str, + _length: usize, + ) -> Result<Self::SerializeStruct, Self::Error> { + Err(Error) + } + + #[inline] + fn serialize_struct_variant( + self, + _name: &'static str, + _index: u32, + _variant: &'static str, + _length: usize, + ) -> Result<Self::SerializeStructVariant, Self::Error> { + Err(Error) + } + + #[inline] + fn is_human_readable(&self) -> bool { + false + } +} + +impl ser::SerializeSeq for Serializer { + type Ok = u64; + type Error = Error; + + #[inline] + fn serialize_element<U: ?Sized + ser::Serialize>(&mut self, _value: &U) -> Result<(), Error> { + Err(Error) + } + + #[inline] + fn end(self) -> Result<Self::Ok, Self::Error> { + Err(Error) + } +} + +impl ser::SerializeTuple for Serializer { + type Ok = u64; + type Error = Error; + + #[inline] + fn serialize_element<U: ?Sized + ser::Serialize>(&mut self, _value: &U) -> Result<(), Error> { + Err(Error) + } + + #[inline] + fn end(self) -> Result<Self::Ok, Self::Error> { + Err(Error) + } +} + +impl ser::SerializeTupleStruct for Serializer { + type Ok = u64; + type Error = Error; + + #[inline] + fn serialize_field<U: ?Sized + ser::Serialize>(&mut self, _value: &U) -> Result<(), Error> { + Err(Error) + } + + #[inline] + fn end(self) -> Result<Self::Ok, Self::Error> { + Err(Error) + } +} + +impl ser::SerializeTupleVariant for Serializer { + type Ok = u64; + type Error = Error; + + #[inline] + fn serialize_field<U: ?Sized + ser::Serialize>(&mut self, _value: &U) -> Result<(), Error> { + Err(Error) + } + + #[inline] + fn end(self) -> Result<Self::Ok, Self::Error> { + Err(Error) + } +} + +impl ser::SerializeMap for Serializer { + type Ok = u64; + type Error = Error; + + #[inline] + fn serialize_key<U: ?Sized + ser::Serialize>(&mut self, _key: &U) -> Result<(), Error> { + Err(Error) + } + + #[inline] + fn serialize_value<U: ?Sized + ser::Serialize>(&mut self, _value: &U) -> Result<(), Error> { + Err(Error) + } + + #[inline] + fn end(self) -> Result<Self::Ok, Self::Error> { + Err(Error) + } +} + +impl ser::SerializeStruct for Serializer { + type Ok = u64; + type Error = Error; + + #[inline] + fn serialize_field<U: ?Sized + ser::Serialize>( + &mut self, + _key: &'static str, + _value: &U, + ) -> Result<(), Error> { + Err(Error) + } + + #[inline] + fn end(self) -> Result<Self::Ok, Self::Error> { + Err(Error) + } +} + +impl ser::SerializeStructVariant for Serializer { + type Ok = u64; + type Error = Error; + + #[inline] + fn serialize_field<U: ?Sized + ser::Serialize>( + &mut self, + _key: &'static str, + _value: &U, + ) -> Result<(), Self::Error> { + Err(Error) + } + + #[inline] + fn end(self) -> Result<Self::Ok, Self::Error> { + Err(Error) + } +} diff --git a/vendor/ciborium/src/value/canonical.rs b/vendor/ciborium/src/value/canonical.rs new file mode 100644 index 000000000..f1196f4d0 --- /dev/null +++ b/vendor/ciborium/src/value/canonical.rs @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: Apache-2.0 + +use crate::value::Value; +use alloc::vec::Vec; +use core::cmp::Ordering; +use serde::{de, ser}; + +/// Manually serialize values to compare them. +fn serialized_canonical_cmp(v1: &Value, v2: &Value) -> Ordering { + // There is an optimization to be done here, but it would take a lot more code + // and using mixing keys, Arrays or Maps as CanonicalValue is probably not the + // best use of this type as it is meant mainly to be used as keys. + + let mut bytes1 = Vec::new(); + let _ = crate::ser::into_writer(v1, &mut bytes1); + let mut bytes2 = Vec::new(); + let _ = crate::ser::into_writer(v2, &mut bytes2); + + match bytes1.len().cmp(&bytes2.len()) { + Ordering::Equal => bytes1.cmp(&bytes2), + x => x, + } +} + +/// Compares two values uses canonical comparison, as defined in both +/// RFC 7049 Section 3.9 (regarding key sorting) and RFC 8949 4.2.3 (as errata). +/// +/// In short, the comparison follow the following rules: +/// - If two keys have different lengths, the shorter one sorts earlier; +/// - If two keys have the same length, the one with the lower value in +/// (byte-wise) lexical order sorts earlier. +/// +/// This specific comparison allows Maps and sorting that respect these two rules. +pub fn cmp_value(v1: &Value, v2: &Value) -> Ordering { + use Value::*; + + match (v1, v2) { + (Integer(i), Integer(o)) => { + // Because of the first rule above, two numbers might be in a different + // order than regular i128 comparison. For example, 10 < -1 in + // canonical ordering, since 10 serializes to `0x0a` and -1 to `0x20`, + // and -1 < -1000 because of their lengths. + i.canonical_cmp(o) + } + (Text(s), Text(o)) => match s.len().cmp(&o.len()) { + Ordering::Equal => s.cmp(o), + x => x, + }, + (Bool(s), Bool(o)) => s.cmp(o), + (Null, Null) => Ordering::Equal, + (Tag(t, v), Tag(ot, ov)) => match Value::from(*t).partial_cmp(&Value::from(*ot)) { + Some(Ordering::Equal) | None => match v.partial_cmp(ov) { + Some(x) => x, + None => serialized_canonical_cmp(v1, v2), + }, + Some(x) => x, + }, + (_, _) => serialized_canonical_cmp(v1, v2), + } +} + +/// A CBOR Value that impl Ord and Eq to allow sorting of values as defined in both +/// RFC 7049 Section 3.9 (regarding key sorting) and RFC 8949 4.2.3 (as errata). +/// +/// Since a regular [Value] can be +#[derive(Clone, Debug)] +pub struct CanonicalValue(Value); + +impl PartialEq for CanonicalValue { + fn eq(&self, other: &Self) -> bool { + self.cmp(other) == Ordering::Equal + } +} + +impl Eq for CanonicalValue {} + +impl From<Value> for CanonicalValue { + fn from(v: Value) -> Self { + Self(v) + } +} + +impl From<CanonicalValue> for Value { + fn from(v: CanonicalValue) -> Self { + v.0 + } +} + +impl ser::Serialize for CanonicalValue { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + self.0.serialize(serializer) + } +} + +impl<'de> de::Deserialize<'de> for CanonicalValue { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: de::Deserializer<'de>, + { + Value::deserialize(deserializer).map(Into::into) + } + + fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error> + where + D: de::Deserializer<'de>, + { + Value::deserialize_in_place(deserializer, &mut place.0) + } +} + +impl Ord for CanonicalValue { + fn cmp(&self, other: &Self) -> Ordering { + cmp_value(&self.0, &other.0) + } +} + +impl PartialOrd for CanonicalValue { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(cmp_value(&self.0, &other.0)) + } +} diff --git a/vendor/ciborium/src/value/de.rs b/vendor/ciborium/src/value/de.rs new file mode 100644 index 000000000..63231905a --- /dev/null +++ b/vendor/ciborium/src/value/de.rs @@ -0,0 +1,616 @@ +// SPDX-License-Identifier: Apache-2.0 + +use super::{Error, Integer, Value}; + +use alloc::{boxed::Box, string::String, vec::Vec}; +use core::iter::Peekable; + +use ciborium_ll::tag; +use serde::de::{self, Deserializer as _}; + +impl<'a> From<Integer> for de::Unexpected<'a> { + #[inline] + fn from(value: Integer) -> Self { + u64::try_from(value) + .map(de::Unexpected::Unsigned) + .unwrap_or_else(|_| { + i64::try_from(value) + .map(de::Unexpected::Signed) + .unwrap_or_else(|_| de::Unexpected::Other("large integer")) + }) + } +} + +impl<'a> From<&'a Value> for de::Unexpected<'a> { + #[inline] + fn from(value: &'a Value) -> Self { + match value { + Value::Bool(x) => Self::Bool(*x), + Value::Integer(x) => Self::from(*x), + Value::Float(x) => Self::Float(*x), + Value::Bytes(x) => Self::Bytes(x), + Value::Text(x) => Self::Str(x), + Value::Array(..) => Self::Seq, + Value::Map(..) => Self::Map, + Value::Null => Self::Other("null"), + Value::Tag(..) => Self::Other("tag"), + } + } +} + +macro_rules! mkvisit { + ($($f:ident($v:ty)),+ $(,)?) => { + $( + #[inline] + fn $f<E: de::Error>(self, v: $v) -> Result<Self::Value, E> { + Ok(v.into()) + } + )+ + }; +} + +struct Visitor; + +impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = Value; + + fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(formatter, "a valid CBOR item") + } + + mkvisit! { + visit_bool(bool), + visit_f32(f32), + visit_f64(f64), + + visit_i8(i8), + visit_i16(i16), + visit_i32(i32), + visit_i64(i64), + visit_i128(i128), + + visit_u8(u8), + visit_u16(u16), + visit_u32(u32), + visit_u64(u64), + visit_u128(u128), + + visit_char(char), + visit_str(&str), + visit_borrowed_str(&'de str), + visit_string(String), + + visit_bytes(&[u8]), + visit_borrowed_bytes(&'de [u8]), + visit_byte_buf(Vec<u8>), + } + + #[inline] + fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> { + Ok(Value::Null) + } + + #[inline] + fn visit_some<D: de::Deserializer<'de>>( + self, + deserializer: D, + ) -> Result<Self::Value, D::Error> { + deserializer.deserialize_any(self) + } + + #[inline] + fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> { + Ok(Value::Null) + } + + #[inline] + fn visit_newtype_struct<D: de::Deserializer<'de>>( + self, + deserializer: D, + ) -> Result<Self::Value, D::Error> { + deserializer.deserialize_any(self) + } + + #[inline] + fn visit_seq<A: de::SeqAccess<'de>>(self, mut acc: A) -> Result<Self::Value, A::Error> { + let mut seq = Vec::new(); + + while let Some(elem) = acc.next_element()? { + seq.push(elem); + } + + Ok(Value::Array(seq)) + } + + #[inline] + fn visit_map<A: de::MapAccess<'de>>(self, mut acc: A) -> Result<Self::Value, A::Error> { + let mut map = Vec::<(Value, Value)>::new(); + + while let Some(kv) = acc.next_entry()? { + map.push(kv); + } + + Ok(Value::Map(map)) + } + + #[inline] + fn visit_enum<A: de::EnumAccess<'de>>(self, acc: A) -> Result<Self::Value, A::Error> { + use serde::de::VariantAccess; + + struct Inner; + + impl<'de> serde::de::Visitor<'de> for Inner { + type Value = Value; + + fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(formatter, "a valid CBOR item") + } + + #[inline] + fn visit_seq<A: de::SeqAccess<'de>>(self, mut acc: A) -> Result<Self::Value, A::Error> { + let tag: u64 = acc + .next_element()? + .ok_or_else(|| de::Error::custom("expected tag"))?; + let val = acc + .next_element()? + .ok_or_else(|| de::Error::custom("expected val"))?; + Ok(Value::Tag(tag, Box::new(val))) + } + } + + let (name, data): (String, _) = acc.variant()?; + assert_eq!("@@TAGGED@@", name); + data.tuple_variant(2, Inner) + } +} + +impl<'de> de::Deserialize<'de> for Value { + #[inline] + fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { + deserializer.deserialize_any(Visitor) + } +} + +struct Deserializer<T>(T); + +impl<'a> Deserializer<&'a Value> { + fn integer<N>(&self, kind: &'static str) -> Result<N, Error> + where + N: TryFrom<u128>, + N: TryFrom<i128>, + { + fn raw(value: &Value) -> Result<u128, Error> { + let mut buffer = 0u128.to_ne_bytes(); + let length = buffer.len(); + + let bytes = match value { + Value::Bytes(bytes) => { + // Skip leading zeros... + let mut bytes: &[u8] = bytes.as_ref(); + while bytes.len() > buffer.len() && bytes[0] == 0 { + bytes = &bytes[1..]; + } + + if bytes.len() > buffer.len() { + return Err(de::Error::custom("bigint too large")); + } + + bytes + } + + _ => return Err(de::Error::invalid_type(value.into(), &"bytes")), + }; + + buffer[length - bytes.len()..].copy_from_slice(bytes); + Ok(u128::from_be_bytes(buffer)) + } + + let err = || de::Error::invalid_type(self.0.into(), &kind); + + Ok(match self.0 { + Value::Integer(x) => i128::from(*x).try_into().map_err(|_| err())?, + Value::Tag(t, v) if *t == tag::BIGPOS => raw(v)?.try_into().map_err(|_| err())?, + Value::Tag(t, v) if *t == tag::BIGNEG => i128::try_from(raw(v)?) + .map(|x| x ^ !0) + .map_err(|_| err()) + .and_then(|x| x.try_into().map_err(|_| err()))?, + _ => return Err(de::Error::invalid_type(self.0.into(), &"(big)int")), + }) + } +} + +impl<'a, 'de> de::Deserializer<'de> for Deserializer<&'a Value> { + type Error = Error; + + #[inline] + fn deserialize_any<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + match self.0 { + Value::Bytes(x) => visitor.visit_bytes(x), + Value::Text(x) => visitor.visit_str(x), + Value::Array(x) => visitor.visit_seq(Deserializer(x.iter())), + Value::Map(x) => visitor.visit_map(Deserializer(x.iter().peekable())), + Value::Bool(x) => visitor.visit_bool(*x), + Value::Null => visitor.visit_none(), + + Value::Tag(t, v) => { + let parent: Deserializer<&Value> = Deserializer(v); + let access = crate::tag::TagAccess::new(parent, Some(*t)); + visitor.visit_enum(access) + } + + Value::Integer(x) => { + if let Ok(x) = u64::try_from(*x) { + visitor.visit_u64(x) + } else if let Ok(x) = i64::try_from(*x) { + visitor.visit_i64(x) + } else if let Ok(x) = i128::try_from(*x) { + visitor.visit_i128(x) + } else { + unreachable!() + } + } + + Value::Float(x) => visitor.visit_f64(*x), + } + } + + #[inline] + fn deserialize_bool<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + let mut value = self.0; + while let Value::Tag(.., v) = value { + value = v; + } + + match value { + Value::Bool(x) => visitor.visit_bool(*x), + _ => Err(de::Error::invalid_type(value.into(), &"bool")), + } + } + + #[inline] + fn deserialize_f32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + self.deserialize_f64(visitor) + } + + #[inline] + fn deserialize_f64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + let mut value = self.0; + while let Value::Tag(.., v) = value { + value = v; + } + + match value { + Value::Float(x) => visitor.visit_f64(*x), + _ => Err(de::Error::invalid_type(value.into(), &"f64")), + } + } + + fn deserialize_i8<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + visitor.visit_i8(self.integer("i8")?) + } + + fn deserialize_i16<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + visitor.visit_i16(self.integer("i16")?) + } + + fn deserialize_i32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + visitor.visit_i32(self.integer("i32")?) + } + + fn deserialize_i64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + visitor.visit_i64(self.integer("i64")?) + } + + fn deserialize_i128<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + visitor.visit_i128(self.integer("i128")?) + } + + fn deserialize_u8<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + visitor.visit_u8(self.integer("u8")?) + } + + fn deserialize_u16<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + visitor.visit_u16(self.integer("u16")?) + } + + fn deserialize_u32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + visitor.visit_u32(self.integer("u32")?) + } + + fn deserialize_u64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + visitor.visit_u64(self.integer("u64")?) + } + + fn deserialize_u128<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + visitor.visit_u128(self.integer("u128")?) + } + + fn deserialize_char<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + let mut value = self.0; + while let Value::Tag(.., v) = value { + value = v; + } + + match value { + Value::Text(x) => match x.chars().count() { + 1 => visitor.visit_char(x.chars().next().unwrap()), + _ => Err(de::Error::invalid_type(value.into(), &"char")), + }, + + _ => Err(de::Error::invalid_type(value.into(), &"char")), + } + } + + fn deserialize_str<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + let mut value = self.0; + while let Value::Tag(.., v) = value { + value = v; + } + + match value { + Value::Text(x) => visitor.visit_str(x), + _ => Err(de::Error::invalid_type(value.into(), &"str")), + } + } + + fn deserialize_string<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + self.deserialize_str(visitor) + } + + fn deserialize_bytes<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + let mut value = self.0; + while let Value::Tag(.., v) = value { + value = v; + } + + match value { + Value::Bytes(x) => visitor.visit_bytes(x), + _ => Err(de::Error::invalid_type(value.into(), &"bytes")), + } + } + + fn deserialize_byte_buf<V: de::Visitor<'de>>( + self, + visitor: V, + ) -> Result<V::Value, Self::Error> { + self.deserialize_bytes(visitor) + } + + fn deserialize_seq<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + let mut value = self.0; + while let Value::Tag(.., v) = value { + value = v; + } + + match value { + Value::Array(x) => visitor.visit_seq(Deserializer(x.iter())), + _ => Err(de::Error::invalid_type(value.into(), &"array")), + } + } + + fn deserialize_map<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + let mut value = self.0; + while let Value::Tag(.., v) = value { + value = v; + } + + match value { + Value::Map(x) => visitor.visit_map(Deserializer(x.iter().peekable())), + _ => Err(de::Error::invalid_type(value.into(), &"map")), + } + } + + fn deserialize_struct<V: de::Visitor<'de>>( + self, + _name: &'static str, + _fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Self::Error> { + self.deserialize_map(visitor) + } + + fn deserialize_tuple<V: de::Visitor<'de>>( + self, + _len: usize, + visitor: V, + ) -> Result<V::Value, Self::Error> { + self.deserialize_seq(visitor) + } + + fn deserialize_tuple_struct<V: de::Visitor<'de>>( + self, + _name: &'static str, + _len: usize, + visitor: V, + ) -> Result<V::Value, Self::Error> { + self.deserialize_seq(visitor) + } + + fn deserialize_identifier<V: de::Visitor<'de>>( + self, + visitor: V, + ) -> Result<V::Value, Self::Error> { + self.deserialize_str(visitor) + } + + fn deserialize_ignored_any<V: de::Visitor<'de>>( + self, + visitor: V, + ) -> Result<V::Value, Self::Error> { + self.deserialize_any(visitor) + } + + #[inline] + fn deserialize_option<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + match self.0 { + Value::Null => visitor.visit_none(), + x => visitor.visit_some(Self(x)), + } + } + + #[inline] + fn deserialize_unit<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> { + match self.0 { + Value::Null => visitor.visit_unit(), + _ => Err(de::Error::invalid_type(self.0.into(), &"null")), + } + } + + #[inline] + fn deserialize_unit_struct<V: de::Visitor<'de>>( + self, + _name: &'static str, + visitor: V, + ) -> Result<V::Value, Self::Error> { + self.deserialize_unit(visitor) + } + + #[inline] + fn deserialize_newtype_struct<V: de::Visitor<'de>>( + self, + _name: &'static str, + visitor: V, + ) -> Result<V::Value, Self::Error> { + visitor.visit_newtype_struct(self) + } + + #[inline] + fn deserialize_enum<V: de::Visitor<'de>>( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Self::Error> { + if name == "@@TAG@@" { + let (tag, val) = match self.0 { + Value::Tag(t, v) => (Some(*t), v.as_ref()), + v => (None, v), + }; + + let parent: Deserializer<&Value> = Deserializer(val); + let access = crate::tag::TagAccess::new(parent, tag); + return visitor.visit_enum(access); + } + + match self.0 { + Value::Tag(.., v) => Deserializer(v.as_ref()).deserialize_enum(name, variants, visitor), + Value::Map(x) if x.len() == 1 => visitor.visit_enum(Deserializer(&x[0])), + x @ Value::Text(..) => visitor.visit_enum(Deserializer(x)), + _ => Err(de::Error::invalid_type(self.0.into(), &"map")), + } + } +} + +impl<'a, 'de, T: Iterator<Item = &'a Value>> de::SeqAccess<'de> for Deserializer<T> { + type Error = Error; + + #[inline] + fn next_element_seed<U: de::DeserializeSeed<'de>>( + &mut self, + seed: U, + ) -> Result<Option<U::Value>, Self::Error> { + match self.0.next() { + None => Ok(None), + Some(v) => seed.deserialize(Deserializer(v)).map(Some), + } + } +} + +impl<'a, 'de, T: Iterator<Item = &'a (Value, Value)>> de::MapAccess<'de> + for Deserializer<Peekable<T>> +{ + type Error = Error; + + #[inline] + fn next_key_seed<K: de::DeserializeSeed<'de>>( + &mut self, + seed: K, + ) -> Result<Option<K::Value>, Self::Error> { + match self.0.peek() { + None => Ok(None), + Some(x) => Ok(Some(seed.deserialize(Deserializer(&x.0))?)), + } + } + + #[inline] + fn next_value_seed<V: de::DeserializeSeed<'de>>( + &mut self, + seed: V, + ) -> Result<V::Value, Self::Error> { + seed.deserialize(Deserializer(&self.0.next().unwrap().1)) + } +} + +impl<'a, 'de> de::EnumAccess<'de> for Deserializer<&'a (Value, Value)> { + type Error = Error; + type Variant = Deserializer<&'a Value>; + + #[inline] + fn variant_seed<V: de::DeserializeSeed<'de>>( + self, + seed: V, + ) -> Result<(V::Value, Self::Variant), Self::Error> { + let k = seed.deserialize(Deserializer(&self.0 .0))?; + Ok((k, Deserializer(&self.0 .1))) + } +} + +impl<'a, 'de> de::EnumAccess<'de> for Deserializer<&'a Value> { + type Error = Error; + type Variant = Deserializer<&'a Value>; + + #[inline] + fn variant_seed<V: de::DeserializeSeed<'de>>( + self, + seed: V, + ) -> Result<(V::Value, Self::Variant), Self::Error> { + let k = seed.deserialize(self)?; + Ok((k, Deserializer(&Value::Null))) + } +} + +impl<'a, 'de> de::VariantAccess<'de> for Deserializer<&'a Value> { + type Error = Error; + + #[inline] + fn unit_variant(self) -> Result<(), Self::Error> { + match self.0 { + Value::Null => Ok(()), + _ => Err(de::Error::invalid_type(self.0.into(), &"unit")), + } + } + + #[inline] + fn newtype_variant_seed<U: de::DeserializeSeed<'de>>( + self, + seed: U, + ) -> Result<U::Value, Self::Error> { + seed.deserialize(self) + } + + #[inline] + fn tuple_variant<V: de::Visitor<'de>>( + self, + _len: usize, + visitor: V, + ) -> Result<V::Value, Self::Error> { + self.deserialize_seq(visitor) + } + + #[inline] + fn struct_variant<V: de::Visitor<'de>>( + self, + _fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Self::Error> { + self.deserialize_map(visitor) + } +} + +impl Value { + /// Deserializes the `Value` into an object + #[inline] + pub fn deserialized<'de, T: de::Deserialize<'de>>(&self) -> Result<T, Error> { + T::deserialize(Deserializer(self)) + } +} diff --git a/vendor/ciborium/src/value/error.rs b/vendor/ciborium/src/value/error.rs new file mode 100644 index 000000000..bcec128f3 --- /dev/null +++ b/vendor/ciborium/src/value/error.rs @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: Apache-2.0 + +use alloc::string::{String, ToString}; + +/// The error when serializing to/from a `Value` +#[derive(Debug)] +pub enum Error { + /// A custom error string produced by serde + Custom(String), +} + +impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:?}", self) + } +} + +impl serde::de::StdError for Error {} + +impl serde::de::Error for Error { + #[inline] + fn custom<T: core::fmt::Display>(msg: T) -> Self { + Self::Custom(msg.to_string()) + } +} + +impl serde::ser::Error for Error { + #[inline] + fn custom<T: core::fmt::Display>(msg: T) -> Self { + Self::Custom(msg.to_string()) + } +} diff --git a/vendor/ciborium/src/value/integer.rs b/vendor/ciborium/src/value/integer.rs new file mode 100644 index 000000000..ef6ea3df0 --- /dev/null +++ b/vendor/ciborium/src/value/integer.rs @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: Apache-2.0 +use core::cmp::Ordering; + +macro_rules! implfrom { + ($( $(#[$($attr:meta)+])? $t:ident)+) => { + $( + $(#[$($attr)+])? + impl From<$t> for Integer { + #[inline] + fn from(value: $t) -> Self { + Self(value as _) + } + } + + impl TryFrom<Integer> for $t { + type Error = core::num::TryFromIntError; + + #[inline] + fn try_from(value: Integer) -> Result<Self, Self::Error> { + $t::try_from(value.0) + } + } + )+ + }; +} + +/// An abstract integer value +/// +/// This opaque type represents an integer value which can be encoded in CBOR +/// without resulting to big integer encoding. Larger values may be encoded +/// using the big integer encoding as described in the CBOR RFC. See the +/// implementations for 128-bit integer conversions on `Value` for more +/// details. +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct Integer(i128); + +impl Integer { + /// Returns the canonical length this integer will have when serialized to bytes. + /// This is called `canonical` as it is only used for canonically comparing two + /// values. It shouldn't be used in any other context. + fn canonical_len(&self) -> usize { + let x = self.0; + + if let Ok(x) = u8::try_from(x) { + if x < 24 { + 1 + } else { + 2 + } + } else if let Ok(x) = i8::try_from(x) { + if x >= -24i8 { + 1 + } else { + 2 + } + } else if u16::try_from(x).is_ok() || i16::try_from(x).is_ok() { + 3 + } else if u32::try_from(x).is_ok() || i32::try_from(x).is_ok() { + 5 + } else if u64::try_from(x).is_ok() || i64::try_from(x).is_ok() { + 9 + } else { + // Ciborium serializes u128/i128 as BigPos if they don't fit in 64 bits. + // In this special case we have to calculate the length. + // The Tag itself will always be 1 byte. + x.to_be_bytes().len() + 1 + } + } + + /// Compare two integers as if we were to serialize them, but more efficiently. + pub fn canonical_cmp(&self, other: &Self) -> Ordering { + match self.canonical_len().cmp(&other.canonical_len()) { + Ordering::Equal => { + // Negative numbers are higher in byte-order than positive numbers. + match (self.0.is_negative(), other.0.is_negative()) { + (false, true) => Ordering::Less, + (true, false) => Ordering::Greater, + (true, true) => { + // For negative numbers the byte order puts numbers closer to 0 which + // are lexically higher, lower. So -1 < -2 when sorting by be_bytes(). + match self.0.cmp(&other.0) { + Ordering::Less => Ordering::Greater, + Ordering::Equal => Ordering::Equal, + Ordering::Greater => Ordering::Less, + } + } + (_, _) => self.0.cmp(&other.0), + } + } + x => x, + } + } +} + +implfrom! { + u8 u16 u32 u64 + i8 i16 i32 i64 + + #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] + usize + + #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] + isize +} + +impl TryFrom<i128> for Integer { + type Error = core::num::TryFromIntError; + + #[inline] + fn try_from(value: i128) -> Result<Self, Self::Error> { + u64::try_from(match value.is_negative() { + false => value, + true => value ^ !0, + })?; + + Ok(Integer(value)) + } +} + +impl TryFrom<u128> for Integer { + type Error = core::num::TryFromIntError; + + #[inline] + fn try_from(value: u128) -> Result<Self, Self::Error> { + Ok(Self(u64::try_from(value)?.into())) + } +} + +impl From<Integer> for i128 { + #[inline] + fn from(value: Integer) -> Self { + value.0 + } +} + +impl TryFrom<Integer> for u128 { + type Error = core::num::TryFromIntError; + + #[inline] + fn try_from(value: Integer) -> Result<Self, Self::Error> { + u128::try_from(value.0) + } +} diff --git a/vendor/ciborium/src/value/mod.rs b/vendor/ciborium/src/value/mod.rs new file mode 100644 index 000000000..7233026f1 --- /dev/null +++ b/vendor/ciborium/src/value/mod.rs @@ -0,0 +1,685 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! A dynamic CBOR value + +mod canonical; +mod integer; + +mod de; +mod error; +mod ser; + +pub use canonical::CanonicalValue; +pub use error::Error; +pub use integer::Integer; + +use alloc::{boxed::Box, string::String, vec::Vec}; + +/// A representation of a dynamic CBOR value that can handled dynamically +#[non_exhaustive] +#[derive(Clone, Debug, PartialEq, PartialOrd)] +pub enum Value { + /// An integer + Integer(Integer), + + /// Bytes + Bytes(Vec<u8>), + + /// A float + Float(f64), + + /// A string + Text(String), + + /// A boolean + Bool(bool), + + /// Null + Null, + + /// Tag + Tag(u64, Box<Value>), + + /// An array + Array(Vec<Value>), + + /// A map + Map(Vec<(Value, Value)>), +} + +impl Value { + /// Returns true if the `Value` is an `Integer`. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Integer(17.into()); + /// + /// assert!(value.is_integer()); + /// ``` + pub fn is_integer(&self) -> bool { + self.as_integer().is_some() + } + + /// If the `Value` is a `Integer`, returns a reference to the associated `Integer` data. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Integer(17.into()); + /// + /// // We can read the number + /// assert_eq!(17, value.as_integer().unwrap().try_into().unwrap()); + /// ``` + pub fn as_integer(&self) -> Option<Integer> { + match self { + Value::Integer(int) => Some(*int), + _ => None, + } + } + + /// If the `Value` is a `Integer`, returns a the associated `Integer` data as `Ok`. + /// Returns `Err(Self)` otherwise. + /// + /// ``` + /// # use ciborium::{Value, value::Integer}; + /// # + /// let value = Value::Integer(17.into()); + /// assert_eq!(value.into_integer(), Ok(Integer::from(17))); + /// + /// let value = Value::Bool(true); + /// assert_eq!(value.into_integer(), Err(Value::Bool(true))); + /// ``` + pub fn into_integer(self) -> Result<Integer, Self> { + match self { + Value::Integer(int) => Ok(int), + other => Err(other), + } + } + + /// Returns true if the `Value` is a `Bytes`. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Bytes(vec![104, 101, 108, 108, 111]); + /// + /// assert!(value.is_bytes()); + /// ``` + pub fn is_bytes(&self) -> bool { + self.as_bytes().is_some() + } + + /// If the `Value` is a `Bytes`, returns a reference to the associated bytes vector. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Bytes(vec![104, 101, 108, 108, 111]); + /// + /// assert_eq!(std::str::from_utf8(value.as_bytes().unwrap()).unwrap(), "hello"); + /// ``` + pub fn as_bytes(&self) -> Option<&Vec<u8>> { + match *self { + Value::Bytes(ref bytes) => Some(bytes), + _ => None, + } + } + + /// If the `Value` is a `Bytes`, returns a mutable reference to the associated bytes vector. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let mut value = Value::Bytes(vec![104, 101, 108, 108, 111]); + /// value.as_bytes_mut().unwrap().clear(); + /// + /// assert_eq!(value, Value::Bytes(vec![])); + /// ``` + pub fn as_bytes_mut(&mut self) -> Option<&mut Vec<u8>> { + match *self { + Value::Bytes(ref mut bytes) => Some(bytes), + _ => None, + } + } + + /// If the `Value` is a `Bytes`, returns a the associated `Vec<u8>` data as `Ok`. + /// Returns `Err(Self)` otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Bytes(vec![104, 101, 108, 108, 111]); + /// assert_eq!(value.into_bytes(), Ok(vec![104, 101, 108, 108, 111])); + /// + /// let value = Value::Bool(true); + /// assert_eq!(value.into_bytes(), Err(Value::Bool(true))); + /// ``` + pub fn into_bytes(self) -> Result<Vec<u8>, Self> { + match self { + Value::Bytes(vec) => Ok(vec), + other => Err(other), + } + } + + /// Returns true if the `Value` is a `Float`. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Float(17.0.into()); + /// + /// assert!(value.is_float()); + /// ``` + pub fn is_float(&self) -> bool { + self.as_float().is_some() + } + + /// If the `Value` is a `Float`, returns a reference to the associated float data. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Float(17.0.into()); + /// + /// // We can read the float number + /// assert_eq!(value.as_float().unwrap(), 17.0_f64); + /// ``` + pub fn as_float(&self) -> Option<f64> { + match *self { + Value::Float(f) => Some(f), + _ => None, + } + } + + /// If the `Value` is a `Float`, returns a the associated `f64` data as `Ok`. + /// Returns `Err(Self)` otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Float(17.); + /// assert_eq!(value.into_float(), Ok(17.)); + /// + /// let value = Value::Bool(true); + /// assert_eq!(value.into_float(), Err(Value::Bool(true))); + /// ``` + pub fn into_float(self) -> Result<f64, Self> { + match self { + Value::Float(f) => Ok(f), + other => Err(other), + } + } + + /// Returns true if the `Value` is a `Text`. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Text(String::from("hello")); + /// + /// assert!(value.is_text()); + /// ``` + pub fn is_text(&self) -> bool { + self.as_text().is_some() + } + + /// If the `Value` is a `Text`, returns a reference to the associated `String` data. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Text(String::from("hello")); + /// + /// // We can read the String + /// assert_eq!(value.as_text().unwrap(), "hello"); + /// ``` + pub fn as_text(&self) -> Option<&str> { + match *self { + Value::Text(ref s) => Some(s), + _ => None, + } + } + + /// If the `Value` is a `Text`, returns a mutable reference to the associated `String` data. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let mut value = Value::Text(String::from("hello")); + /// value.as_text_mut().unwrap().clear(); + /// + /// assert_eq!(value.as_text().unwrap(), &String::from("")); + /// ``` + pub fn as_text_mut(&mut self) -> Option<&mut String> { + match *self { + Value::Text(ref mut s) => Some(s), + _ => None, + } + } + + /// If the `Value` is a `String`, returns a the associated `String` data as `Ok`. + /// Returns `Err(Self)` otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Text(String::from("hello")); + /// assert_eq!(value.into_text().as_deref(), Ok("hello")); + /// + /// let value = Value::Bool(true); + /// assert_eq!(value.into_text(), Err(Value::Bool(true))); + /// ``` + pub fn into_text(self) -> Result<String, Self> { + match self { + Value::Text(s) => Ok(s), + other => Err(other), + } + } + + /// Returns true if the `Value` is a `Bool`. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Bool(false); + /// + /// assert!(value.is_bool()); + /// ``` + pub fn is_bool(&self) -> bool { + self.as_bool().is_some() + } + + /// If the `Value` is a `Bool`, returns a copy of the associated boolean value. Returns None + /// otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Bool(false); + /// + /// assert_eq!(value.as_bool().unwrap(), false); + /// ``` + pub fn as_bool(&self) -> Option<bool> { + match *self { + Value::Bool(b) => Some(b), + _ => None, + } + } + + /// If the `Value` is a `Bool`, returns a the associated `bool` data as `Ok`. + /// Returns `Err(Self)` otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Bool(false); + /// assert_eq!(value.into_bool(), Ok(false)); + /// + /// let value = Value::Float(17.); + /// assert_eq!(value.into_bool(), Err(Value::Float(17.))); + /// ``` + pub fn into_bool(self) -> Result<bool, Self> { + match self { + Value::Bool(b) => Ok(b), + other => Err(other), + } + } + + /// Returns true if the `Value` is a `Null`. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Null; + /// + /// assert!(value.is_null()); + /// ``` + pub fn is_null(&self) -> bool { + matches!(self, Value::Null) + } + + /// Returns true if the `Value` is a `Tag`. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Tag(61, Box::from(Value::Null)); + /// + /// assert!(value.is_tag()); + /// ``` + pub fn is_tag(&self) -> bool { + self.as_tag().is_some() + } + + /// If the `Value` is a `Tag`, returns the associated tag value and a reference to the tag `Value`. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Tag(61, Box::from(Value::Bytes(vec![104, 101, 108, 108, 111]))); + /// + /// let (tag, data) = value.as_tag().unwrap(); + /// assert_eq!(tag, 61); + /// assert_eq!(data, &Value::Bytes(vec![104, 101, 108, 108, 111])); + /// ``` + pub fn as_tag(&self) -> Option<(u64, &Value)> { + match self { + Value::Tag(tag, data) => Some((*tag, data)), + _ => None, + } + } + + /// If the `Value` is a `Tag`, returns the associated tag value and a mutable reference + /// to the tag `Value`. Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let mut value = Value::Tag(61, Box::from(Value::Bytes(vec![104, 101, 108, 108, 111]))); + /// + /// let (tag, mut data) = value.as_tag_mut().unwrap(); + /// data.as_bytes_mut().unwrap().clear(); + /// assert_eq!(tag, &61); + /// assert_eq!(data, &Value::Bytes(vec![])); + /// ``` + pub fn as_tag_mut(&mut self) -> Option<(&mut u64, &mut Value)> { + match self { + Value::Tag(tag, data) => Some((tag, data.as_mut())), + _ => None, + } + } + + /// If the `Value` is a `Tag`, returns a the associated pair of `u64` and `Box<value>` data as `Ok`. + /// Returns `Err(Self)` otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Tag(7, Box::new(Value::Float(12.))); + /// assert_eq!(value.into_tag(), Ok((7, Box::new(Value::Float(12.))))); + /// + /// let value = Value::Bool(true); + /// assert_eq!(value.into_tag(), Err(Value::Bool(true))); + /// ``` + pub fn into_tag(self) -> Result<(u64, Box<Value>), Self> { + match self { + Value::Tag(tag, value) => Ok((tag, value)), + other => Err(other), + } + } + + /// Returns true if the `Value` is an Array. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Array( + /// vec![ + /// Value::Text(String::from("foo")), + /// Value::Text(String::from("bar")) + /// ] + /// ); + /// + /// assert!(value.is_array()); + /// ``` + pub fn is_array(&self) -> bool { + self.as_array().is_some() + } + + /// If the `Value` is an Array, returns a reference to the associated vector. Returns None + /// otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Array( + /// vec![ + /// Value::Text(String::from("foo")), + /// Value::Text(String::from("bar")) + /// ] + /// ); + /// + /// // The length of `value` is 2 elements. + /// assert_eq!(value.as_array().unwrap().len(), 2); + /// ``` + pub fn as_array(&self) -> Option<&Vec<Value>> { + match *self { + Value::Array(ref array) => Some(array), + _ => None, + } + } + + /// If the `Value` is an Array, returns a mutable reference to the associated vector. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let mut value = Value::Array( + /// vec![ + /// Value::Text(String::from("foo")), + /// Value::Text(String::from("bar")) + /// ] + /// ); + /// + /// value.as_array_mut().unwrap().clear(); + /// assert_eq!(value, Value::Array(vec![])); + /// ``` + pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> { + match *self { + Value::Array(ref mut list) => Some(list), + _ => None, + } + } + + /// If the `Value` is a `Array`, returns a the associated `Vec<Value>` data as `Ok`. + /// Returns `Err(Self)` otherwise. + /// + /// ``` + /// # use ciborium::{Value, value::Integer}; + /// # + /// let mut value = Value::Array( + /// vec![ + /// Value::Integer(17.into()), + /// Value::Float(18.), + /// ] + /// ); + /// assert_eq!(value.into_array(), Ok(vec![Value::Integer(17.into()), Value::Float(18.)])); + /// + /// let value = Value::Bool(true); + /// assert_eq!(value.into_array(), Err(Value::Bool(true))); + /// ``` + pub fn into_array(self) -> Result<Vec<Value>, Self> { + match self { + Value::Array(vec) => Ok(vec), + other => Err(other), + } + } + + /// Returns true if the `Value` is a Map. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Map( + /// vec![ + /// (Value::Text(String::from("foo")), Value::Text(String::from("bar"))) + /// ] + /// ); + /// + /// assert!(value.is_map()); + /// ``` + pub fn is_map(&self) -> bool { + self.as_map().is_some() + } + + /// If the `Value` is a Map, returns a reference to the associated Map data. Returns None + /// otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Map( + /// vec![ + /// (Value::Text(String::from("foo")), Value::Text(String::from("bar"))) + /// ] + /// ); + /// + /// // The length of data is 1 entry (1 key/value pair). + /// assert_eq!(value.as_map().unwrap().len(), 1); + /// + /// // The content of the first element is what we expect + /// assert_eq!( + /// value.as_map().unwrap().get(0).unwrap(), + /// &(Value::Text(String::from("foo")), Value::Text(String::from("bar"))) + /// ); + /// ``` + pub fn as_map(&self) -> Option<&Vec<(Value, Value)>> { + match *self { + Value::Map(ref map) => Some(map), + _ => None, + } + } + + /// If the `Value` is a Map, returns a mutable reference to the associated Map Data. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let mut value = Value::Map( + /// vec![ + /// (Value::Text(String::from("foo")), Value::Text(String::from("bar"))) + /// ] + /// ); + /// + /// value.as_map_mut().unwrap().clear(); + /// assert_eq!(value, Value::Map(vec![])); + /// assert_eq!(value.as_map().unwrap().len(), 0); + /// ``` + pub fn as_map_mut(&mut self) -> Option<&mut Vec<(Value, Value)>> { + match *self { + Value::Map(ref mut map) => Some(map), + _ => None, + } + } + + /// If the `Value` is a `Map`, returns a the associated `Vec<(Value, Value)>` data as `Ok`. + /// Returns `Err(Self)` otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let mut value = Value::Map( + /// vec![ + /// (Value::Text(String::from("key")), Value::Float(18.)), + /// ] + /// ); + /// assert_eq!(value.into_map(), Ok(vec![(Value::Text(String::from("key")), Value::Float(18.))])); + /// + /// let value = Value::Bool(true); + /// assert_eq!(value.into_map(), Err(Value::Bool(true))); + /// ``` + pub fn into_map(self) -> Result<Vec<(Value, Value)>, Self> { + match self { + Value::Map(map) => Ok(map), + other => Err(other), + } + } +} + +macro_rules! implfrom { + ($($v:ident($t:ty)),+ $(,)?) => { + $( + impl From<$t> for Value { + #[inline] + fn from(value: $t) -> Self { + Self::$v(value.into()) + } + } + )+ + }; +} + +implfrom! { + Integer(Integer), + Integer(u64), + Integer(i64), + Integer(u32), + Integer(i32), + Integer(u16), + Integer(i16), + Integer(u8), + Integer(i8), + + Bytes(Vec<u8>), + Bytes(&[u8]), + + Float(f64), + Float(f32), + + Text(String), + Text(&str), + + Bool(bool), + + Array(&[Value]), + Array(Vec<Value>), + + Map(&[(Value, Value)]), + Map(Vec<(Value, Value)>), +} + +impl From<u128> for Value { + #[inline] + fn from(value: u128) -> Self { + if let Ok(x) = Integer::try_from(value) { + return Value::Integer(x); + } + + let mut bytes = &value.to_be_bytes()[..]; + while let Some(0) = bytes.first() { + bytes = &bytes[1..]; + } + + Value::Tag(ciborium_ll::tag::BIGPOS, Value::Bytes(bytes.into()).into()) + } +} + +impl From<i128> for Value { + #[inline] + fn from(value: i128) -> Self { + if let Ok(x) = Integer::try_from(value) { + return Value::Integer(x); + } + + let (tag, raw) = match value.is_negative() { + true => (ciborium_ll::tag::BIGNEG, value as u128 ^ !0), + false => (ciborium_ll::tag::BIGPOS, value as u128), + }; + + let mut bytes = &raw.to_be_bytes()[..]; + while let Some(0) = bytes.first() { + bytes = &bytes[1..]; + } + + Value::Tag(tag, Value::Bytes(bytes.into()).into()) + } +} + +impl From<char> for Value { + #[inline] + fn from(value: char) -> Self { + let mut v = String::with_capacity(1); + v.push(value); + Value::Text(v) + } +} diff --git a/vendor/ciborium/src/value/ser.rs b/vendor/ciborium/src/value/ser.rs new file mode 100644 index 000000000..a399719d0 --- /dev/null +++ b/vendor/ciborium/src/value/ser.rs @@ -0,0 +1,434 @@ +// SPDX-License-Identifier: Apache-2.0 + +use super::{Error, Value}; + +use alloc::{vec, vec::Vec}; + +use ::serde::ser::{self, SerializeMap as _, SerializeSeq as _, SerializeTupleVariant as _}; + +impl ser::Serialize for Value { + #[inline] + fn serialize<S: ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + match self { + Value::Bytes(x) => serializer.serialize_bytes(x), + Value::Bool(x) => serializer.serialize_bool(*x), + Value::Text(x) => serializer.serialize_str(x), + Value::Null => serializer.serialize_unit(), + + Value::Tag(t, v) => { + let mut acc = serializer.serialize_tuple_variant("@@TAG@@", 0, "@@TAGGED@@", 2)?; + acc.serialize_field(t)?; + acc.serialize_field(v)?; + acc.end() + } + + Value::Float(x) => { + let y = *x as f32; + if (y as f64).to_bits() == x.to_bits() { + serializer.serialize_f32(y) + } else { + serializer.serialize_f64(*x) + } + } + + Value::Integer(x) => { + if let Ok(x) = u8::try_from(*x) { + serializer.serialize_u8(x) + } else if let Ok(x) = i8::try_from(*x) { + serializer.serialize_i8(x) + } else if let Ok(x) = u16::try_from(*x) { + serializer.serialize_u16(x) + } else if let Ok(x) = i16::try_from(*x) { + serializer.serialize_i16(x) + } else if let Ok(x) = u32::try_from(*x) { + serializer.serialize_u32(x) + } else if let Ok(x) = i32::try_from(*x) { + serializer.serialize_i32(x) + } else if let Ok(x) = u64::try_from(*x) { + serializer.serialize_u64(x) + } else if let Ok(x) = i64::try_from(*x) { + serializer.serialize_i64(x) + } else if let Ok(x) = u128::try_from(*x) { + serializer.serialize_u128(x) + } else if let Ok(x) = i128::try_from(*x) { + serializer.serialize_i128(x) + } else { + unreachable!() + } + } + + Value::Array(x) => { + let mut map = serializer.serialize_seq(Some(x.len()))?; + + for v in x { + map.serialize_element(v)?; + } + + map.end() + } + + Value::Map(x) => { + let mut map = serializer.serialize_map(Some(x.len()))?; + + for (k, v) in x { + map.serialize_entry(k, v)?; + } + + map.end() + } + } + } +} + +macro_rules! mkserialize { + ($($f:ident($v:ty)),+ $(,)?) => { + $( + #[inline] + fn $f(self, v: $v) -> Result<Self::Ok, Self::Error> { + Ok(v.into()) + } + )+ + }; +} + +struct Tagged { + tag: Option<u64>, + val: Option<Value>, +} + +struct Named<T> { + name: &'static str, + data: T, + tag: Option<Tagged>, +} + +struct Map { + data: Vec<(Value, Value)>, + temp: Option<Value>, +} + +struct Serializer<T>(T); + +impl ser::Serializer for Serializer<()> { + type Ok = Value; + type Error = Error; + + type SerializeSeq = Serializer<Vec<Value>>; + type SerializeTuple = Serializer<Vec<Value>>; + type SerializeTupleStruct = Serializer<Vec<Value>>; + type SerializeTupleVariant = Serializer<Named<Vec<Value>>>; + type SerializeMap = Serializer<Map>; + type SerializeStruct = Serializer<Vec<(Value, Value)>>; + type SerializeStructVariant = Serializer<Named<Vec<(Value, Value)>>>; + + mkserialize! { + serialize_bool(bool), + + serialize_f32(f32), + serialize_f64(f64), + + serialize_i8(i8), + serialize_i16(i16), + serialize_i32(i32), + serialize_i64(i64), + serialize_i128(i128), + serialize_u8(u8), + serialize_u16(u16), + serialize_u32(u32), + serialize_u64(u64), + serialize_u128(u128), + + serialize_char(char), + serialize_str(&str), + serialize_bytes(&[u8]), + } + + #[inline] + fn serialize_none(self) -> Result<Value, Error> { + Ok(Value::Null) + } + + #[inline] + fn serialize_some<U: ?Sized + ser::Serialize>(self, value: &U) -> Result<Value, Error> { + value.serialize(self) + } + + #[inline] + fn serialize_unit(self) -> Result<Value, Error> { + self.serialize_none() + } + + #[inline] + fn serialize_unit_struct(self, _name: &'static str) -> Result<Value, Error> { + self.serialize_unit() + } + + #[inline] + fn serialize_unit_variant( + self, + _name: &'static str, + _index: u32, + variant: &'static str, + ) -> Result<Value, Error> { + Ok(variant.into()) + } + + #[inline] + fn serialize_newtype_struct<U: ?Sized + ser::Serialize>( + self, + _name: &'static str, + value: &U, + ) -> Result<Value, Error> { + value.serialize(self) + } + + #[inline] + fn serialize_newtype_variant<U: ?Sized + ser::Serialize>( + self, + name: &'static str, + _index: u32, + variant: &'static str, + value: &U, + ) -> Result<Value, Error> { + Ok(match (name, variant) { + ("@@TAG@@", "@@UNTAGGED@@") => Value::serialized(value)?, + _ => vec![(variant.into(), Value::serialized(value)?)].into(), + }) + } + + #[inline] + fn serialize_seq(self, length: Option<usize>) -> Result<Self::SerializeSeq, Error> { + Ok(Serializer(Vec::with_capacity(length.unwrap_or(0)))) + } + + #[inline] + fn serialize_tuple(self, length: usize) -> Result<Self::SerializeTuple, Error> { + self.serialize_seq(Some(length)) + } + + #[inline] + fn serialize_tuple_struct( + self, + _name: &'static str, + length: usize, + ) -> Result<Self::SerializeTupleStruct, Error> { + self.serialize_seq(Some(length)) + } + + #[inline] + fn serialize_tuple_variant( + self, + name: &'static str, + _index: u32, + variant: &'static str, + length: usize, + ) -> Result<Self::SerializeTupleVariant, Error> { + Ok(Serializer(Named { + name: variant, + data: Vec::with_capacity(length), + tag: match (name, variant) { + ("@@TAG@@", "@@TAGGED@@") => Some(Tagged { + tag: None, + val: None, + }), + + _ => None, + }, + })) + } + + #[inline] + fn serialize_map(self, length: Option<usize>) -> Result<Self::SerializeMap, Error> { + Ok(Serializer(Map { + data: Vec::with_capacity(length.unwrap_or(0)), + temp: None, + })) + } + + #[inline] + fn serialize_struct( + self, + _name: &'static str, + length: usize, + ) -> Result<Self::SerializeStruct, Error> { + Ok(Serializer(Vec::with_capacity(length))) + } + + #[inline] + fn serialize_struct_variant( + self, + _name: &'static str, + _index: u32, + variant: &'static str, + length: usize, + ) -> Result<Self::SerializeStructVariant, Error> { + Ok(Serializer(Named { + name: variant, + data: Vec::with_capacity(length), + tag: None, + })) + } +} + +impl ser::SerializeSeq for Serializer<Vec<Value>> { + type Ok = Value; + type Error = Error; + + #[inline] + fn serialize_element<U: ?Sized + ser::Serialize>(&mut self, value: &U) -> Result<(), Error> { + self.0.push(Value::serialized(&value)?); + Ok(()) + } + + #[inline] + fn end(self) -> Result<Self::Ok, Self::Error> { + Ok(self.0.into()) + } +} + +impl ser::SerializeTuple for Serializer<Vec<Value>> { + type Ok = Value; + type Error = Error; + + #[inline] + fn serialize_element<U: ?Sized + ser::Serialize>(&mut self, value: &U) -> Result<(), Error> { + self.0.push(Value::serialized(&value)?); + Ok(()) + } + + #[inline] + fn end(self) -> Result<Self::Ok, Self::Error> { + Ok(self.0.into()) + } +} + +impl ser::SerializeTupleStruct for Serializer<Vec<Value>> { + type Ok = Value; + type Error = Error; + + #[inline] + fn serialize_field<U: ?Sized + ser::Serialize>(&mut self, value: &U) -> Result<(), Error> { + self.0.push(Value::serialized(&value)?); + Ok(()) + } + + #[inline] + fn end(self) -> Result<Self::Ok, Self::Error> { + Ok(self.0.into()) + } +} + +impl ser::SerializeTupleVariant for Serializer<Named<Vec<Value>>> { + type Ok = Value; + type Error = Error; + + #[inline] + fn serialize_field<U: ?Sized + ser::Serialize>(&mut self, value: &U) -> Result<(), Error> { + match self.0.tag.as_mut() { + Some(tag) => match tag.tag { + None => match value.serialize(crate::tag::Serializer) { + Ok(t) => tag.tag = Some(t), + Err(..) => return Err(ser::Error::custom("expected tag")), + }, + + Some(..) => tag.val = Some(Value::serialized(value)?), + }, + + None => self.0.data.push(Value::serialized(value)?), + } + + Ok(()) + } + + #[inline] + fn end(self) -> Result<Self::Ok, Self::Error> { + Ok(match self.0.tag { + Some(tag) => match tag { + Tagged { + tag: Some(t), + val: Some(v), + } => Value::Tag(t, v.into()), + _ => return Err(ser::Error::custom("invalid tag input")), + }, + + None => vec![(self.0.name.into(), self.0.data.into())].into(), + }) + } +} + +impl ser::SerializeMap for Serializer<Map> { + type Ok = Value; + type Error = Error; + + #[inline] + fn serialize_key<U: ?Sized + ser::Serialize>(&mut self, key: &U) -> Result<(), Error> { + self.0.temp = Some(Value::serialized(key)?); + Ok(()) + } + + #[inline] + fn serialize_value<U: ?Sized + ser::Serialize>(&mut self, value: &U) -> Result<(), Error> { + let key = self.0.temp.take().unwrap(); + let val = Value::serialized(&value)?; + + self.0.data.push((key, val)); + Ok(()) + } + + #[inline] + fn end(self) -> Result<Self::Ok, Self::Error> { + Ok(self.0.data.into()) + } +} + +impl ser::SerializeStruct for Serializer<Vec<(Value, Value)>> { + type Ok = Value; + type Error = Error; + + #[inline] + fn serialize_field<U: ?Sized + ser::Serialize>( + &mut self, + key: &'static str, + value: &U, + ) -> Result<(), Error> { + let k = Value::serialized(&key)?; + let v = Value::serialized(&value)?; + self.0.push((k, v)); + Ok(()) + } + + #[inline] + fn end(self) -> Result<Self::Ok, Self::Error> { + Ok(self.0.into()) + } +} + +impl ser::SerializeStructVariant for Serializer<Named<Vec<(Value, Value)>>> { + type Ok = Value; + type Error = Error; + + #[inline] + fn serialize_field<U: ?Sized + ser::Serialize>( + &mut self, + key: &'static str, + value: &U, + ) -> Result<(), Self::Error> { + let k = Value::serialized(&key)?; + let v = Value::serialized(&value)?; + self.0.data.push((k, v)); + Ok(()) + } + + #[inline] + fn end(self) -> Result<Self::Ok, Self::Error> { + Ok(vec![(self.0.name.into(), self.0.data.into())].into()) + } +} + +impl Value { + /// Serializes an object into a `Value` + #[inline] + pub fn serialized<T: ?Sized + ser::Serialize>(value: &T) -> Result<Self, Error> { + value.serialize(Serializer(())) + } +} diff --git a/vendor/ciborium/tests/canonical.rs b/vendor/ciborium/tests/canonical.rs new file mode 100644 index 000000000..d4aa33c58 --- /dev/null +++ b/vendor/ciborium/tests/canonical.rs @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: Apache-2.0 + +extern crate std; + +use ciborium::cbor; +use ciborium::tag::Required; +use ciborium::value::CanonicalValue; +use rand::prelude::*; +use std::collections::BTreeMap; + +macro_rules! cval { + ($x:expr) => { + CanonicalValue::from(val!($x)) + }; +} + +macro_rules! val { + ($x:expr) => { + cbor!($x).unwrap() + }; +} + +#[test] +fn rfc8949_example() { + let mut array: Vec<CanonicalValue> = vec![ + cval!(10), + cval!(-1), + cval!(false), + cval!(100), + cval!("z"), + cval!([-1]), + cval!("aa"), + cval!([100]), + ]; + let golden = array.clone(); + + // Shuffle the array. + array.shuffle(&mut rand::thread_rng()); + + array.sort(); + + assert_eq!(array, golden); +} + +#[test] +fn map() { + let mut map = BTreeMap::new(); + map.insert(cval!(false), val!(2)); + map.insert(cval!([-1]), val!(5)); + map.insert(cval!(-1), val!(1)); + map.insert(cval!(10), val!(0)); + map.insert(cval!(100), val!(3)); + map.insert(cval!([100]), val!(7)); + map.insert(cval!("z"), val!(4)); + map.insert(cval!("aa"), val!(6)); + + let mut bytes1 = Vec::new(); + ciborium::ser::into_writer(&map, &mut bytes1).unwrap(); + + assert_eq!( + hex::encode(&bytes1), + "a80a002001f402186403617a048120056261610681186407" + ); +} + +#[test] +fn negative_numbers() { + let mut array: Vec<CanonicalValue> = vec![ + cval!(10), + cval!(-1), + cval!(-2), + cval!(-3), + cval!(-4), + cval!(false), + cval!(100), + cval!(-100), + cval!(-200), + cval!("z"), + cval!([-1]), + cval!(-300), + cval!("aa"), + cval!([100]), + ]; + let golden = array.clone(); + + // Shuffle the array. + array.shuffle(&mut rand::thread_rng()); + + array.sort(); + + assert_eq!(array, golden); +} + +#[test] +fn tagged_option() { + let mut opt = Some(Required::<u64, 0xff>(2u32.into())); + + let mut bytes = Vec::new(); + ciborium::ser::into_writer(&opt, &mut bytes).unwrap(); + + let output = ciborium::de::from_reader(&bytes[..]).unwrap(); + assert_eq!(opt, output); + + opt = None; + + let mut bytes = Vec::new(); + ciborium::ser::into_writer(&opt, &mut bytes).unwrap(); + + let output = ciborium::de::from_reader(&bytes[..]).unwrap(); + assert_eq!(opt, output); +} diff --git a/vendor/ciborium/tests/codec.rs b/vendor/ciborium/tests/codec.rs new file mode 100644 index 000000000..d5df9a7f2 --- /dev/null +++ b/vendor/ciborium/tests/codec.rs @@ -0,0 +1,433 @@ +// SPDX-License-Identifier: Apache-2.0 + +extern crate std; + +use std::collections::{BTreeMap, HashMap}; +use std::convert::TryFrom; +use std::fmt::Debug; + +use ciborium::value::Value; +use ciborium::{cbor, de::from_reader, ser::into_writer}; + +use rstest::rstest; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; + +macro_rules! val { + ($x:expr) => { + Value::try_from($x).unwrap() + }; +} + +macro_rules! hex { + ($x:expr) => { + serde_bytes::ByteBuf::from(hex::decode($x).unwrap()) + }; +} + +macro_rules! map { + ($($k:expr => $v:expr),*) => {{ + let mut map = BTreeMap::new(); + $( + map.insert($k, $v); + )* + map + }} +} + +// Keep the first "case" aligned to a line number ending in 1 for ease in finding tests. +#[allow(clippy::excessive_precision)] +#[rstest(input, value, bytes, alternate, equality, + + case(0u8, val!(0u8), "00", false, same), + case(0u16, val!(0u16), "00", false, same), + case(0u32, val!(0u32), "00", false, same), + case(0u64, val!(0u64), "00", false, same), + case(0u128, val!(0u128), "00", false, same), + case(0i8, val!(0i8), "00", false, same), + case(0i16, val!(0i16), "00", false, same), + case(0i32, val!(0i32), "00", false, same), + case(0i64, val!(0i64), "00", false, same), + case(0i128, val!(0i128), "00", false, same), + case(1u8, val!(1u8), "01", false, same), + case(1u16, val!(1u16), "01", false, same), + case(1u32, val!(1u32), "01", false, same), + case(1u64, val!(1u64), "01", false, same), + case(1u128, val!(1u128), "01", false, same), + case(1i8, val!(1i8), "01", false, same), + case(1i16, val!(1i16), "01", false, same), + case(1i32, val!(1i32), "01", false, same), + case(1i64, val!(1i64), "01", false, same), + case(1i128, val!(1i128), "01", false, same), + case(1u8, val!(1u8), "1b0000000000000001", true, same), + case(1u16, val!(1u16), "1b0000000000000001", true, same), + case(1u32, val!(1u32), "1b0000000000000001", true, same), + case(1u64, val!(1u64), "1b0000000000000001", true, same), + case(1u128, val!(1u128), "1b0000000000000001", true, same), + case(1i8, val!(1i8), "1b0000000000000001", true, same), + case(1i16, val!(1i16), "1b0000000000000001", true, same), + case(1i32, val!(1i32), "1b0000000000000001", true, same), + case(1i64, val!(1i64), "1b0000000000000001", true, same), + case(1i128, val!(1i128), "1b0000000000000001", true, same), + case(1u8, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC + case(1u16, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC + case(1u32, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC + case(1u64, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC + case(1u128, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC + case(1i8, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC + case(1i16, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC + case(1i32, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC + case(1i64, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC + case(1i128, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC + case(10u8, val!(10u8), "0a", false, same), + case(10u16, val!(10u16), "0a", false, same), + case(10u32, val!(10u32), "0a", false, same), + case(10u64, val!(10u64), "0a", false, same), + case(10u128, val!(10u128), "0a", false, same), + case(10i8, val!(10i8), "0a", false, same), + case(10i16, val!(10i16), "0a", false, same), + case(10i32, val!(10i32), "0a", false, same), + case(10i64, val!(10i64), "0a", false, same), + case(10i128, val!(10i128), "0a", false, same), + case(23u8, val!(23u8), "17", false, same), + case(23u16, val!(23u16), "17", false, same), + case(23u32, val!(23u32), "17", false, same), + case(23u64, val!(23u64), "17", false, same), + case(23u128, val!(23u128), "17", false, same), + case(23i8, val!(23i8), "17", false, same), + case(23i16, val!(23i16), "17", false, same), + case(23i32, val!(23i32), "17", false, same), + case(23i64, val!(23i64), "17", false, same), + case(23i128, val!(23i128), "17", false, same), + case(24u8, val!(24u8), "1818", false, same), + case(24u16, val!(24u16), "1818", false, same), + case(24u32, val!(24u32), "1818", false, same), + case(24u64, val!(24u64), "1818", false, same), + case(24u128, val!(24u128), "1818", false, same), + case(24i8, val!(24i8), "1818", false, same), + case(24i16, val!(24i16), "1818", false, same), + case(24i32, val!(24i32), "1818", false, same), + case(24i64, val!(24i64), "1818", false, same), + case(24i128, val!(24i128), "1818", false, same), + case(25u8, val!(25u8), "1819", false, same), + case(25u16, val!(25u16), "1819", false, same), + case(25u32, val!(25u32), "1819", false, same), + case(25u64, val!(25u64), "1819", false, same), + case(25u128, val!(25u128), "1819", false, same), + case(25i8, val!(25i8), "1819", false, same), + case(25i16, val!(25i16), "1819", false, same), + case(25i32, val!(25i32), "1819", false, same), + case(25i64, val!(25i64), "1819", false, same), + case(25i128, val!(25i128), "1819", false, same), + case(100u8, val!(100u8), "1864", false, same), + case(100u16, val!(100u16), "1864", false, same), + case(100u32, val!(100u32), "1864", false, same), + case(100u64, val!(100u64), "1864", false, same), + case(100u128, val!(100u128), "1864", false, same), + case(100i8, val!(100i8), "1864", false, same), + case(100i16, val!(100i16), "1864", false, same), + case(100i32, val!(100i32), "1864", false, same), + case(100i64, val!(100i64), "1864", false, same), + case(100i128, val!(100i128), "1864", false, same), + case(1000u16, val!(1000u16), "1903e8", false, same), + case(1000u32, val!(1000u32), "1903e8", false, same), + case(1000u64, val!(1000u64), "1903e8", false, same), + case(1000u128, val!(1000u128), "1903e8", false, same), + case(1000i16, val!(1000i16), "1903e8", false, same), + case(1000i32, val!(1000i32), "1903e8", false, same), + case(1000i64, val!(1000i64), "1903e8", false, same), + case(1000i128, val!(1000i128), "1903e8", false, same), + case(1000000u32, val!(1000000u32), "1a000f4240", false, same), + case(1000000u64, val!(1000000u64), "1a000f4240", false, same), + case(1000000u128, val!(1000000u128), "1a000f4240", false, same), + case(1000000i32, val!(1000000i32), "1a000f4240", false, same), + case(1000000i64, val!(1000000i64), "1a000f4240", false, same), + case(1000000i128, val!(1000000i128), "1a000f4240", false, same), + case(1000000000000u64, val!(1000000000000u64), "1b000000e8d4a51000", false, same), + case(1000000000000u128, val!(1000000000000u128), "1b000000e8d4a51000", false, same), + case(1000000000000i64, val!(1000000000000i64), "1b000000e8d4a51000", false, same), + case(1000000000000i128, val!(1000000000000i128), "1b000000e8d4a51000", false, same), + case(18446744073709551615u64, val!(18446744073709551615u64), "1bffffffffffffffff", false, same), + case(18446744073709551615u128, val!(18446744073709551615u128), "1bffffffffffffffff", false, same), + case(18446744073709551615i128, val!(18446744073709551615i128), "1bffffffffffffffff", false, same), + case(18446744073709551616u128, val!(18446744073709551616u128), "c249010000000000000000", false, same), + case(18446744073709551616i128, val!(18446744073709551616i128), "c249010000000000000000", false, same), + case(-18446744073709551617i128, val!(-18446744073709551617i128), "c349010000000000000000", false, same), + case(-18446744073709551616i128, val!(-18446744073709551616i128), "3bffffffffffffffff", false, same), + case(-1000i16, val!(-1000i16), "3903e7", false, same), + case(-1000i32, val!(-1000i32), "3903e7", false, same), + case(-1000i64, val!(-1000i64), "3903e7", false, same), + case(-1000i128, val!(-1000i128), "3903e7", false, same), + case(-100i8, val!(-100i8), "3863", false, same), + case(-100i16, val!(-100i16), "3863", false, same), + case(-100i32, val!(-100i32), "3863", false, same), + case(-100i64, val!(-100i64), "3863", false, same), + case(-100i128, val!(-100i128), "3863", false, same), + case(-10i8, val!(-10i8), "29", false, same), + case(-10i16, val!(-10i16), "29", false, same), + case(-10i32, val!(-10i32), "29", false, same), + case(-10i64, val!(-10i64), "29", false, same), + case(-10i128, val!(-10i128), "29", false, same), + case(-1i8, val!(-1i8), "20", false, same), + case(-1i16, val!(-1i16), "20", false, same), + case(-1i32, val!(-1i32), "20", false, same), + case(-1i64, val!(-1i64), "20", false, same), + case(-1i128, val!(-1i128), "20", false, same), + case(-1i8, val!(-1i8), "3b0000000000000000", true, same), + case(-1i16, val!(-1i16), "3b0000000000000000", true, same), + case(-1i32, val!(-1i32), "3b0000000000000000", true, same), + case(-1i64, val!(-1i64), "3b0000000000000000", true, same), + case(-1i128, val!(-1i128), "3b0000000000000000", true, same), + case(0.0f32, val!(0.0f32), "f90000", false, Float), + case(0.0f64, val!(0.0f64), "f90000", false, Float), + case(-0.0f32, val!(-0.0f32), "f98000", false, Float), + case(-0.0f64, val!(-0.0f64), "f98000", false, Float), + case(1.0f32, val!(1.0f32), "f93c00", false, Float), + case(1.0f64, val!(1.0f64), "f93c00", false, Float), + case(1.1f32, val!(1.1f32), "fa3f8ccccd", false, Float), // Not In RFC + case(1.1f64, val!(1.1f64), "fb3ff199999999999a", false, Float), + case(1.5f32, val!(1.5f32), "f93e00", false, Float), + case(1.5f64, val!(1.5f64), "f93e00", false, Float), + case(65504.0f32, val!(65504.0f32), "f97bff", false, Float), + case(65504.0f64, val!(65504.0f64), "f97bff", false, Float), + case(100000.0f32, val!(100000.0f32), "fa47c35000", false, Float), + case(100000.0f64, val!(100000.0f64), "fa47c35000", false, Float), + case(3.4028234663852886e+38f32, val!(3.4028234663852886e+38f32), "fa7f7fffff", false, Float), + case(3.4028234663852886e+38f64, val!(3.4028234663852886e+38f64), "fa7f7fffff", false, Float), + case(1.0e+300f64, val!(1.0e+300f64), "fb7e37e43c8800759c", false, Float), + case(5.960464477539063e-8f32, val!(5.960464477539063e-8f32), "f90001", false, Float), + case(5.960464477539063e-8f64, val!(5.960464477539063e-8f64), "f90001", false, Float), + case(0.00006103515625f32, val!(0.00006103515625f32), "f90400", false, Float), + case(0.00006103515625f64, val!(0.00006103515625f64), "f90400", false, Float), + case(-4.0f32, val!(-4.0f32), "f9c400", false, Float), + case(-4.0f64, val!(-4.0f64), "f9c400", false, Float), + case(-4.1f32, val!(-4.1f32), "fac0833333", false, Float), // Not In RFC + case(-4.1f64, val!(-4.1f64), "fbc010666666666666", false, Float), + case(core::f32::INFINITY, val!(core::f32::INFINITY), "f97c00", false, Float), + case(core::f64::INFINITY, val!(core::f64::INFINITY), "f97c00", false, Float), + case(core::f32::INFINITY, val!(core::f32::INFINITY), "fa7f800000", true, Float), + case(core::f64::INFINITY, val!(core::f64::INFINITY), "fa7f800000", true, Float), + case(core::f32::INFINITY, val!(core::f32::INFINITY), "fb7ff0000000000000", true, Float), + case(core::f64::INFINITY, val!(core::f64::INFINITY), "fb7ff0000000000000", true, Float), + case(-core::f32::INFINITY, val!(-core::f32::INFINITY), "f9fc00", false, Float), + case(-core::f64::INFINITY, val!(-core::f64::INFINITY), "f9fc00", false, Float), + case(-core::f32::INFINITY, val!(-core::f32::INFINITY), "faff800000", true, Float), + case(-core::f64::INFINITY, val!(-core::f64::INFINITY), "faff800000", true, Float), + case(-core::f32::INFINITY, val!(-core::f32::INFINITY), "fbfff0000000000000", true, Float), + case(-core::f64::INFINITY, val!(-core::f64::INFINITY), "fbfff0000000000000", true, Float), + case(core::f32::NAN, val!(core::f32::NAN), "f97e00", false, Float), + case(core::f64::NAN, val!(core::f64::NAN), "f97e00", false, Float), + case(core::f32::NAN, val!(core::f32::NAN), "fa7fc00000", true, Float), + case(core::f64::NAN, val!(core::f64::NAN), "fa7fc00000", true, Float), + case(core::f32::NAN, val!(core::f32::NAN), "fb7ff8000000000000", true, Float), + case(core::f64::NAN, val!(core::f64::NAN), "fb7ff8000000000000", true, Float), + case(-core::f32::NAN, val!(-core::f32::NAN), "f9fe00", false, Float), // Not In RFC + case(-core::f64::NAN, val!(-core::f64::NAN), "f9fe00", false, Float), // Not In RFC + case(-core::f32::NAN, val!(-core::f32::NAN), "faffc00000", true, Float), // Not In RFC + case(-core::f64::NAN, val!(-core::f64::NAN), "faffc00000", true, Float), // Not In RFC + case(-core::f32::NAN, val!(-core::f32::NAN), "fbfff8000000000000", true, Float), // Not In RFC + case(-core::f64::NAN, val!(-core::f64::NAN), "fbfff8000000000000", true, Float), // Not In RFC + case(false, val!(false), "f4", false, same), + case(true, val!(true), "f5", false, same), + case(Value::Null, Value::Null, "f6", false, same), + case(hex!(""), val!(&b""[..]), "40", false, same), + case(hex!("01020304"), val!(&b"\x01\x02\x03\x04"[..]), "4401020304", false, same), + case(hex!("0102030405"), val!(&b"\x01\x02\x03\x04\x05"[..]), "5f42010243030405ff", true, same), + case("", val!(""), "60", false, ToOwned::to_owned), + case("a", val!("a"), "6161", false, ToOwned::to_owned), + case('a', val!('a'), "6161", false, same), + case("IETF", val!("IETF"), "6449455446", false, ToOwned::to_owned), + case("\"\\", val!("\"\\"), "62225c", false, ToOwned::to_owned), + case("ü", val!("ü"), "62c3bc", false, ToOwned::to_owned), + case('ü', val!('ü'), "62c3bc", false, same), + case("水", val!("水"), "63e6b0b4", false, ToOwned::to_owned), + case('水', val!('水'), "63e6b0b4", false, same), + case("𐅑", val!("𐅑"), "64f0908591", false, ToOwned::to_owned), + case('𐅑', val!('𐅑'), "64f0908591", false, same), + case("streaming", val!("streaming"), "7f657374726561646d696e67ff", true, ToOwned::to_owned), + case(cbor!([]).unwrap(), Vec::<Value>::new().into(), "80", false, same), + case(cbor!([]).unwrap(), Vec::<Value>::new().into(), "9fff", true, same), + case(cbor!([1, 2, 3]).unwrap(), cbor!([1, 2, 3]).unwrap(), "83010203", false, same), + case(cbor!([1, [2, 3], [4, 5]]).unwrap(), cbor!([1, [2, 3], [4, 5]]).unwrap(), "8301820203820405", false, same), + case(cbor!([1, [2, 3], [4, 5]]).unwrap(), cbor!([1, [2, 3], [4, 5]]).unwrap(), "9f018202039f0405ffff", true, same), + case(cbor!([1, [2, 3], [4, 5]]).unwrap(), cbor!([1, [2, 3], [4, 5]]).unwrap(), "9f01820203820405ff", true, same), + case(cbor!([1, [2, 3], [4, 5]]).unwrap(), cbor!([1, [2, 3], [4, 5]]).unwrap(), "83018202039f0405ff", true, same), + case(cbor!([1, [2, 3], [4, 5]]).unwrap(), cbor!([1, [2, 3], [4, 5]]).unwrap(), "83019f0203ff820405", true, same), + case((1..=25).collect::<Vec<u8>>(), (1..=25).map(|x| x.into()).collect::<Vec<Value>>().into(), "98190102030405060708090a0b0c0d0e0f101112131415161718181819", false, same), + case((1..=25).collect::<Vec<u8>>(), (1..=25).map(|x| x.into()).collect::<Vec<Value>>().into(), "9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff", true, same), + case(HashMap::<u8, u8>::new(), Value::Map(vec![]), "a0", false, same), + case(BTreeMap::<u8, u8>::new(), Value::Map(vec![]), "a0", false, same), + case(map!{1 => 2, 3 => 4}, cbor!({1 => 2, 3 => 4}).unwrap(), "a201020304", false, same), + case(cbor!({"a" => 1, "b" => [2, 3]}).unwrap(), cbor!({"a" => 1, "b" => [2, 3]}).unwrap(), "a26161016162820203", false, same), + case(cbor!({"a" => 1, "b" => [2, 3]}).unwrap(), cbor!({"a" => 1, "b" => [2, 3]}).unwrap(), "bf61610161629f0203ffff", true, same), + case(cbor!(["a", {"b" => "c"}]).unwrap(), cbor!(["a", {"b" => "c"}]).unwrap(), "826161a161626163", false, same), + case(cbor!(["a", {"b" => "c"}]).unwrap(), cbor!(["a", {"b" => "c"}]).unwrap(), "826161bf61626163ff", true, same), + case(cbor!({"Fun" => true, "Amt" => -2}).unwrap(), cbor!({"Fun" => true, "Amt" => -2}).unwrap(), "bf6346756ef563416d7421ff", true, same), + case(map_big(), vmap_big(), "a56161614161626142616361436164614461656145", false, same), + case(Option::<u8>::None, Value::Null, "f6", false, same), // Not In RFC + case(Option::Some(7u8), val!(7u8), "07", false, same), // Not In RFC + case((), Value::Null, "f6", false, same), // Not In RFC + case(UnitStruct, Value::Null, "f6", false, same), // Not In RFC + case(Newtype(123), val!(123u8), "187b", false, same), // Not In RFC + case((22u8, 23u16), cbor!([22, 23]).unwrap(), "821617", false, same), // Not In RFC + case(TupleStruct(33, 34), cbor!([33, 34]).unwrap(), "8218211822", false, same), // Not In RFC + case(Enum::Unit, cbor!("Unit").unwrap(), "64556e6974", false, same), // Not In RFC + case(Enum::Newtype(45), cbor!({"Newtype" => 45}).unwrap(), "a1674e657774797065182d", false, same), // Not In RFC + case(Enum::Tuple(56, 67), cbor!({"Tuple" => [56, 67]}).unwrap(), "a1655475706c658218381843", false, same), // Not In RFC + case(Enum::Struct { first: 78, second: 89 }, cbor!({ "Struct" => { "first" => 78, "second" => 89 }}).unwrap(), "a166537472756374a2656669727374184e667365636f6e641859", false, same), // Not In RFC +)] +fn codec<'de, T: Serialize + Clone, V: Debug + PartialEq + DeserializeOwned, F: Fn(T) -> V>( + input: T, + value: Value, + bytes: &str, + alternate: bool, + equality: F, +) { + let bytes = hex::decode(bytes).unwrap(); + + if !alternate { + let mut encoded = Vec::new(); + into_writer(&input, &mut encoded).unwrap(); + eprintln!("{:x?} == {:x?}", bytes, encoded); + assert_eq!(bytes, encoded); + + let mut encoded = Vec::new(); + into_writer(&value, &mut encoded).unwrap(); + eprintln!("{:x?} == {:x?}", bytes, encoded); + assert_eq!(bytes, encoded); + + let encoded = Value::serialized(&input).unwrap(); + eprintln!("{:x?} == {:x?}", &value, &encoded); + assert!(veq(&value, &encoded)); + } + + let decoded: V = from_reader(&bytes[..]).unwrap(); + let answer = equality(input.clone()); + eprintln!("{:x?} == {:x?}", answer, decoded); + assert_eq!(answer, decoded); + + let decoded: Value = from_reader(&bytes[..]).unwrap(); + eprintln!("{:x?} == {:x?}", &value, &decoded); + assert!(veq(&value, &decoded)); + + let decoded: V = value.deserialized().unwrap(); + let answer = equality(input); + eprintln!("{:x?} == {:x?}", answer, decoded); + assert_eq!(answer, decoded); +} + +#[inline] +fn veq(lhs: &Value, rhs: &Value) -> bool { + if let Value::Float(l) = lhs { + if let Value::Float(r) = rhs { + return Float(*l) == Float(*r); + } + } + + lhs == rhs +} + +#[inline] +fn same<T>(x: T) -> T { + x +} + +#[derive(Debug, Deserialize)] +struct Float<T>(T); + +impl PartialEq for Float<f32> { + fn eq(&self, other: &Float<f32>) -> bool { + if self.0.is_nan() && other.0.is_nan() { + return true; + } + + self.0 == other.0 + } +} + +impl PartialEq for Float<f64> { + fn eq(&self, other: &Float<f64>) -> bool { + if self.0.is_nan() && other.0.is_nan() { + return true; + } + + self.0 == other.0 + } +} + +#[inline] +fn map_big() -> BTreeMap<String, String> { + let mut map = BTreeMap::new(); + map.insert("a".into(), "A".into()); + map.insert("b".into(), "B".into()); + map.insert("c".into(), "C".into()); + map.insert("d".into(), "D".into()); + map.insert("e".into(), "E".into()); + map +} + +#[inline] +fn vmap_big() -> Value { + Value::Map( + map_big() + .into_iter() + .map(|x| (x.0.into(), x.1.into())) + .collect(), + ) +} + +#[inline] +fn bigint() -> Value { + let bytes = hex::decode("0000000000000000000000000000000000000001").unwrap(); + Value::Tag(2, Value::Bytes(bytes).into()) +} + +#[derive(Deserialize, Serialize, Copy, Clone, Debug, PartialEq, Eq)] +struct UnitStruct; + +#[derive(Deserialize, Serialize, Copy, Clone, Debug, PartialEq, Eq)] +struct TupleStruct(u8, u16); + +#[derive(Deserialize, Serialize, Copy, Clone, Debug, PartialEq, Eq)] +struct Newtype(u8); + +#[derive(Deserialize, Serialize, Copy, Clone, Debug, PartialEq, Eq)] +enum Enum { + Unit, + Newtype(u8), + Tuple(u8, u16), + Struct { first: u8, second: u16 }, +} + +#[rstest( + input, + case(vec![]), + case(vec![0u8, 1, 2, 3]), +)] +fn byte_vec_serde_bytes_compatibility(input: Vec<u8>) { + use serde_bytes::ByteBuf; + + let mut buf = Vec::new(); + into_writer(&input, &mut buf).unwrap(); + let bytes: ByteBuf = from_reader(&buf[..]).unwrap(); + assert_eq!(input, bytes.to_vec()); + + let mut buf = Vec::new(); + into_writer(&ByteBuf::from(input.clone()), &mut buf).unwrap(); + let bytes: Vec<u8> = from_reader(&buf[..]).unwrap(); + assert_eq!(input, bytes); +} + +#[derive(Serialize, Deserialize, Eq, PartialEq, Debug)] +struct Foo { + bar: u8, +} + +#[rstest(input, expected, + case("a163626172182a", Foo { bar: 42 }), + case("a143626172182a", Foo { bar: 42 }), +)] +fn handle_struct_field_names(input: &str, expected: Foo) { + let buf = hex::decode(input).unwrap(); + let read = from_reader(&buf[..]).unwrap(); + assert_eq!(expected, read); +} diff --git a/vendor/ciborium/tests/error.rs b/vendor/ciborium/tests/error.rs new file mode 100644 index 000000000..13bcd5ac5 --- /dev/null +++ b/vendor/ciborium/tests/error.rs @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: Apache-2.0 + +use ciborium::{ + de::{from_reader, Error}, + ser::into_writer, + value::Value, +}; +use rstest::rstest; + +#[rstest(bytes, error, + // Invalid value + case("1e", Error::Syntax(0)), + + // Indeterminate integers are invalid + case("1f", Error::Syntax(0)), + + // Indeterminate integer in an array + case("83011f03", Error::Syntax(2)), + + // Integer in a string continuation + case("7F616101FF", Error::Syntax(3)), + + // Bytes in a string continuation + case("7F61614101FF", Error::Syntax(3)), + + // Invalid UTF-8 + case("62C328", Error::Syntax(0)), + + // Invalid UTF-8 in a string continuation + case("7F62C328FF", Error::Syntax(1)), +)] +fn test(bytes: &str, error: Error<std::io::Error>) { + let bytes = hex::decode(bytes).unwrap(); + + let correct = match error { + Error::Io(..) => panic!(), + Error::Syntax(x) => ("syntax", Some(x), None), + Error::Semantic(x, y) => ("semantic", x, Some(y)), + Error::RecursionLimitExceeded => panic!(), + }; + + let result: Result<Value, _> = from_reader(&bytes[..]); + let actual = match result.unwrap_err() { + Error::Io(..) => panic!(), + Error::Syntax(x) => ("syntax", Some(x), None), + Error::Semantic(x, y) => ("semantic", x, Some(y)), + Error::RecursionLimitExceeded => panic!(), + }; + + assert_eq!(correct, actual); +} + +#[test] +fn test_long_utf8_deserialization() { + let s = (0..2000).map(|_| 'ボ').collect::<String>(); + let mut v = Vec::new(); + into_writer(&s, &mut v).unwrap(); + let _: String = from_reader(&*v).unwrap(); +} diff --git a/vendor/ciborium/tests/fuzz.rs b/vendor/ciborium/tests/fuzz.rs new file mode 100644 index 000000000..2b9d0ecd9 --- /dev/null +++ b/vendor/ciborium/tests/fuzz.rs @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: Apache-2.0 + +use std::fs::File; +use std::io::Read; +use std::io::Write; +use std::os::raw::c_int; +use std::os::unix::io::{FromRawFd, RawFd}; + +use ciborium::{de::from_reader, value::Value}; +use rand::Rng; + +const ITERATIONS: usize = 128 * 1024; + +#[allow(non_camel_case_types)] +type pid_t = i32; + +extern "C" { + fn close(fd: RawFd) -> c_int; + fn fork() -> pid_t; + fn pipe(pipefd: &mut [RawFd; 2]) -> c_int; + fn waitpid(pid: pid_t, wstatus: *mut c_int, options: c_int) -> pid_t; +} + +#[test] +fn fuzz() { + let mut fds: [RawFd; 2] = [0; 2]; + assert_eq!(unsafe { pipe(&mut fds) }, 0); + + let pid = unsafe { fork() }; + assert!(pid >= 0); + + match pid { + 0 => { + let mut child = unsafe { File::from_raw_fd(fds[1]) }; + unsafe { close(fds[0]) }; + + let mut rng = rand::thread_rng(); + let mut buffer = [0u8; 32]; + + for _ in 0..ITERATIONS { + let len = rng.gen_range(0..buffer.len()); + rng.fill(&mut buffer[..len]); + + writeln!(child, "{}", hex::encode(&buffer[..len])).unwrap(); + writeln!(child, "{:?}", from_reader::<Value, _>(&buffer[..len])).unwrap(); + } + } + + pid => { + let mut parent = unsafe { File::from_raw_fd(fds[0]) }; + unsafe { close(fds[1]) }; + + let mut string = String::new(); + parent.read_to_string(&mut string).unwrap(); + eprint!("{}", string); + + let mut status = 0; + assert_eq!(pid, unsafe { waitpid(pid, &mut status, 0) }); + + eprintln!("exit status: {:?}", status); + assert_eq!(0, status); + } + } +} diff --git a/vendor/ciborium/tests/macro.rs b/vendor/ciborium/tests/macro.rs new file mode 100644 index 000000000..a73fc849c --- /dev/null +++ b/vendor/ciborium/tests/macro.rs @@ -0,0 +1,358 @@ +// SPDX-License-Identifier: Apache-2.0 + +extern crate alloc; + +use ciborium::{ + cbor, + value::{Integer, Value, Value::Null}, +}; + +use rstest::rstest; +use serde_bytes::Bytes; + +macro_rules! map { + ($($key:expr => $val:expr),* $(,)*) => { + Value::Map(vec![$( + ( + Value::serialized(&$key).unwrap(), + Value::serialized(&$val).unwrap() + ) + ),*]) + }; +} + +macro_rules! arr { + ($($val:expr),*) => { + Value::Array(vec![$( + Value::serialized(&$val).unwrap() + ),*]) + }; +} + +#[rstest(answer, question, + // Non-numeric simple types + case(Value::Null, cbor!(null).unwrap()), + case(Value::Bool(true), cbor!(true).unwrap()), + case(Value::Bool(false), cbor!(false).unwrap()), + case(Value::Text("foo".into()), cbor!("foo").unwrap()), + case(Value::Bytes(vec![0, 1, 2]), cbor!(Bytes::new(b"\x00\x01\x02")).unwrap()), + + // Numeric simple types + case(Value::Integer(Integer::from(123)), cbor!(123).unwrap()), + case(Value::Integer(Integer::from(-123)), cbor!(-123).unwrap()), + case(Value::Float(1.23), cbor!(1.23).unwrap()), + case(Value::Float(-1.23), cbor!(-1.23).unwrap()), + case(Value::Float(2.5e+1), cbor!(2.5e+1).unwrap()), + case(Value::Float(-2.5e+1), cbor!(-2.5e+1).unwrap()), + + // Simple array formulations + case(arr![], cbor!([]).unwrap()), + case(arr![Null], cbor!([null]).unwrap()), + case(arr![true], cbor!([true]).unwrap()), + case(arr![false], cbor!([false]).unwrap()), + case(arr!["foo"], cbor!(["foo"]).unwrap()), + case(arr![123], cbor!([123]).unwrap()), + case(arr![-123], cbor!([-123]).unwrap()), + case(arr![1.23], cbor!([1.23]).unwrap()), + case(arr![-1.23], cbor!([-1.23]).unwrap()), + case(arr![2.5e+1], cbor!([2.5e+1]).unwrap()), + case(arr![2.5e+1], cbor!([2.5e+1]).unwrap()), + case(arr![[1, 2]], cbor!([[1, 2]]).unwrap()), + case(arr![map! {1=>2,3=>4}], cbor!([{1=>2,3=>4}]).unwrap()), + + // Two-item array formluations + case(arr![Null, Null], cbor!([null, null]).unwrap()), + case(arr![Null, true], cbor!([null, true]).unwrap()), + case(arr![Null, false], cbor!([null, false]).unwrap()), + case(arr![Null, "foo"], cbor!([null, "foo"]).unwrap()), + case(arr![Null, 123], cbor!([null, 123]).unwrap()), + case(arr![Null, -123], cbor!([null, -123]).unwrap()), + case(arr![Null, 1.23], cbor!([null, 1.23]).unwrap()), + case(arr![Null, -1.23], cbor!([null, -1.23]).unwrap()), + case(arr![Null, 2.5e+1], cbor!([null, 2.5e+1]).unwrap()), + case(arr![Null, 2.5e+1], cbor!([null, 2.5e+1]).unwrap()), + case(arr![Null, [1, 2]], cbor!([null, [1, 2]]).unwrap()), + case(arr![Null, map! {1=>2,3=>4}], cbor!([null, {1=>2,3=>4}]).unwrap()), + case(arr![true, Null], cbor!([true, null]).unwrap()), + case(arr![true, true], cbor!([true, true]).unwrap()), + case(arr![true, false], cbor!([true, false]).unwrap()), + case(arr![true, "foo"], cbor!([true, "foo"]).unwrap()), + case(arr![true, 123], cbor!([true, 123]).unwrap()), + case(arr![true, -123], cbor!([true, -123]).unwrap()), + case(arr![true, 1.23], cbor!([true, 1.23]).unwrap()), + case(arr![true, -1.23], cbor!([true, -1.23]).unwrap()), + case(arr![true, 2.5e+1], cbor!([true, 2.5e+1]).unwrap()), + case(arr![true, 2.5e+1], cbor!([true, 2.5e+1]).unwrap()), + case(arr![true, [1, 2]], cbor!([true, [1, 2]]).unwrap()), + case(arr![true, map! {1=>2,3=>4}], cbor!([true, {1=>2,3=>4}]).unwrap()), + case(arr![false, Null], cbor!([false, null]).unwrap()), + case(arr![false, true], cbor!([false, true]).unwrap()), + case(arr![false, false], cbor!([false, false]).unwrap()), + case(arr![false, "foo"], cbor!([false, "foo"]).unwrap()), + case(arr![false, 123], cbor!([false, 123]).unwrap()), + case(arr![false, -123], cbor!([false, -123]).unwrap()), + case(arr![false, 1.23], cbor!([false, 1.23]).unwrap()), + case(arr![false, -1.23], cbor!([false, -1.23]).unwrap()), + case(arr![false, 2.5e+1], cbor!([false, 2.5e+1]).unwrap()), + case(arr![false, 2.5e+1], cbor!([false, 2.5e+1]).unwrap()), + case(arr![false, [1, 2]], cbor!([false, [1, 2]]).unwrap()), + case(arr![false, map! {1=>2,3=>4}], cbor!([false, {1=>2,3=>4}]).unwrap()), + case(arr!["foo", Null], cbor!(["foo", null]).unwrap()), + case(arr!["foo", true], cbor!(["foo", true]).unwrap()), + case(arr!["foo", false], cbor!(["foo", false]).unwrap()), + case(arr!["foo", "foo"], cbor!(["foo", "foo"]).unwrap()), + case(arr!["foo", 123], cbor!(["foo", 123]).unwrap()), + case(arr!["foo", -123], cbor!(["foo", -123]).unwrap()), + case(arr!["foo", 1.23], cbor!(["foo", 1.23]).unwrap()), + case(arr!["foo", -1.23], cbor!(["foo", -1.23]).unwrap()), + case(arr!["foo", 2.5e+1], cbor!(["foo", 2.5e+1]).unwrap()), + case(arr!["foo", 2.5e+1], cbor!(["foo", 2.5e+1]).unwrap()), + case(arr!["foo", [1, 2]], cbor!(["foo", [1, 2]]).unwrap()), + case(arr!["foo", map! {1=>2,3=>4}], cbor!(["foo", {1=>2,3=>4}]).unwrap()), + case(arr![123, Null], cbor!([123, null]).unwrap()), + case(arr![123, true], cbor!([123, true]).unwrap()), + case(arr![123, false], cbor!([123, false]).unwrap()), + case(arr![123, "foo"], cbor!([123, "foo"]).unwrap()), + case(arr![123, 123], cbor!([123, 123]).unwrap()), + case(arr![123, -123], cbor!([123, -123]).unwrap()), + case(arr![123, 1.23], cbor!([123, 1.23]).unwrap()), + case(arr![123, -1.23], cbor!([123, -1.23]).unwrap()), + case(arr![123, 2.5e+1], cbor!([123, 2.5e+1]).unwrap()), + case(arr![123, 2.5e+1], cbor!([123, 2.5e+1]).unwrap()), + case(arr![123, [1, 2]], cbor!([123, [1, 2]]).unwrap()), + case(arr![123, map! {1=>2,3=>4}], cbor!([123, {1=>2,3=>4}]).unwrap()), + case(arr![-123, Null], cbor!([-123, null]).unwrap()), + case(arr![-123, true], cbor!([-123, true]).unwrap()), + case(arr![-123, false], cbor!([-123, false]).unwrap()), + case(arr![-123, "foo"], cbor!([-123, "foo"]).unwrap()), + case(arr![-123, 123], cbor!([-123, 123]).unwrap()), + case(arr![-123, -123], cbor!([-123, -123]).unwrap()), + case(arr![-123, 1.23], cbor!([-123, 1.23]).unwrap()), + case(arr![-123, -1.23], cbor!([-123, -1.23]).unwrap()), + case(arr![-123, 2.5e+1], cbor!([-123, 2.5e+1]).unwrap()), + case(arr![-123, 2.5e+1], cbor!([-123, 2.5e+1]).unwrap()), + case(arr![-123, [1, 2]], cbor!([-123, [1, 2]]).unwrap()), + case(arr![-123, map! {1=>2,3=>4}], cbor!([-123, {1=>2,3=>4}]).unwrap()), + case(arr![1.23, Null], cbor!([1.23, null]).unwrap()), + case(arr![1.23, true], cbor!([1.23, true]).unwrap()), + case(arr![1.23, false], cbor!([1.23, false]).unwrap()), + case(arr![1.23, "foo"], cbor!([1.23, "foo"]).unwrap()), + case(arr![1.23, 123], cbor!([1.23, 123]).unwrap()), + case(arr![1.23, -123], cbor!([1.23, -123]).unwrap()), + case(arr![1.23, 1.23], cbor!([1.23, 1.23]).unwrap()), + case(arr![1.23, -1.23], cbor!([1.23, -1.23]).unwrap()), + case(arr![1.23, 2.5e+1], cbor!([1.23, 2.5e+1]).unwrap()), + case(arr![1.23, 2.5e+1], cbor!([1.23, 2.5e+1]).unwrap()), + case(arr![1.23, [1, 2]], cbor!([1.23, [1, 2]]).unwrap()), + case(arr![1.23, map! {1=>2,3=>4}], cbor!([1.23, {1=>2,3=>4}]).unwrap()), + case(arr![-1.23, Null], cbor!([-1.23, null]).unwrap()), + case(arr![-1.23, true], cbor!([-1.23, true]).unwrap()), + case(arr![-1.23, false], cbor!([-1.23, false]).unwrap()), + case(arr![-1.23, "foo"], cbor!([-1.23, "foo"]).unwrap()), + case(arr![-1.23, 123], cbor!([-1.23, 123]).unwrap()), + case(arr![-1.23, -123], cbor!([-1.23, -123]).unwrap()), + case(arr![-1.23, 1.23], cbor!([-1.23, 1.23]).unwrap()), + case(arr![-1.23, -1.23], cbor!([-1.23, -1.23]).unwrap()), + case(arr![-1.23, 2.5e+1], cbor!([-1.23, 2.5e+1]).unwrap()), + case(arr![-1.23, 2.5e+1], cbor!([-1.23, 2.5e+1]).unwrap()), + case(arr![-1.23, [1, 2]], cbor!([-1.23, [1, 2]]).unwrap()), + case(arr![-1.23, map! {1=>2,3=>4}], cbor!([-1.23, {1=>2,3=>4}]).unwrap()), + case(arr![2.5e+1, Null], cbor!([2.5e+1, null]).unwrap()), + case(arr![2.5e+1, true], cbor!([2.5e+1, true]).unwrap()), + case(arr![2.5e+1, false], cbor!([2.5e+1, false]).unwrap()), + case(arr![2.5e+1, "foo"], cbor!([2.5e+1, "foo"]).unwrap()), + case(arr![2.5e+1, 123], cbor!([2.5e+1, 123]).unwrap()), + case(arr![2.5e+1, -123], cbor!([2.5e+1, -123]).unwrap()), + case(arr![2.5e+1, 1.23], cbor!([2.5e+1, 1.23]).unwrap()), + case(arr![2.5e+1, -1.23], cbor!([2.5e+1, -1.23]).unwrap()), + case(arr![2.5e+1, 2.5e+1], cbor!([2.5e+1, 2.5e+1]).unwrap()), + case(arr![2.5e+1, 2.5e+1], cbor!([2.5e+1, 2.5e+1]).unwrap()), + case(arr![2.5e+1, [1, 2]], cbor!([2.5e+1, [1, 2]]).unwrap()), + case(arr![2.5e+1, map! {1=>2,3=>4}], cbor!([2.5e+1, {1=>2,3=>4}]).unwrap()), + case(arr![2.5e+1, Null], cbor!([2.5e+1, null]).unwrap()), + case(arr![2.5e+1, true], cbor!([2.5e+1, true]).unwrap()), + case(arr![2.5e+1, false], cbor!([2.5e+1, false]).unwrap()), + case(arr![2.5e+1, "foo"], cbor!([2.5e+1, "foo"]).unwrap()), + case(arr![2.5e+1, 123], cbor!([2.5e+1, 123]).unwrap()), + case(arr![2.5e+1, -123], cbor!([2.5e+1, -123]).unwrap()), + case(arr![2.5e+1, 1.23], cbor!([2.5e+1, 1.23]).unwrap()), + case(arr![2.5e+1, -1.23], cbor!([2.5e+1, -1.23]).unwrap()), + case(arr![2.5e+1, 2.5e+1], cbor!([2.5e+1, 2.5e+1]).unwrap()), + case(arr![2.5e+1, 2.5e+1], cbor!([2.5e+1, 2.5e+1]).unwrap()), + case(arr![2.5e+1, [1, 2]], cbor!([2.5e+1, [1, 2]]).unwrap()), + case(arr![2.5e+1, map! {1=>2,3=>4}], cbor!([2.5e+1, {1=>2,3=>4}]).unwrap()), + case(arr![[1, 2], Null], cbor!([[1, 2], null]).unwrap()), + case(arr![[1, 2], true], cbor!([[1, 2], true]).unwrap()), + case(arr![[1, 2], false], cbor!([[1, 2], false]).unwrap()), + case(arr![[1, 2], "foo"], cbor!([[1, 2], "foo"]).unwrap()), + case(arr![[1, 2], 123], cbor!([[1, 2], 123]).unwrap()), + case(arr![[1, 2], -123], cbor!([[1, 2], -123]).unwrap()), + case(arr![[1, 2], 1.23], cbor!([[1, 2], 1.23]).unwrap()), + case(arr![[1, 2], -1.23], cbor!([[1, 2], -1.23]).unwrap()), + case(arr![[1, 2], 2.5e+1], cbor!([[1, 2], 2.5e+1]).unwrap()), + case(arr![[1, 2], 2.5e+1], cbor!([[1, 2], 2.5e+1]).unwrap()), + case(arr![[1, 2], [1, 2]], cbor!([[1, 2], [1, 2]]).unwrap()), + case(arr![[1, 2], map! {1=>2,3=>4}], cbor!([[1, 2], {1=>2,3=>4}]).unwrap()), + case(arr![map! {1=>2,3=>4}, Null], cbor!([{1=>2,3=>4}, null]).unwrap()), + case(arr![map! {1=>2,3=>4}, true], cbor!([{1=>2,3=>4}, true]).unwrap()), + case(arr![map! {1=>2,3=>4}, false], cbor!([{1=>2,3=>4}, false]).unwrap()), + case(arr![map! {1=>2,3=>4}, "foo"], cbor!([{1=>2,3=>4}, "foo"]).unwrap()), + case(arr![map! {1=>2,3=>4}, 123], cbor!([{1=>2,3=>4}, 123]).unwrap()), + case(arr![map! {1=>2,3=>4}, -123], cbor!([{1=>2,3=>4}, -123]).unwrap()), + case(arr![map! {1=>2,3=>4}, 1.23], cbor!([{1=>2,3=>4}, 1.23]).unwrap()), + case(arr![map! {1=>2,3=>4}, -1.23], cbor!([{1=>2,3=>4}, -1.23]).unwrap()), + case(arr![map! {1=>2,3=>4}, 2.5e+1], cbor!([{1=>2,3=>4}, 2.5e+1]).unwrap()), + case(arr![map! {1=>2,3=>4}, 2.5e+1], cbor!([{1=>2,3=>4}, 2.5e+1]).unwrap()), + case(arr![map! {1=>2,3=>4}, [1, 2]], cbor!([{1=>2,3=>4}, [1, 2]]).unwrap()), + case(arr![map! {1=>2,3=>4}, map! {1=>2,3=>4}], cbor!([{1=>2,3=>4}, {1=>2,3=>4}]).unwrap()), + + // Map formulations + case(map! {}, cbor!({}).unwrap()), + case(map! {Null => Null}, cbor!({ null => null }).unwrap()), + case(map! {Null => true}, cbor!({ null => true }).unwrap()), + case(map! {Null => false}, cbor!({ null => false }).unwrap()), + case(map! {Null => "foo"}, cbor!({ null => "foo" }).unwrap()), + case(map! {Null => 123}, cbor!({ null => 123 }).unwrap()), + case(map! {Null => -123}, cbor!({ null => -123 }).unwrap()), + case(map! {Null => 1.23}, cbor!({ null => 1.23 }).unwrap()), + case(map! {Null => -1.23}, cbor!({ null => -1.23 }).unwrap()), + case(map! {Null => 2.5e+1}, cbor!({ null => 2.5e+1 }).unwrap()), + case(map! {Null => 2.5e+1}, cbor!({ null => 2.5e+1 }).unwrap()), + case(map! {Null => [1, 2]}, cbor!({ null => [1, 2] }).unwrap()), + case(map! {Null => map! {1=>2,3=>4}}, cbor!({ null => {1=>2,3=>4} }).unwrap()), + case(map! {true => Null}, cbor!({ true => null }).unwrap()), + case(map! {true => true}, cbor!({ true => true }).unwrap()), + case(map! {true => false}, cbor!({ true => false }).unwrap()), + case(map! {true => "foo"}, cbor!({ true => "foo" }).unwrap()), + case(map! {true => 123}, cbor!({ true => 123 }).unwrap()), + case(map! {true => -123}, cbor!({ true => -123 }).unwrap()), + case(map! {true => 1.23}, cbor!({ true => 1.23 }).unwrap()), + case(map! {true => -1.23}, cbor!({ true => -1.23 }).unwrap()), + case(map! {true => 2.5e+1}, cbor!({ true => 2.5e+1 }).unwrap()), + case(map! {true => 2.5e+1}, cbor!({ true => 2.5e+1 }).unwrap()), + case(map! {true => [1, 2]}, cbor!({ true => [1, 2] }).unwrap()), + case(map! {true => map! {1=>2,3=>4}}, cbor!({ true => {1=>2,3=>4} }).unwrap()), + case(map! {false => Null}, cbor!({ false => null }).unwrap()), + case(map! {false => true}, cbor!({ false => true }).unwrap()), + case(map! {false => false}, cbor!({ false => false }).unwrap()), + case(map! {false => "foo"}, cbor!({ false => "foo" }).unwrap()), + case(map! {false => 123}, cbor!({ false => 123 }).unwrap()), + case(map! {false => -123}, cbor!({ false => -123 }).unwrap()), + case(map! {false => 1.23}, cbor!({ false => 1.23 }).unwrap()), + case(map! {false => -1.23}, cbor!({ false => -1.23 }).unwrap()), + case(map! {false => 2.5e+1}, cbor!({ false => 2.5e+1 }).unwrap()), + case(map! {false => 2.5e+1}, cbor!({ false => 2.5e+1 }).unwrap()), + case(map! {false => [1, 2]}, cbor!({ false => [1, 2] }).unwrap()), + case(map! {false => map! {1=>2,3=>4}}, cbor!({ false => {1=>2,3=>4} }).unwrap()), + case(map! {"foo" => Null}, cbor!({ "foo" => null }).unwrap()), + case(map! {"foo" => true}, cbor!({ "foo" => true }).unwrap()), + case(map! {"foo" => false}, cbor!({ "foo" => false }).unwrap()), + case(map! {"foo" => "foo"}, cbor!({ "foo" => "foo" }).unwrap()), + case(map! {"foo" => 123}, cbor!({ "foo" => 123 }).unwrap()), + case(map! {"foo" => -123}, cbor!({ "foo" => -123 }).unwrap()), + case(map! {"foo" => 1.23}, cbor!({ "foo" => 1.23 }).unwrap()), + case(map! {"foo" => -1.23}, cbor!({ "foo" => -1.23 }).unwrap()), + case(map! {"foo" => 2.5e+1}, cbor!({ "foo" => 2.5e+1 }).unwrap()), + case(map! {"foo" => 2.5e+1}, cbor!({ "foo" => 2.5e+1 }).unwrap()), + case(map! {"foo" => [1, 2]}, cbor!({ "foo" => [1, 2] }).unwrap()), + case(map! {"foo" => map! {1=>2,3=>4}}, cbor!({ "foo" => {1=>2,3=>4} }).unwrap()), + case(map! {123 => Null}, cbor!({ 123 => null }).unwrap()), + case(map! {123 => true}, cbor!({ 123 => true }).unwrap()), + case(map! {123 => false}, cbor!({ 123 => false }).unwrap()), + case(map! {123 => "foo"}, cbor!({ 123 => "foo" }).unwrap()), + case(map! {123 => 123}, cbor!({ 123 => 123 }).unwrap()), + case(map! {123 => -123}, cbor!({ 123 => -123 }).unwrap()), + case(map! {123 => 1.23}, cbor!({ 123 => 1.23 }).unwrap()), + case(map! {123 => -1.23}, cbor!({ 123 => -1.23 }).unwrap()), + case(map! {123 => 2.5e+1}, cbor!({ 123 => 2.5e+1 }).unwrap()), + case(map! {123 => 2.5e+1}, cbor!({ 123 => 2.5e+1 }).unwrap()), + case(map! {123 => [1, 2]}, cbor!({ 123 => [1, 2] }).unwrap()), + case(map! {123 => map! {1=>2,3=>4}}, cbor!({ 123 => {1=>2,3=>4} }).unwrap()), + case(map! {-123 => Null}, cbor!({ -123 => null }).unwrap()), + case(map! {-123 => true}, cbor!({ -123 => true }).unwrap()), + case(map! {-123 => false}, cbor!({ -123 => false }).unwrap()), + case(map! {-123 => "foo"}, cbor!({ -123 => "foo" }).unwrap()), + case(map! {-123 => 123}, cbor!({ -123 => 123 }).unwrap()), + case(map! {-123 => -123}, cbor!({ -123 => -123 }).unwrap()), + case(map! {-123 => 1.23}, cbor!({ -123 => 1.23 }).unwrap()), + case(map! {-123 => -1.23}, cbor!({ -123 => -1.23 }).unwrap()), + case(map! {-123 => 2.5e+1}, cbor!({ -123 => 2.5e+1 }).unwrap()), + case(map! {-123 => 2.5e+1}, cbor!({ -123 => 2.5e+1 }).unwrap()), + case(map! {-123 => [1, 2]}, cbor!({ -123 => [1, 2] }).unwrap()), + case(map! {-123 => map! {1=>2,3=>4}}, cbor!({ -123 => {1=>2,3=>4} }).unwrap()), + case(map! {1.23 => Null}, cbor!({ 1.23 => null }).unwrap()), + case(map! {1.23 => true}, cbor!({ 1.23 => true }).unwrap()), + case(map! {1.23 => false}, cbor!({ 1.23 => false }).unwrap()), + case(map! {1.23 => "foo"}, cbor!({ 1.23 => "foo" }).unwrap()), + case(map! {1.23 => 123}, cbor!({ 1.23 => 123 }).unwrap()), + case(map! {1.23 => -123}, cbor!({ 1.23 => -123 }).unwrap()), + case(map! {1.23 => 1.23}, cbor!({ 1.23 => 1.23 }).unwrap()), + case(map! {1.23 => -1.23}, cbor!({ 1.23 => -1.23 }).unwrap()), + case(map! {1.23 => 2.5e+1}, cbor!({ 1.23 => 2.5e+1 }).unwrap()), + case(map! {1.23 => 2.5e+1}, cbor!({ 1.23 => 2.5e+1 }).unwrap()), + case(map! {1.23 => [1, 2]}, cbor!({ 1.23 => [1, 2] }).unwrap()), + case(map! {1.23 => map! {1=>2,3=>4}}, cbor!({ 1.23 => {1=>2,3=>4} }).unwrap()), + case(map! {-1.23 => Null}, cbor!({ -1.23 => null }).unwrap()), + case(map! {-1.23 => true}, cbor!({ -1.23 => true }).unwrap()), + case(map! {-1.23 => false}, cbor!({ -1.23 => false }).unwrap()), + case(map! {-1.23 => "foo"}, cbor!({ -1.23 => "foo" }).unwrap()), + case(map! {-1.23 => 123}, cbor!({ -1.23 => 123 }).unwrap()), + case(map! {-1.23 => -123}, cbor!({ -1.23 => -123 }).unwrap()), + case(map! {-1.23 => 1.23}, cbor!({ -1.23 => 1.23 }).unwrap()), + case(map! {-1.23 => -1.23}, cbor!({ -1.23 => -1.23 }).unwrap()), + case(map! {-1.23 => 2.5e+1}, cbor!({ -1.23 => 2.5e+1 }).unwrap()), + case(map! {-1.23 => 2.5e+1}, cbor!({ -1.23 => 2.5e+1 }).unwrap()), + case(map! {-1.23 => [1, 2]}, cbor!({ -1.23 => [1, 2] }).unwrap()), + case(map! {-1.23 => map! {1=>2,3=>4}}, cbor!({ -1.23 => {1=>2,3=>4} }).unwrap()), + case(map! {2.5e+1 => Null}, cbor!({ 2.5e+1 => null }).unwrap()), + case(map! {2.5e+1 => true}, cbor!({ 2.5e+1 => true }).unwrap()), + case(map! {2.5e+1 => false}, cbor!({ 2.5e+1 => false }).unwrap()), + case(map! {2.5e+1 => "foo"}, cbor!({ 2.5e+1 => "foo" }).unwrap()), + case(map! {2.5e+1 => 123}, cbor!({ 2.5e+1 => 123 }).unwrap()), + case(map! {2.5e+1 => -123}, cbor!({ 2.5e+1 => -123 }).unwrap()), + case(map! {2.5e+1 => 1.23}, cbor!({ 2.5e+1 => 1.23 }).unwrap()), + case(map! {2.5e+1 => -1.23}, cbor!({ 2.5e+1 => -1.23 }).unwrap()), + case(map! {2.5e+1 => 2.5e+1}, cbor!({ 2.5e+1 => 2.5e+1 }).unwrap()), + case(map! {2.5e+1 => 2.5e+1}, cbor!({ 2.5e+1 => 2.5e+1 }).unwrap()), + case(map! {2.5e+1 => [1, 2]}, cbor!({ 2.5e+1 => [1, 2] }).unwrap()), + case(map! {2.5e+1 => map! {1=>2,3=>4}}, cbor!({ 2.5e+1 => {1=>2,3=>4} }).unwrap()), + case(map! {2.5e+1 => Null}, cbor!({ 2.5e+1 => null }).unwrap()), + case(map! {2.5e+1 => true}, cbor!({ 2.5e+1 => true }).unwrap()), + case(map! {2.5e+1 => false}, cbor!({ 2.5e+1 => false }).unwrap()), + case(map! {2.5e+1 => "foo"}, cbor!({ 2.5e+1 => "foo" }).unwrap()), + case(map! {2.5e+1 => 123}, cbor!({ 2.5e+1 => 123 }).unwrap()), + case(map! {2.5e+1 => -123}, cbor!({ 2.5e+1 => -123 }).unwrap()), + case(map! {2.5e+1 => 1.23}, cbor!({ 2.5e+1 => 1.23 }).unwrap()), + case(map! {2.5e+1 => -1.23}, cbor!({ 2.5e+1 => -1.23 }).unwrap()), + case(map! {2.5e+1 => 2.5e+1}, cbor!({ 2.5e+1 => 2.5e+1 }).unwrap()), + case(map! {2.5e+1 => 2.5e+1}, cbor!({ 2.5e+1 => 2.5e+1 }).unwrap()), + case(map! {2.5e+1 => [1, 2]}, cbor!({ 2.5e+1 => [1, 2] }).unwrap()), + case(map! {2.5e+1 => map! {1=>2,3=>4}}, cbor!({ 2.5e+1 => {1=>2,3=>4} }).unwrap()), + case(map! {[1, 2] => Null}, cbor!({ [1, 2] => null }).unwrap()), + case(map! {[1, 2] => true}, cbor!({ [1, 2] => true }).unwrap()), + case(map! {[1, 2] => false}, cbor!({ [1, 2] => false }).unwrap()), + case(map! {[1, 2] => "foo"}, cbor!({ [1, 2] => "foo" }).unwrap()), + case(map! {[1, 2] => 123}, cbor!({ [1, 2] => 123 }).unwrap()), + case(map! {[1, 2] => -123}, cbor!({ [1, 2] => -123 }).unwrap()), + case(map! {[1, 2] => 1.23}, cbor!({ [1, 2] => 1.23 }).unwrap()), + case(map! {[1, 2] => -1.23}, cbor!({ [1, 2] => -1.23 }).unwrap()), + case(map! {[1, 2] => 2.5e+1}, cbor!({ [1, 2] => 2.5e+1 }).unwrap()), + case(map! {[1, 2] => 2.5e+1}, cbor!({ [1, 2] => 2.5e+1 }).unwrap()), + case(map! {[1, 2] => [1, 2]}, cbor!({ [1, 2] => [1, 2] }).unwrap()), + case(map! {[1, 2] => map! {1=>2,3=>4}}, cbor!({ [1, 2] => {1=>2,3=>4} }).unwrap()), + case(map! {map! {1=>2,3=>4} => Null}, cbor!({ {1=>2,3=>4} => null }).unwrap()), + case(map! {map! {1=>2,3=>4} => true}, cbor!({ {1=>2,3=>4} => true }).unwrap()), + case(map! {map! {1=>2,3=>4} => false}, cbor!({ {1=>2,3=>4} => false }).unwrap()), + case(map! {map! {1=>2,3=>4} => "foo"}, cbor!({ {1=>2,3=>4} => "foo" }).unwrap()), + case(map! {map! {1=>2,3=>4} => 123}, cbor!({ {1=>2,3=>4} => 123 }).unwrap()), + case(map! {map! {1=>2,3=>4} => -123}, cbor!({ {1=>2,3=>4} => -123 }).unwrap()), + case(map! {map! {1=>2,3=>4} => 1.23}, cbor!({ {1=>2,3=>4} => 1.23 }).unwrap()), + case(map! {map! {1=>2,3=>4} => -1.23}, cbor!({ {1=>2,3=>4} => -1.23 }).unwrap()), + case(map! {map! {1=>2,3=>4} => 2.5e+1}, cbor!({ {1=>2,3=>4} => 2.5e+1 }).unwrap()), + case(map! {map! {1=>2,3=>4} => 2.5e+1}, cbor!({ {1=>2,3=>4} => 2.5e+1 }).unwrap()), + case(map! {map! {1=>2,3=>4} => [1, 2]}, cbor!({ {1=>2,3=>4} => [1, 2] }).unwrap()), + case(map! {map! {1=>2,3=>4} => map! {1=>2,3=>4}}, cbor!({ {1=>2,3=>4} => {1=>2,3=>4} }).unwrap()), +)] +fn test(answer: Value, question: Value) { + assert_eq!(answer, question); +} diff --git a/vendor/ciborium/tests/no_std.rs b/vendor/ciborium/tests/no_std.rs new file mode 100644 index 000000000..6ea008a46 --- /dev/null +++ b/vendor/ciborium/tests/no_std.rs @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: Apache-2.0 + +#![cfg(all(feature = "serde", not(feature = "std")))] +#![no_std] + +extern crate alloc; + +use alloc::vec::Vec; + +use ciborium::{de::from_reader, ser::into_writer}; + +#[test] +fn decode() { + assert_eq!(from_reader::<u8, &[u8]>(&[7u8][..]).unwrap(), 7); +} + +#[test] +fn eof() { + from_reader::<u8, &[u8]>(&[]).unwrap_err(); +} + +#[test] +fn encode_slice() { + let mut buffer = [0u8; 1]; + into_writer(&3u8, &mut buffer[..]).unwrap(); + assert_eq!(buffer[0], 3); +} + +#[test] +fn encode_vec() { + let mut buffer = Vec::with_capacity(1); + into_writer(&3u8, &mut buffer).unwrap(); + assert_eq!(buffer[0], 3); +} + +#[test] +fn oos() { + into_writer(&3u8, &mut [][..]).unwrap_err(); +} diff --git a/vendor/ciborium/tests/recursion.rs b/vendor/ciborium/tests/recursion.rs new file mode 100644 index 000000000..a340b2def --- /dev/null +++ b/vendor/ciborium/tests/recursion.rs @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! This test validates that we don't get stack overflows. +//! +//! If container types cause recursion, then a long list of prefixes which +//! indicate nested container types could cause the stack to overflow. We +//! test each of these types here to ensure there is no stack overflow. + +use ciborium::{ + de::{from_reader, Error}, + value::Value, +}; + +#[test] +fn array() { + let bytes = [0x9f; 128 * 1024]; + match from_reader::<Value, _>(&bytes[..]).unwrap_err() { + Error::RecursionLimitExceeded => (), + e => panic!("incorrect error: {:?}", e), + } +} + +#[test] +fn map() { + let bytes = [0xbf; 128 * 1024]; + match from_reader::<Value, _>(&bytes[..]).unwrap_err() { + Error::RecursionLimitExceeded => (), + e => panic!("incorrect error: {:?}", e), + } +} + +#[test] +fn bytes() { + let bytes = [0x5f; 128 * 1024]; + match from_reader::<Value, _>(&bytes[..]).unwrap_err() { + Error::Io(..) => (), + e => panic!("incorrect error: {:?}", e), + } +} + +#[test] +fn text() { + let bytes = [0x7f; 128 * 1024]; + match from_reader::<Value, _>(&bytes[..]).unwrap_err() { + Error::Io(..) => (), + e => panic!("incorrect error: {:?}", e), + } +} diff --git a/vendor/ciborium/tests/tag.rs b/vendor/ciborium/tests/tag.rs new file mode 100644 index 000000000..c19ee0090 --- /dev/null +++ b/vendor/ciborium/tests/tag.rs @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: Apache-2.0 + +extern crate alloc; + +use ciborium::{de::from_reader, ser::into_writer, tag::*, value::Value}; +use rstest::rstest; +use serde::{de::DeserializeOwned, Serialize}; + +use core::fmt::Debug; + +#[rstest(item, bytes, value, encode, success, + case(Captured(Some(6), true), "c6f5", Value::Tag(6, Value::Bool(true).into()), true, true), + case(Captured(None, true), "f5", Value::Bool(true), true, true), + + case(Required::<_, 6>(true), "c6f5", Value::Tag(6, Value::Bool(true).into()), true, true), + case(Required::<_, 6>(true), "c7f5", Value::Tag(7, Value::Bool(true).into()), false, false), + case(Required::<_, 6>(true), "f5", Value::Bool(true), false, false), + + case(Accepted::<_, 6>(true), "c6f5", Value::Tag(6, Value::Bool(true).into()), true, true), + case(Accepted::<_, 6>(true), "c7f5", Value::Tag(7, Value::Bool(true).into()), false, false), + case(Accepted::<_, 6>(true), "f5", Value::Bool(true), false, true), +)] +fn test<T: Serialize + DeserializeOwned + Debug + Eq>( + item: T, + bytes: &str, + value: Value, + encode: bool, + success: bool, +) { + let bytes = hex::decode(bytes).unwrap(); + + if encode { + // Encode into bytes + let mut encoded = Vec::new(); + into_writer(&item, &mut encoded).unwrap(); + assert_eq!(bytes, encoded); + + // Encode into value + assert_eq!(value, Value::serialized(&item).unwrap()); + } + + // Decode from bytes + match from_reader(&bytes[..]) { + Ok(x) if success => assert_eq!(item, x), + Ok(..) => panic!("unexpected success"), + Err(e) if success => Err(e).unwrap(), + Err(..) => (), + } + + // Decode from value + match value.deserialized() { + Ok(x) if success => assert_eq!(item, x), + Ok(..) => panic!("unexpected success"), + Err(e) if success => Err(e).unwrap(), + Err(..) => (), + } +} |