summaryrefslogtreecommitdiffstats
path: root/vendor/ciborium-ll
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
commitd1b2d29528b7794b41e66fc2136e395a02f8529b (patch)
treea4a17504b260206dec3cf55b2dca82929a348ac2 /vendor/ciborium-ll
parentReleasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-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-ll')
-rw-r--r--vendor/ciborium-ll/.cargo-checksum.json1
-rw-r--r--vendor/ciborium-ll/Cargo.toml49
-rw-r--r--vendor/ciborium-ll/LICENSE201
-rw-r--r--vendor/ciborium-ll/README.md131
-rw-r--r--vendor/ciborium-ll/src/dec.rs174
-rw-r--r--vendor/ciborium-ll/src/enc.rs127
-rw-r--r--vendor/ciborium-ll/src/hdr.rs163
-rw-r--r--vendor/ciborium-ll/src/lib.rs487
-rw-r--r--vendor/ciborium-ll/src/seg.rs216
9 files changed, 1549 insertions, 0 deletions
diff --git a/vendor/ciborium-ll/.cargo-checksum.json b/vendor/ciborium-ll/.cargo-checksum.json
new file mode 100644
index 000000000..26a540019
--- /dev/null
+++ b/vendor/ciborium-ll/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"278cfaa9b5844046a047f8c9799de6888ab057de74462dec1761ff5d8fc5bb80","LICENSE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","README.md":"b79803cccd55d24fc81e47aa3fac77461caa78c80799b9115e283ac0bc805c3a","src/dec.rs":"48b2b15a181cc76153be58eb14762c854b83f696150946f3b74fe6b20c717912","src/enc.rs":"90388589b9798382c1abcae21d91e9f3d4a35415c3ad534f41312e94a0e43635","src/hdr.rs":"6cdbdf3c9ea430d804c1c64ab70c7a2a6e38e49f9cbd6f157c6542d8c9b2e952","src/lib.rs":"da6178728228ebfc50b13fc32ce707f2cc539f0212a919645ec64a50e21a0977","src/seg.rs":"cb3e552aad59bdbd0023c5a27b9c04bc61609175e03e6400d38767d964152288"},"package":"defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b"} \ No newline at end of file
diff --git a/vendor/ciborium-ll/Cargo.toml b/vendor/ciborium-ll/Cargo.toml
new file mode 100644
index 000000000..29675d1b4
--- /dev/null
+++ b/vendor/ciborium-ll/Cargo.toml
@@ -0,0 +1,49 @@
+# 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-ll"
+version = "0.2.1"
+authors = ["Nathaniel McCallum <npmccallum@profian.com>"]
+description = "Low-level CBOR codec primitives"
+homepage = "https://github.com/enarx/ciborium"
+readme = "README.md"
+keywords = ["cbor"]
+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"
+
+[dependencies.half]
+version = "1.6"
+[dev-dependencies.hex]
+version = "0.4"
+
+[features]
+alloc = []
+std = ["alloc"]
+[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-ll/LICENSE b/vendor/ciborium-ll/LICENSE
new file mode 100644
index 000000000..261eeb9e9
--- /dev/null
+++ b/vendor/ciborium-ll/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-ll/README.md b/vendor/ciborium-ll/README.md
new file mode 100644
index 000000000..2ca6306a7
--- /dev/null
+++ b/vendor/ciborium-ll/README.md
@@ -0,0 +1,131 @@
+[![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-ll
+
+Low level CBOR parsing tools
+
+This crate contains low-level types for encoding and decoding items in
+CBOR. This crate is usable in both `no_std` and `no_alloc` environments.
+To understand how this crate works, first we will look at the structure
+of a CBOR item on the wire.
+
+## Anatomy of a CBOR Item
+
+This is a brief anatomy of a CBOR item on the wire.
+
+```
++------------+-----------+
+| | |
+| Major | Minor |
+| (3bits) | (5bits) |
+| | |
++------------+-----------+
+^ ^
+| |
++-----+ +-----+
+ | |
+ | |
+ +----------------------------+--------------+
+ | | | |
+ | Prefix | Affix | Suffix |
+ | (1 byte) | (0-8 bytes) | (0+ bytes) |
+ | | | |
+ +------------+---------------+--------------+
+
+ | | |
+ +------------+---------------+--------------+
+ | |
+ v v
+
+ Header Body
+```
+
+The `ciborium` crate works by providing the `Decoder` and `Encoder` types
+which provide input and output for a CBOR header (see: `Header`). From
+there, you can either handle the body yourself or use the provided utility
+functions.
+
+For more information on the CBOR format, see
+[RFC 7049](https://tools.ietf.org/html/rfc7049).
+
+## Decoding
+
+In order to decode CBOR, you will create a `Decoder` from a reader. The
+decoder instance will allow you to `Decoder::pull()` `Header` instances
+from the input.
+
+Most CBOR items are fully contained in their headers and therefore have no
+body. These items can be evaluated directly from the `Header` instance.
+
+Bytes and text items have a body but do not contain child items. Since
+both bytes and text values may be segmented, parsing them can be a bit
+tricky. Therefore, we provide helper functions to parse these types. See
+`Decoder::bytes()` and `Decoder::text()` for more details.
+
+Array and map items have a body which contains child items. These can be
+parsed by simply doing `Decoder::pull()` to parse the child items.
+
+### Example
+
+```rust
+use ciborium_ll::{Decoder, Header};
+use ciborium_io::Read as _;
+
+let input = b"\x6dHello, World!";
+let mut decoder = Decoder::from(&input[..]);
+let mut chunks = 0;
+
+match decoder.pull().unwrap() {
+ Header::Text(len) => {
+ let mut segments = decoder.text(len);
+ while let Some(mut segment) = segments.pull().unwrap() {
+ let mut buffer = [0u8; 7];
+ while let Some(chunk) = segment.pull(&mut buffer[..]).unwrap() {
+ match chunk {
+ "Hello, " if chunks == 0 => chunks = 1,
+ "World!" if chunks == 1 => chunks = 2,
+ _ => panic!("received unexpected chunk"),
+ }
+ }
+ }
+ }
+
+ _ => panic!("received unexpected value"),
+}
+
+assert_eq!(chunks, 2);
+```
+
+## Encoding
+
+To encode values to CBOR, create an `Encoder` from a writer. The encoder
+instance provides the `Encoder::push()` method to write a `Header` value
+to the wire. CBOR item bodies can be written directly.
+
+For bytes and text, there are the `Encoder::bytes()` and `Encoder::text()`
+utility functions, respectively, which will properly segment the output
+on the wire for you.
+
+### Example
+
+```rust
+use ciborium_ll::{Encoder, Header};
+use ciborium_io::Write as _;
+
+let mut buffer = [0u8; 19];
+let mut encoder = Encoder::from(&mut buffer[..]);
+
+// Write the structure
+encoder.push(Header::Map(Some(1))).unwrap();
+encoder.push(Header::Positive(7)).unwrap();
+encoder.text("Hello, World!", 7).unwrap();
+
+// Validate our output
+encoder.flush().unwrap();
+assert_eq!(b"\xa1\x07\x7f\x67Hello, \x66World!\xff", &buffer[..]);
+```
+
+License: Apache-2.0
diff --git a/vendor/ciborium-ll/src/dec.rs b/vendor/ciborium-ll/src/dec.rs
new file mode 100644
index 000000000..832963451
--- /dev/null
+++ b/vendor/ciborium-ll/src/dec.rs
@@ -0,0 +1,174 @@
+use super::*;
+
+use ciborium_io::Read;
+
+/// An error that occurred while decoding
+#[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),
+}
+
+impl<T> From<T> for Error<T> {
+ #[inline]
+ fn from(value: T) -> Self {
+ Self::Io(value)
+ }
+}
+
+/// A decoder for deserializing CBOR items
+///
+/// This decoder manages the low-level decoding of CBOR items into `Header`
+/// objects. It also contains utility functions for parsing segmented bytes
+/// and text inputs.
+pub struct Decoder<R: Read> {
+ reader: R,
+ offset: usize,
+ buffer: Option<Title>,
+}
+
+impl<R: Read> From<R> for Decoder<R> {
+ #[inline]
+ fn from(value: R) -> Self {
+ Self {
+ reader: value,
+ offset: 0,
+ buffer: None,
+ }
+ }
+}
+
+impl<R: Read> Read for Decoder<R> {
+ type Error = R::Error;
+
+ #[inline]
+ fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
+ assert!(self.buffer.is_none());
+ self.reader.read_exact(data)?;
+ self.offset += data.len();
+ Ok(())
+ }
+}
+
+impl<R: Read> Decoder<R> {
+ #[inline]
+ fn pull_title(&mut self) -> Result<Title, Error<R::Error>> {
+ if let Some(title) = self.buffer.take() {
+ self.offset += title.1.as_ref().len() + 1;
+ return Ok(title);
+ }
+
+ let mut prefix = [0u8; 1];
+ self.read_exact(&mut prefix[..])?;
+
+ let major = match prefix[0] >> 5 {
+ 0 => Major::Positive,
+ 1 => Major::Negative,
+ 2 => Major::Bytes,
+ 3 => Major::Text,
+ 4 => Major::Array,
+ 5 => Major::Map,
+ 6 => Major::Tag,
+ 7 => Major::Other,
+ _ => unreachable!(),
+ };
+
+ let mut minor = match prefix[0] & 0b00011111 {
+ x if x < 24 => Minor::This(x),
+ 24 => Minor::Next1([0; 1]),
+ 25 => Minor::Next2([0; 2]),
+ 26 => Minor::Next4([0; 4]),
+ 27 => Minor::Next8([0; 8]),
+ 31 => Minor::More,
+ _ => return Err(Error::Syntax(self.offset - 1)),
+ };
+
+ self.read_exact(minor.as_mut())?;
+ Ok(Title(major, minor))
+ }
+
+ #[inline]
+ fn push_title(&mut self, item: Title) {
+ assert!(self.buffer.is_none());
+ self.buffer = Some(item);
+ self.offset -= item.1.as_ref().len() + 1;
+ }
+
+ /// Pulls the next header from the input
+ #[inline]
+ pub fn pull(&mut self) -> Result<Header, Error<R::Error>> {
+ let offset = self.offset;
+ self.pull_title()?
+ .try_into()
+ .map_err(|_| Error::Syntax(offset))
+ }
+
+ /// Push a single header into the input buffer
+ ///
+ /// # Panics
+ ///
+ /// This function panics if called while there is already a header in the
+ /// input buffer. You should take care to call this function only after
+ /// pulling a header to ensure there is nothing in the input buffer.
+ #[inline]
+ pub fn push(&mut self, item: Header) {
+ self.push_title(Title::from(item))
+ }
+
+ /// Gets the current byte offset into the stream
+ ///
+ /// The offset starts at zero when the decoder is created. Therefore, if
+ /// bytes were already read from the reader before the decoder was created,
+ /// you must account for this.
+ #[inline]
+ pub fn offset(&mut self) -> usize {
+ self.offset
+ }
+
+ /// Process an incoming bytes item
+ ///
+ /// In CBOR, bytes can be segmented. The logic for this can be a bit tricky,
+ /// so we encapsulate that logic using this function. This function **MUST**
+ /// be called immediately after first pulling a `Header::Bytes(len)` from
+ /// the wire and `len` must be provided to this function from that value.
+ ///
+ /// The `buf` parameter provides a buffer used when reading in the segmented
+ /// bytes. A large buffer will result in fewer calls to read incoming bytes
+ /// at the cost of memory usage. You should consider this trade off when
+ /// deciding the size of your buffer.
+ #[inline]
+ pub fn bytes(&mut self, len: Option<usize>) -> Segments<R, crate::seg::Bytes> {
+ self.push(Header::Bytes(len));
+ Segments::new(self, |header| match header {
+ Header::Bytes(len) => Ok(len),
+ _ => Err(()),
+ })
+ }
+
+ /// Process an incoming text item
+ ///
+ /// In CBOR, text can be segmented. The logic for this can be a bit tricky,
+ /// so we encapsulate that logic using this function. This function **MUST**
+ /// be called immediately after first pulling a `Header::Text(len)` from
+ /// the wire and `len` must be provided to this function from that value.
+ ///
+ /// The `buf` parameter provides a buffer used when reading in the segmented
+ /// text. A large buffer will result in fewer calls to read incoming bytes
+ /// at the cost of memory usage. You should consider this trade off when
+ /// deciding the size of your buffer.
+ #[inline]
+ pub fn text(&mut self, len: Option<usize>) -> Segments<R, crate::seg::Text> {
+ self.push(Header::Text(len));
+ Segments::new(self, |header| match header {
+ Header::Text(len) => Ok(len),
+ _ => Err(()),
+ })
+ }
+}
diff --git a/vendor/ciborium-ll/src/enc.rs b/vendor/ciborium-ll/src/enc.rs
new file mode 100644
index 000000000..b8b8a20d6
--- /dev/null
+++ b/vendor/ciborium-ll/src/enc.rs
@@ -0,0 +1,127 @@
+use super::*;
+
+use ciborium_io::Write;
+
+/// An encoder for serializing CBOR items
+///
+/// This structure wraps a writer and provides convenience functions for
+/// writing `Header` objects to the wire.
+pub struct Encoder<W: Write>(W);
+
+impl<W: Write> From<W> for Encoder<W> {
+ #[inline]
+ fn from(value: W) -> Self {
+ Self(value)
+ }
+}
+
+impl<W: Write> Write for Encoder<W> {
+ type Error = W::Error;
+
+ fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> {
+ self.0.write_all(data)
+ }
+
+ fn flush(&mut self) -> Result<(), Self::Error> {
+ self.0.flush()
+ }
+}
+
+impl<W: Write> Encoder<W> {
+ /// Push a `Header` to the wire
+ #[inline]
+ pub fn push(&mut self, header: Header) -> Result<(), W::Error> {
+ let title = Title::from(header);
+
+ let major = match title.0 {
+ Major::Positive => 0,
+ Major::Negative => 1,
+ Major::Bytes => 2,
+ Major::Text => 3,
+ Major::Array => 4,
+ Major::Map => 5,
+ Major::Tag => 6,
+ Major::Other => 7,
+ };
+
+ let minor = match title.1 {
+ Minor::This(x) => x,
+ Minor::Next1(..) => 24,
+ Minor::Next2(..) => 25,
+ Minor::Next4(..) => 26,
+ Minor::Next8(..) => 27,
+ Minor::More => 31,
+ };
+
+ self.0.write_all(&[major << 5 | minor])?;
+ self.0.write_all(title.1.as_ref())
+ }
+
+ /// Serialize a byte slice as CBOR
+ ///
+ /// Optionally, segment the output into `segment` size segments. Note that
+ /// if `segment == Some(0)` it will be silently upgraded to `Some(1)`. This
+ /// minimum value is highly inefficient and should not be relied upon.
+ #[inline]
+ pub fn bytes(
+ &mut self,
+ value: &[u8],
+ segment: impl Into<Option<usize>>,
+ ) -> Result<(), W::Error> {
+ let max = segment.into().unwrap_or(value.len());
+ let max = core::cmp::max(max, 1);
+
+ if max >= value.len() {
+ self.push(Header::Bytes(Some(value.len())))?;
+ self.write_all(value)?;
+ } else {
+ self.push(Header::Bytes(None))?;
+
+ for chunk in value.chunks(max) {
+ self.push(Header::Bytes(Some(chunk.len())))?;
+ self.write_all(chunk)?;
+ }
+
+ self.push(Header::Break)?;
+ }
+
+ Ok(())
+ }
+
+ /// Serialize a string slice as CBOR
+ ///
+ /// Optionally, segment the output into `segment` size segments. Note that
+ /// since care is taken to ensure that each segment is itself a valid UTF-8
+ /// string, if `segment` contains a value of less than 4, it will be
+ /// silently upgraded to 4. This minimum value is highly inefficient and
+ /// should not be relied upon.
+ #[inline]
+ pub fn text(&mut self, value: &str, segment: impl Into<Option<usize>>) -> Result<(), W::Error> {
+ let max = segment.into().unwrap_or(value.len());
+ let max = core::cmp::max(max, 4);
+
+ if max >= value.len() {
+ self.push(Header::Text(Some(value.len())))?;
+ self.write_all(value.as_bytes())?;
+ } else {
+ self.push(Header::Text(None))?;
+
+ let mut bytes = value.as_bytes();
+ while !bytes.is_empty() {
+ let mut len = core::cmp::min(bytes.len(), max);
+ while len > 0 && core::str::from_utf8(&bytes[..len]).is_err() {
+ len -= 1
+ }
+
+ let (prefix, suffix) = bytes.split_at(len);
+ self.push(Header::Text(Some(prefix.len())))?;
+ self.write_all(prefix)?;
+ bytes = suffix;
+ }
+
+ self.push(Header::Break)?;
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/ciborium-ll/src/hdr.rs b/vendor/ciborium-ll/src/hdr.rs
new file mode 100644
index 000000000..dec178815
--- /dev/null
+++ b/vendor/ciborium-ll/src/hdr.rs
@@ -0,0 +1,163 @@
+use super::*;
+
+use half::f16;
+
+/// A semantic representation of a CBOR item header
+///
+/// This structure represents the valid values of a CBOR item header and is
+/// used extensively when serializing or deserializing CBOR items. Note well
+/// that this structure **DOES NOT** represent the body (i.e. suffix) of the
+/// CBOR item. You must parse the body yourself based on the contents of the
+/// `Header`. However, utility functions are provided for this (see:
+/// `Decoder::bytes()` and `Decoder::text()`).
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub enum Header {
+ /// A positive integer
+ Positive(u64),
+
+ /// A negative integer
+ ///
+ /// Note well that this value has all bits inverted from a normal signed
+ /// integer. For example, to convert the `u64` to a `i128` you would do
+ /// this: `neg as i128 ^ !0`.
+ Negative(u64),
+
+ /// A floating point value
+ Float(f64),
+
+ /// A "simple" value
+ Simple(u8),
+
+ /// A tag
+ Tag(u64),
+
+ /// The "break" value
+ ///
+ /// This value is used to terminate indefinite length arrays and maps,
+ /// as well as segmented byte or text items.
+ Break,
+
+ /// A bytes item
+ ///
+ /// The value contained in this variant indicates the length of the bytes
+ /// which follow or, if `None`, segmented bytes input.
+ ///
+ /// A best practice is to call `Decoder::bytes()` immediately after
+ /// first pulling a bytes item header since this utility function
+ /// encapsulates all the logic needed to handle segmentation.
+ Bytes(Option<usize>),
+
+ /// A text item
+ ///
+ /// The value contained in this variant indicates the length of the text
+ /// which follows (in bytes) or, if `None`, segmented text input.
+ ///
+ /// A best practice is to call `Decoder::text()` immediately after
+ /// first pulling a text item header since this utility function
+ /// encapsulates all the logic needed to handle segmentation.
+ Text(Option<usize>),
+
+ /// An array item
+ ///
+ /// The value contained in this variant indicates the length of the array
+ /// which follows (in items) or, if `None`, an indefinite length array
+ /// terminated by a "break" value.
+ Array(Option<usize>),
+
+ /// An map item
+ ///
+ /// The value contained in this variant indicates the length of the map
+ /// which follows (in item pairs) or, if `None`, an indefinite length map
+ /// terminated by a "break" value.
+ Map(Option<usize>),
+}
+
+impl TryFrom<Title> for Header {
+ type Error = InvalidError;
+
+ fn try_from(title: Title) -> Result<Self, Self::Error> {
+ let opt = |minor| {
+ Some(match minor {
+ Minor::This(x) => x.into(),
+ Minor::Next1(x) => u8::from_be_bytes(x).into(),
+ Minor::Next2(x) => u16::from_be_bytes(x).into(),
+ Minor::Next4(x) => u32::from_be_bytes(x).into(),
+ Minor::Next8(x) => u64::from_be_bytes(x),
+ Minor::More => return None,
+ })
+ };
+
+ let int = |m| opt(m).ok_or(InvalidError(()));
+
+ let len = |m| {
+ opt(m)
+ .map(usize::try_from)
+ .transpose()
+ .or(Err(InvalidError(())))
+ };
+
+ Ok(match title {
+ Title(Major::Positive, minor) => Self::Positive(int(minor)?),
+ Title(Major::Negative, minor) => Self::Negative(int(minor)?),
+ Title(Major::Bytes, minor) => Self::Bytes(len(minor)?),
+ Title(Major::Text, minor) => Self::Text(len(minor)?),
+ Title(Major::Array, minor) => Self::Array(len(minor)?),
+ Title(Major::Map, minor) => Self::Map(len(minor)?),
+ Title(Major::Tag, minor) => Self::Tag(int(minor)?),
+
+ Title(Major::Other, Minor::More) => Self::Break,
+ Title(Major::Other, Minor::This(x)) => Self::Simple(x),
+ Title(Major::Other, Minor::Next1(x)) => Self::Simple(x[0]),
+ Title(Major::Other, Minor::Next2(x)) => Self::Float(f16::from_be_bytes(x).into()),
+ Title(Major::Other, Minor::Next4(x)) => Self::Float(f32::from_be_bytes(x).into()),
+ Title(Major::Other, Minor::Next8(x)) => Self::Float(f64::from_be_bytes(x)),
+ })
+ }
+}
+
+impl From<Header> for Title {
+ fn from(header: Header) -> Self {
+ let int = |i: u64| match i {
+ x if x <= 23 => Minor::This(i as u8),
+ x if x <= core::u8::MAX as u64 => Minor::Next1([i as u8]),
+ x if x <= core::u16::MAX as u64 => Minor::Next2((i as u16).to_be_bytes()),
+ x if x <= core::u32::MAX as u64 => Minor::Next4((i as u32).to_be_bytes()),
+ x => Minor::Next8(x.to_be_bytes()),
+ };
+
+ let len = |l: Option<usize>| l.map(|x| int(x as u64)).unwrap_or(Minor::More);
+
+ match header {
+ Header::Positive(x) => Title(Major::Positive, int(x)),
+ Header::Negative(x) => Title(Major::Negative, int(x)),
+ Header::Bytes(x) => Title(Major::Bytes, len(x)),
+ Header::Text(x) => Title(Major::Text, len(x)),
+ Header::Array(x) => Title(Major::Array, len(x)),
+ Header::Map(x) => Title(Major::Map, len(x)),
+ Header::Tag(x) => Title(Major::Tag, int(x)),
+
+ Header::Break => Title(Major::Other, Minor::More),
+
+ Header::Simple(x) => match x {
+ x @ 0..=23 => Title(Major::Other, Minor::This(x)),
+ x => Title(Major::Other, Minor::Next1([x])),
+ },
+
+ Header::Float(n64) => {
+ let n16 = f16::from_f64(n64);
+ let n32 = n64 as f32;
+
+ Title(
+ Major::Other,
+ if f64::from(n16).to_bits() == n64.to_bits() {
+ Minor::Next2(n16.to_be_bytes())
+ } else if f64::from(n32).to_bits() == n64.to_bits() {
+ Minor::Next4(n32.to_be_bytes())
+ } else {
+ Minor::Next8(n64.to_be_bytes())
+ },
+ )
+ }
+ }
+ }
+}
diff --git a/vendor/ciborium-ll/src/lib.rs b/vendor/ciborium-ll/src/lib.rs
new file mode 100644
index 000000000..8a1fe90ca
--- /dev/null
+++ b/vendor/ciborium-ll/src/lib.rs
@@ -0,0 +1,487 @@
+// SPDX-License-Identifier: Apache-2.0
+
+//! Low level CBOR parsing tools
+//!
+//! This crate contains low-level types for encoding and decoding items in
+//! CBOR. This crate is usable in both `no_std` and `no_alloc` environments.
+//! To understand how this crate works, first we will look at the structure
+//! of a CBOR item on the wire.
+//!
+//! # Anatomy of a CBOR Item
+//!
+//! This is a brief anatomy of a CBOR item on the wire.
+//!
+//! ```text
+//! +------------+-----------+
+//! | | |
+//! | Major | Minor |
+//! | (3bits) | (5bits) |
+//! | | |
+//! +------------+-----------+
+//! ^ ^
+//! | |
+//! +-----+ +-----+
+//! | |
+//! | |
+//! +----------------------------+--------------+
+//! | | | |
+//! | Prefix | Affix | Suffix |
+//! | (1 byte) | (0-8 bytes) | (0+ bytes) |
+//! | | | |
+//! +------------+---------------+--------------+
+//!
+//! | | |
+//! +------------+---------------+--------------+
+//! | |
+//! v v
+//!
+//! Header Body
+//! ```
+//!
+//! The `ciborium` crate works by providing the `Decoder` and `Encoder` types
+//! which provide input and output for a CBOR header (see: `Header`). From
+//! there, you can either handle the body yourself or use the provided utility
+//! functions.
+//!
+//! For more information on the CBOR format, see
+//! [RFC 7049](https://tools.ietf.org/html/rfc7049).
+//!
+//! # Decoding
+//!
+//! In order to decode CBOR, you will create a `Decoder` from a reader. The
+//! decoder instance will allow you to `Decoder::pull()` `Header` instances
+//! from the input.
+//!
+//! Most CBOR items are fully contained in their headers and therefore have no
+//! body. These items can be evaluated directly from the `Header` instance.
+//!
+//! Bytes and text items have a body but do not contain child items. Since
+//! both bytes and text values may be segmented, parsing them can be a bit
+//! tricky. Therefore, we provide helper functions to parse these types. See
+//! `Decoder::bytes()` and `Decoder::text()` for more details.
+//!
+//! Array and map items have a body which contains child items. These can be
+//! parsed by simply doing `Decoder::pull()` to parse the child items.
+//!
+//! ## Example
+//!
+//! ```rust
+//! use ciborium_ll::{Decoder, Header};
+//! use ciborium_io::Read as _;
+//!
+//! let input = b"\x6dHello, World!";
+//! let mut decoder = Decoder::from(&input[..]);
+//! let mut chunks = 0;
+//!
+//! match decoder.pull().unwrap() {
+//! Header::Text(len) => {
+//! let mut segments = decoder.text(len);
+//! while let Some(mut segment) = segments.pull().unwrap() {
+//! let mut buffer = [0u8; 7];
+//! while let Some(chunk) = segment.pull(&mut buffer[..]).unwrap() {
+//! match chunk {
+//! "Hello, " if chunks == 0 => chunks = 1,
+//! "World!" if chunks == 1 => chunks = 2,
+//! _ => panic!("received unexpected chunk"),
+//! }
+//! }
+//! }
+//! }
+//!
+//! _ => panic!("received unexpected value"),
+//! }
+//!
+//! assert_eq!(chunks, 2);
+//! ```
+//!
+//! # Encoding
+//!
+//! To encode values to CBOR, create an `Encoder` from a writer. The encoder
+//! instance provides the `Encoder::push()` method to write a `Header` value
+//! to the wire. CBOR item bodies can be written directly.
+//!
+//! For bytes and text, there are the `Encoder::bytes()` and `Encoder::text()`
+//! utility functions, respectively, which will properly segment the output
+//! on the wire for you.
+//!
+//! ## Example
+//!
+//! ```rust
+//! use ciborium_ll::{Encoder, Header};
+//! use ciborium_io::Write as _;
+//!
+//! let mut buffer = [0u8; 19];
+//! let mut encoder = Encoder::from(&mut buffer[..]);
+//!
+//! // Write the structure
+//! encoder.push(Header::Map(Some(1))).unwrap();
+//! encoder.push(Header::Positive(7)).unwrap();
+//! encoder.text("Hello, World!", 7).unwrap();
+//!
+//! // Validate our output
+//! encoder.flush().unwrap();
+//! assert_eq!(b"\xa1\x07\x7f\x67Hello, \x66World!\xff", &buffer[..]);
+//! ```
+
+#![cfg_attr(not(feature = "std"), no_std)]
+#![deny(missing_docs)]
+#![deny(clippy::all)]
+#![deny(clippy::cargo)]
+
+#[cfg(feature = "alloc")]
+extern crate alloc;
+
+mod dec;
+mod enc;
+mod hdr;
+mod seg;
+
+pub use dec::*;
+pub use enc::*;
+pub use hdr::*;
+pub use seg::{Segment, Segments};
+
+/// Simple value constants
+pub mod simple {
+ #![allow(missing_docs)]
+
+ pub const FALSE: u8 = 20;
+ pub const TRUE: u8 = 21;
+ pub const NULL: u8 = 22;
+ pub const UNDEFINED: u8 = 23;
+}
+
+/// Tag constants
+pub mod tag {
+ #![allow(missing_docs)]
+
+ pub const BIGPOS: u64 = 2;
+ pub const BIGNEG: u64 = 3;
+}
+
+#[derive(Debug)]
+struct InvalidError(());
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+enum Major {
+ Positive,
+ Negative,
+ Bytes,
+ Text,
+ Array,
+ Map,
+ Tag,
+ Other,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+enum Minor {
+ This(u8),
+ Next1([u8; 1]),
+ Next2([u8; 2]),
+ Next4([u8; 4]),
+ Next8([u8; 8]),
+ More,
+}
+
+impl AsRef<[u8]> for Minor {
+ #[inline]
+ fn as_ref(&self) -> &[u8] {
+ match self {
+ Self::More => &[],
+ Self::This(..) => &[],
+ Self::Next1(x) => x.as_ref(),
+ Self::Next2(x) => x.as_ref(),
+ Self::Next4(x) => x.as_ref(),
+ Self::Next8(x) => x.as_ref(),
+ }
+ }
+}
+
+impl AsMut<[u8]> for Minor {
+ #[inline]
+ fn as_mut(&mut self) -> &mut [u8] {
+ match self {
+ Self::More => &mut [],
+ Self::This(..) => &mut [],
+ Self::Next1(x) => x.as_mut(),
+ Self::Next2(x) => x.as_mut(),
+ Self::Next4(x) => x.as_mut(),
+ Self::Next8(x) => x.as_mut(),
+ }
+ }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+struct Title(pub Major, pub Minor);
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ macro_rules! neg {
+ ($i:expr) => {
+ Header::Negative((($i as i128) ^ !0) as u64)
+ };
+ }
+
+ #[allow(clippy::excessive_precision)]
+ #[test]
+ fn leaf() {
+ use core::f64::{INFINITY, NAN};
+
+ let data = &[
+ (Header::Positive(0), "00", true),
+ (Header::Positive(1), "01", true),
+ (Header::Positive(10), "0a", true),
+ (Header::Positive(23), "17", true),
+ (Header::Positive(24), "1818", true),
+ (Header::Positive(25), "1819", true),
+ (Header::Positive(100), "1864", true),
+ (Header::Positive(1000), "1903e8", true),
+ (Header::Positive(1000000), "1a000f4240", true),
+ (Header::Positive(1000000000000), "1b000000e8d4a51000", true),
+ (
+ Header::Positive(18446744073709551615),
+ "1bffffffffffffffff",
+ true,
+ ),
+ (neg!(-18446744073709551616), "3bffffffffffffffff", true),
+ (neg!(-1), "20", true),
+ (neg!(-10), "29", true),
+ (neg!(-100), "3863", true),
+ (neg!(-1000), "3903e7", true),
+ (Header::Float(0.0), "f90000", true),
+ (Header::Float(-0.0), "f98000", true),
+ (Header::Float(1.0), "f93c00", true),
+ (Header::Float(1.1), "fb3ff199999999999a", true),
+ (Header::Float(1.5), "f93e00", true),
+ (Header::Float(65504.0), "f97bff", true),
+ (Header::Float(100000.0), "fa47c35000", true),
+ (Header::Float(3.4028234663852886e+38), "fa7f7fffff", true),
+ (Header::Float(1.0e+300), "fb7e37e43c8800759c", true),
+ (Header::Float(5.960464477539063e-8), "f90001", true),
+ (Header::Float(0.00006103515625), "f90400", true),
+ (Header::Float(-4.0), "f9c400", true),
+ (Header::Float(-4.1), "fbc010666666666666", true),
+ (Header::Float(INFINITY), "f97c00", true),
+ (Header::Float(NAN), "f97e00", true),
+ (Header::Float(-INFINITY), "f9fc00", true),
+ (Header::Float(INFINITY), "fa7f800000", false),
+ (Header::Float(NAN), "fa7fc00000", false),
+ (Header::Float(-INFINITY), "faff800000", false),
+ (Header::Float(INFINITY), "fb7ff0000000000000", false),
+ (Header::Float(NAN), "fb7ff8000000000000", false),
+ (Header::Float(-INFINITY), "fbfff0000000000000", false),
+ (Header::Simple(simple::FALSE), "f4", true),
+ (Header::Simple(simple::TRUE), "f5", true),
+ (Header::Simple(simple::NULL), "f6", true),
+ (Header::Simple(simple::UNDEFINED), "f7", true),
+ (Header::Simple(16), "f0", true),
+ (Header::Simple(24), "f818", true),
+ (Header::Simple(255), "f8ff", true),
+ (Header::Tag(0), "c0", true),
+ (Header::Tag(1), "c1", true),
+ (Header::Tag(23), "d7", true),
+ (Header::Tag(24), "d818", true),
+ (Header::Tag(32), "d820", true),
+ (Header::Bytes(Some(0)), "40", true),
+ (Header::Bytes(Some(4)), "44", true),
+ (Header::Text(Some(0)), "60", true),
+ (Header::Text(Some(4)), "64", true),
+ ];
+
+ for (header, bytes, encode) in data.iter().cloned() {
+ let bytes = hex::decode(bytes).unwrap();
+
+ let mut decoder = Decoder::from(&bytes[..]);
+ match (header, decoder.pull().unwrap()) {
+ // NaN equality...
+ (Header::Float(l), Header::Float(r)) if l.is_nan() && r.is_nan() => (),
+
+ // Everything else...
+ (l, r) => assert_eq!(l, r),
+ }
+
+ if encode {
+ let mut buffer = [0u8; 1024];
+ let mut writer = &mut buffer[..];
+ let mut encoder = Encoder::from(&mut writer);
+ encoder.push(header).unwrap();
+
+ let len = writer.len();
+ assert_eq!(&bytes[..], &buffer[..1024 - len]);
+ }
+ }
+ }
+
+ #[test]
+ fn node() {
+ let data: &[(&str, &[Header])] = &[
+ ("80", &[Header::Array(Some(0))]),
+ (
+ "83010203",
+ &[
+ Header::Array(Some(3)),
+ Header::Positive(1),
+ Header::Positive(2),
+ Header::Positive(3),
+ ],
+ ),
+ (
+ "98190102030405060708090a0b0c0d0e0f101112131415161718181819",
+ &[
+ Header::Array(Some(25)),
+ Header::Positive(1),
+ Header::Positive(2),
+ Header::Positive(3),
+ Header::Positive(4),
+ Header::Positive(5),
+ Header::Positive(6),
+ Header::Positive(7),
+ Header::Positive(8),
+ Header::Positive(9),
+ Header::Positive(10),
+ Header::Positive(11),
+ Header::Positive(12),
+ Header::Positive(13),
+ Header::Positive(14),
+ Header::Positive(15),
+ Header::Positive(16),
+ Header::Positive(17),
+ Header::Positive(18),
+ Header::Positive(19),
+ Header::Positive(20),
+ Header::Positive(21),
+ Header::Positive(22),
+ Header::Positive(23),
+ Header::Positive(24),
+ Header::Positive(25),
+ ],
+ ),
+ ("a0", &[Header::Map(Some(0))]),
+ (
+ "a201020304",
+ &[
+ Header::Map(Some(2)),
+ Header::Positive(1),
+ Header::Positive(2),
+ Header::Positive(3),
+ Header::Positive(4),
+ ],
+ ),
+ ("9fff", &[Header::Array(None), Header::Break]),
+ (
+ "9f018202039f0405ffff",
+ &[
+ Header::Array(None),
+ Header::Positive(1),
+ Header::Array(Some(2)),
+ Header::Positive(2),
+ Header::Positive(3),
+ Header::Array(None),
+ Header::Positive(4),
+ Header::Positive(5),
+ Header::Break,
+ Header::Break,
+ ],
+ ),
+ (
+ "9f01820203820405ff",
+ &[
+ Header::Array(None),
+ Header::Positive(1),
+ Header::Array(Some(2)),
+ Header::Positive(2),
+ Header::Positive(3),
+ Header::Array(Some(2)),
+ Header::Positive(4),
+ Header::Positive(5),
+ Header::Break,
+ ],
+ ),
+ (
+ "83018202039f0405ff",
+ &[
+ Header::Array(Some(3)),
+ Header::Positive(1),
+ Header::Array(Some(2)),
+ Header::Positive(2),
+ Header::Positive(3),
+ Header::Array(None),
+ Header::Positive(4),
+ Header::Positive(5),
+ Header::Break,
+ ],
+ ),
+ (
+ "83019f0203ff820405",
+ &[
+ Header::Array(Some(3)),
+ Header::Positive(1),
+ Header::Array(None),
+ Header::Positive(2),
+ Header::Positive(3),
+ Header::Break,
+ Header::Array(Some(2)),
+ Header::Positive(4),
+ Header::Positive(5),
+ ],
+ ),
+ (
+ "9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff",
+ &[
+ Header::Array(None),
+ Header::Positive(1),
+ Header::Positive(2),
+ Header::Positive(3),
+ Header::Positive(4),
+ Header::Positive(5),
+ Header::Positive(6),
+ Header::Positive(7),
+ Header::Positive(8),
+ Header::Positive(9),
+ Header::Positive(10),
+ Header::Positive(11),
+ Header::Positive(12),
+ Header::Positive(13),
+ Header::Positive(14),
+ Header::Positive(15),
+ Header::Positive(16),
+ Header::Positive(17),
+ Header::Positive(18),
+ Header::Positive(19),
+ Header::Positive(20),
+ Header::Positive(21),
+ Header::Positive(22),
+ Header::Positive(23),
+ Header::Positive(24),
+ Header::Positive(25),
+ Header::Break,
+ ],
+ ),
+ ];
+
+ for (bytes, headers) in data {
+ let bytes = hex::decode(bytes).unwrap();
+
+ // Test decoding
+ let mut decoder = Decoder::from(&bytes[..]);
+ for header in headers.iter().cloned() {
+ assert_eq!(header, decoder.pull().unwrap());
+ }
+
+ // Test encoding
+ let mut buffer = [0u8; 1024];
+ let mut writer = &mut buffer[..];
+ let mut encoder = Encoder::from(&mut writer);
+
+ for header in headers.iter().cloned() {
+ encoder.push(header).unwrap();
+ }
+
+ let len = writer.len();
+ assert_eq!(&bytes[..], &buffer[..1024 - len]);
+ }
+ }
+}
diff --git a/vendor/ciborium-ll/src/seg.rs b/vendor/ciborium-ll/src/seg.rs
new file mode 100644
index 000000000..95eaac9b0
--- /dev/null
+++ b/vendor/ciborium-ll/src/seg.rs
@@ -0,0 +1,216 @@
+use super::*;
+
+use ciborium_io::Read;
+
+use core::marker::PhantomData;
+
+/// A parser for incoming segments
+pub trait Parser: Default {
+ /// The type of item that is parsed
+ type Item: ?Sized;
+
+ /// The parsing error that may occur
+ type Error;
+
+ /// The main parsing function
+ ///
+ /// This function processes the incoming bytes and returns the item.
+ ///
+ /// One important detail that **MUST NOT** be overlooked is that the
+ /// parser may save data from a previous parsing attempt. The number of
+ /// bytes saved is indicated by the `Parser::saved()` function. The saved
+ /// bytes will be copied into the beginning of the `bytes` array before
+ /// processing. Therefore, two requirements should be met.
+ ///
+ /// First, the incoming byte slice should be larger than the saved bytes.
+ ///
+ /// Second, the incoming byte slice should contain new bytes only after
+ /// the saved byte prefix.
+ ///
+ /// If both criteria are met, this allows the parser to prepend its saved
+ /// bytes without any additional allocation.
+ fn parse<'a>(&mut self, bytes: &'a mut [u8]) -> Result<&'a Self::Item, Self::Error>;
+
+ /// Indicates the number of saved bytes in the parser
+ fn saved(&self) -> usize {
+ 0
+ }
+}
+
+/// A bytes parser
+///
+/// No actual processing is performed and the input bytes are directly
+/// returned. This implies that this parser never saves any bytes internally.
+#[derive(Default)]
+pub struct Bytes(());
+
+impl Parser for Bytes {
+ type Item = [u8];
+ type Error = core::convert::Infallible;
+
+ fn parse<'a>(&mut self, bytes: &'a mut [u8]) -> Result<&'a [u8], Self::Error> {
+ Ok(bytes)
+ }
+}
+
+/// A text parser
+///
+/// This parser converts the input bytes to a `str`. This parser preserves
+/// trailing invalid UTF-8 sequences in the case that chunking fell in the
+/// middle of a valid UTF-8 character.
+#[derive(Default)]
+pub struct Text {
+ stored: usize,
+ buffer: [u8; 3],
+}
+
+impl Parser for Text {
+ type Item = str;
+ type Error = core::str::Utf8Error;
+
+ fn parse<'a>(&mut self, bytes: &'a mut [u8]) -> Result<&'a str, Self::Error> {
+ // If we cannot advance, return nothing.
+ if bytes.len() <= self.stored {
+ return Ok("");
+ }
+
+ // Copy previously invalid data into place.
+ bytes[..self.stored].clone_from_slice(&self.buffer[..self.stored]);
+
+ Ok(match core::str::from_utf8(bytes) {
+ Ok(s) => {
+ self.stored = 0;
+ s
+ }
+ Err(e) => {
+ let valid_len = e.valid_up_to();
+ let invalid_len = bytes.len() - valid_len;
+
+ // If the size of the invalid UTF-8 is large enough to hold
+ // all valid UTF-8 characters, we have a syntax error.
+ if invalid_len > self.buffer.len() {
+ return Err(e);
+ }
+
+ // Otherwise, store the invalid bytes for the next read cycle.
+ self.buffer[..invalid_len].clone_from_slice(&bytes[valid_len..]);
+ self.stored = invalid_len;
+
+ // Decode the valid part of the string.
+ core::str::from_utf8(&bytes[..valid_len]).unwrap()
+ }
+ })
+ }
+
+ fn saved(&self) -> usize {
+ self.stored
+ }
+}
+
+/// A CBOR segment
+///
+/// This type represents a single bytes or text segment on the wire. It can be
+/// read out in parsed chunks based on the size of the input scratch buffer.
+pub struct Segment<'r, R: Read, P: Parser> {
+ reader: &'r mut Decoder<R>,
+ unread: usize,
+ offset: usize,
+ parser: P,
+}
+
+impl<'r, R: Read, P: Parser> Segment<'r, R, P> {
+ /// Gets the number of unprocessed bytes
+ #[inline]
+ pub fn left(&self) -> usize {
+ self.unread + self.parser.saved()
+ }
+
+ /// Gets the next parsed chunk within the segment
+ ///
+ /// Returns `Ok(None)` when all chunks have been read.
+ #[inline]
+ pub fn pull<'a>(
+ &mut self,
+ buffer: &'a mut [u8],
+ ) -> Result<Option<&'a P::Item>, Error<R::Error>> {
+ use core::cmp::min;
+
+ let prev = self.parser.saved();
+ match self.unread {
+ 0 if prev == 0 => return Ok(None),
+ 0 => return Err(Error::Syntax(self.offset)),
+ _ => (),
+ }
+
+ // Determine how many bytes to read.
+ let size = min(buffer.len(), prev + self.unread);
+ let full = &mut buffer[..size];
+ let next = &mut full[min(size, prev)..];
+
+ // Read additional bytes.
+ self.reader.read_exact(next)?;
+ self.unread -= next.len();
+
+ self.parser
+ .parse(full)
+ .or(Err(Error::Syntax(self.offset)))
+ .map(Some)
+ }
+}
+
+/// A sequence of CBOR segments
+///
+/// CBOR allows for bytes or text items to be segmented. This type represents
+/// the state of that segmented input stream.
+pub struct Segments<'r, R: Read, P: Parser> {
+ reader: &'r mut Decoder<R>,
+ finish: bool,
+ nested: usize,
+ parser: PhantomData<P>,
+ unwrap: fn(Header) -> Result<Option<usize>, ()>,
+}
+
+impl<'r, R: Read, P: Parser> Segments<'r, R, P> {
+ #[inline]
+ pub(crate) fn new(
+ decoder: &'r mut Decoder<R>,
+ unwrap: fn(Header) -> Result<Option<usize>, ()>,
+ ) -> Self {
+ Self {
+ reader: decoder,
+ finish: false,
+ nested: 0,
+ parser: PhantomData,
+ unwrap,
+ }
+ }
+
+ /// Gets the next segment in the stream
+ ///
+ /// Returns `Ok(None)` at the conclusion of the stream.
+ #[inline]
+ pub fn pull(&mut self) -> Result<Option<Segment<R, P>>, Error<R::Error>> {
+ while !self.finish {
+ let offset = self.reader.offset();
+ match self.reader.pull()? {
+ Header::Break if self.nested == 1 => return Ok(None),
+ Header::Break if self.nested > 1 => self.nested -= 1,
+ header => match (self.unwrap)(header) {
+ Err(..) => return Err(Error::Syntax(offset)),
+ Ok(None) => self.nested += 1,
+ Ok(Some(len)) => {
+ self.finish = self.nested == 0;
+ return Ok(Some(Segment {
+ reader: self.reader,
+ unread: len,
+ offset,
+ parser: P::default(),
+ }));
+ }
+ },
+ }
+ }
+
+ Ok(None)
+ }
+}