summaryrefslogtreecommitdiffstats
path: root/third_party/rust/moz_cbor
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/moz_cbor
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/moz_cbor')
-rw-r--r--third_party/rust/moz_cbor/.cargo-checksum.json1
-rw-r--r--third_party/rust/moz_cbor/Cargo.toml23
-rw-r--r--third_party/rust/moz_cbor/LICENSE373
-rw-r--r--third_party/rust/moz_cbor/README.md8
-rw-r--r--third_party/rust/moz_cbor/rustfmt.toml0
-rw-r--r--third_party/rust/moz_cbor/src/decoder.rs165
-rw-r--r--third_party/rust/moz_cbor/src/lib.rs51
-rw-r--r--third_party/rust/moz_cbor/src/serializer.rs124
-rw-r--r--third_party/rust/moz_cbor/src/test_decoder.rs445
-rw-r--r--third_party/rust/moz_cbor/src/test_serializer.rs324
10 files changed, 1514 insertions, 0 deletions
diff --git a/third_party/rust/moz_cbor/.cargo-checksum.json b/third_party/rust/moz_cbor/.cargo-checksum.json
new file mode 100644
index 0000000000..e3c215583d
--- /dev/null
+++ b/third_party/rust/moz_cbor/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"137eb0326df095bf3fa030839b880f2cf4f370a44511effc4c2a4760798bc695","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"900075da16923e46236926014f2ce8a0a404dfcedceee43d9ad50e6202ab1184","rustfmt.toml":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/decoder.rs":"979a2165a0452368a0eba1da9066ed4cca491567b087dc051f4e65d15a6f13fa","src/lib.rs":"e8b91d719c9ab39562cc101c1fddd1953f7a119ce73320432a4b2647c92b2886","src/serializer.rs":"5e0466556ddc5e222339f244967f10549eb215b5d82ceb655e1838918212bde7","src/test_decoder.rs":"882b804096647cf3864ba067ef3d6eaca60e7945924ca4f122a3bd67a89f298d","src/test_serializer.rs":"b1c198ebc423849504333439c00a5c30dd40a5965da56dd32cc1be5d29d9cb15"},"package":"2133b12230591b7e727c8977b96b791bba421cd80ce8eb08b782dcb4a43fa1e9"} \ No newline at end of file
diff --git a/third_party/rust/moz_cbor/Cargo.toml b/third_party/rust/moz_cbor/Cargo.toml
new file mode 100644
index 0000000000..e849e919ad
--- /dev/null
+++ b/third_party/rust/moz_cbor/Cargo.toml
@@ -0,0 +1,23 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "moz_cbor"
+version = "0.1.2"
+authors = ["Franziskus Kiefer <franziskuskiefer@gmail.com>", "David Keeler <dkeeler@mozilla.com>"]
+description = "Library to use CBOR (https://tools.ietf.org/html/rfc7049) in Rust"
+keywords = ["jose", "cbor"]
+license = "MPL-2.0"
+repository = "https://github.com/franziskuskiefer/cbor-rust"
+
+[features]
+default = []
diff --git a/third_party/rust/moz_cbor/LICENSE b/third_party/rust/moz_cbor/LICENSE
new file mode 100644
index 0000000000..a612ad9813
--- /dev/null
+++ b/third_party/rust/moz_cbor/LICENSE
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/third_party/rust/moz_cbor/README.md b/third_party/rust/moz_cbor/README.md
new file mode 100644
index 0000000000..5b8da92e6c
--- /dev/null
+++ b/third_party/rust/moz_cbor/README.md
@@ -0,0 +1,8 @@
+# cbor-rust
+
+A Rust library for [CBOR](https://tools.ietf.org/html/rfc7049).
+
+[![Build Status](https://travis-ci.org/franziskuskiefer/cbor-rust.svg?branch=master)](https://travis-ci.org/franziskuskiefer/cbor-rust/)
+![Maturity Level](https://img.shields.io/badge/maturity-alpha-red.svg)
+
+**THIS IS WORK IN PROGRESS. DO NOT USE YET.**
diff --git a/third_party/rust/moz_cbor/rustfmt.toml b/third_party/rust/moz_cbor/rustfmt.toml
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/third_party/rust/moz_cbor/rustfmt.toml
diff --git a/third_party/rust/moz_cbor/src/decoder.rs b/third_party/rust/moz_cbor/src/decoder.rs
new file mode 100644
index 0000000000..f93bb13f1c
--- /dev/null
+++ b/third_party/rust/moz_cbor/src/decoder.rs
@@ -0,0 +1,165 @@
+use std::collections::BTreeMap;
+use std::io::{Cursor, Read, Seek, SeekFrom};
+use {CborError, CborType};
+
+// We limit the length of any cbor byte array to 128MiB. This is a somewhat
+// arbitrary limit that should work on all platforms and is large enough for
+// any benign data.
+pub const MAX_ARRAY_SIZE: usize = 134_217_728;
+
+// Prevent stack exhaustion by limiting the nested depth of CBOR data.
+const MAX_NESTED_DEPTH: usize = 256;
+
+/// Struct holding a cursor and additional information for decoding.
+#[derive(Debug)]
+struct DecoderCursor<'a> {
+ cursor: Cursor<&'a [u8]>,
+ depth: usize,
+}
+
+/// Apply this mask (with &) to get the value part of the initial byte of a CBOR item.
+const INITIAL_VALUE_MASK: u64 = 0b0001_1111;
+
+impl<'a> DecoderCursor<'a> {
+ /// Read and return the given number of bytes from the cursor. Advances the cursor.
+ fn read_bytes(&mut self, len: usize) -> Result<Vec<u8>, CborError> {
+ if len > MAX_ARRAY_SIZE {
+ return Err(CborError::InputTooLarge);
+ }
+ let mut buf: Vec<u8> = vec![0; len];
+ if self.cursor.read_exact(&mut buf).is_err() {
+ Err(CborError::TruncatedInput)
+ } else {
+ Ok(buf)
+ }
+ }
+
+ /// Convert num bytes to a u64
+ fn read_uint_from_bytes(&mut self, num: usize) -> Result<u64, CborError> {
+ let x = self.read_bytes(num)?;
+ let mut result: u64 = 0;
+ for i in (0..num).rev() {
+ result += u64::from(x[num - 1 - i]) << (i * 8);
+ }
+ Ok(result)
+ }
+
+ /// Read an integer and return it as u64.
+ fn read_int(&mut self) -> Result<u64, CborError> {
+ let first_value = self.read_uint_from_bytes(1)? & INITIAL_VALUE_MASK;
+ match first_value {
+ 0..=23 => Ok(first_value),
+ 24 => self.read_uint_from_bytes(1),
+ 25 => self.read_uint_from_bytes(2),
+ 26 => self.read_uint_from_bytes(4),
+ 27 => self.read_uint_from_bytes(8),
+ _ => Err(CborError::MalformedInput),
+ }
+ }
+
+ fn read_negative_int(&mut self) -> Result<CborType, CborError> {
+ let uint = self.read_int()?;
+ if uint > i64::max_value() as u64 {
+ return Err(CborError::InputValueOutOfRange);
+ }
+ let result: i64 = -1 - uint as i64;
+ Ok(CborType::SignedInteger(result))
+ }
+
+ /// Read an array of data items and return it.
+ fn read_array(&mut self) -> Result<CborType, CborError> {
+ // Create a new array.
+ let mut array: Vec<CborType> = Vec::new();
+ // Read the length of the array.
+ let num_items = self.read_int()?;
+ // Decode each of the num_items data items.
+ for _ in 0..num_items {
+ let new_item = self.decode_item()?;
+ array.push(new_item);
+ }
+ Ok(CborType::Array(array))
+ }
+
+ /// Read a byte string and return it.
+ fn read_byte_string(&mut self) -> Result<CborType, CborError> {
+ let length = self.read_int()?;
+ if length > MAX_ARRAY_SIZE as u64 {
+ return Err(CborError::InputTooLarge);
+ }
+ let byte_string = self.read_bytes(length as usize)?;
+ Ok(CborType::Bytes(byte_string))
+ }
+
+ /// Read a map.
+ fn read_map(&mut self) -> Result<CborType, CborError> {
+ let num_items = self.read_int()?;
+ // Create a new array.
+ let mut map: BTreeMap<CborType, CborType> = BTreeMap::new();
+ // Decode each of the num_items (key, data item) pairs.
+ for _ in 0..num_items {
+ let key_val = self.decode_item()?;
+ let item_value = self.decode_item()?;
+ if map.insert(key_val, item_value).is_some() {
+ return Err(CborError::DuplicateMapKey);
+ }
+ }
+ Ok(CborType::Map(map))
+ }
+
+ fn read_null(&mut self) -> Result<CborType, CborError> {
+ let value = self.read_uint_from_bytes(1)? & INITIAL_VALUE_MASK;
+ if value != 22 {
+ return Err(CborError::UnsupportedType);
+ }
+ Ok(CborType::Null)
+ }
+
+ /// Peeks at the next byte in the cursor, but does not change the position.
+ fn peek_byte(&mut self) -> Result<u8, CborError> {
+ let x = self.read_bytes(1)?;
+ if self.cursor.seek(SeekFrom::Current(-1)).is_err() {
+ return Err(CborError::LibraryError);
+ };
+ Ok(x[0])
+ }
+
+ /// Decodes the next CBOR item.
+ pub fn decode_item(&mut self) -> Result<CborType, CborError> {
+ if self.depth > MAX_NESTED_DEPTH {
+ return Err(CborError::MalformedInput);
+ }
+ self.depth += 1;
+ let major_type = self.peek_byte()? >> 5;
+ let result = match major_type {
+ 0 => {
+ let value = self.read_int()?;
+ Ok(CborType::Integer(value))
+ }
+ 1 => self.read_negative_int(),
+ 2 => self.read_byte_string(),
+ 4 => self.read_array(),
+ 5 => self.read_map(),
+ 6 => {
+ let tag = self.read_int()?;
+ let item = self.decode_item()?;
+ Ok(CborType::Tag(tag, Box::new(item)))
+ }
+ 7 => self.read_null(),
+ _ => Err(CborError::UnsupportedType),
+ };
+ self.depth -= 1;
+ result
+ }
+}
+
+/// Read the CBOR structure in bytes and return it as a `CborType`. To prevent stack exhaustion, the
+/// maximum nested depth of CBOR objects (for example, an array of an array of an array...) is 256.
+/// If the input data describes a CBOR structure that exceeds this limit, an error will be returned.
+pub fn decode(bytes: &[u8]) -> Result<CborType, CborError> {
+ let mut decoder_cursor = DecoderCursor {
+ cursor: Cursor::new(bytes),
+ depth: 0,
+ };
+ decoder_cursor.decode_item()
+ // TODO: check cursor at end?
+}
diff --git a/third_party/rust/moz_cbor/src/lib.rs b/third_party/rust/moz_cbor/src/lib.rs
new file mode 100644
index 0000000000..de9f992df0
--- /dev/null
+++ b/third_party/rust/moz_cbor/src/lib.rs
@@ -0,0 +1,51 @@
+pub mod decoder;
+pub mod serializer;
+#[cfg(test)]
+mod test_decoder;
+#[cfg(test)]
+mod test_serializer;
+
+use std::cmp::Ordering;
+use std::collections::BTreeMap;
+
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq)]
+pub enum CborType {
+ Integer(u64),
+ SignedInteger(i64),
+ Tag(u64, Box<CborType>),
+ Bytes(Vec<u8>),
+ String(String),
+ Array(Vec<CborType>),
+ Map(BTreeMap<CborType, CborType>),
+ Null,
+}
+
+#[derive(Debug, PartialEq)]
+pub enum CborError {
+ DuplicateMapKey,
+ InputTooLarge,
+ InputValueOutOfRange,
+ LibraryError,
+ MalformedInput,
+ TruncatedInput,
+ UnsupportedType,
+}
+
+impl Ord for CborType {
+ /// Sorting for maps: RFC 7049 Section 3.9
+ ///
+ /// The keys in every map must be sorted lowest value to highest.
+ /// * 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.
+ fn cmp(&self, other: &Self) -> Ordering {
+ let self_bytes = self.serialize();
+ let other_bytes = other.serialize();
+ if self_bytes.len() == other_bytes.len() {
+ return self_bytes.cmp(&other_bytes);
+ }
+ self_bytes.len().cmp(&other_bytes.len())
+ }
+}
diff --git a/third_party/rust/moz_cbor/src/serializer.rs b/third_party/rust/moz_cbor/src/serializer.rs
new file mode 100644
index 0000000000..b796aaedc7
--- /dev/null
+++ b/third_party/rust/moz_cbor/src/serializer.rs
@@ -0,0 +1,124 @@
+use std::collections::BTreeMap;
+use CborType;
+
+/// Given a vector of bytes to append to, a tag to use, and an unsigned value to encode, uses the
+/// CBOR unsigned integer encoding to represent the given value.
+fn common_encode_unsigned(output: &mut Vec<u8>, tag: u8, value: u64) {
+ assert!(tag < 8);
+ let shifted_tag = tag << 5;
+ match value {
+ 0..=23 => {
+ output.push(shifted_tag | (value as u8));
+ }
+ 24..=255 => {
+ output.push(shifted_tag | 24);
+ output.push(value as u8);
+ }
+ 256..=65_535 => {
+ output.push(shifted_tag | 25);
+ output.push((value >> 8) as u8);
+ output.push((value & 255) as u8);
+ }
+ 65_536..=4_294_967_295 => {
+ output.push(shifted_tag | 26);
+ output.push((value >> 24) as u8);
+ output.push(((value >> 16) & 255) as u8);
+ output.push(((value >> 8) & 255) as u8);
+ output.push((value & 255) as u8);
+ }
+ _ => {
+ output.push(shifted_tag | 27);
+ output.push((value >> 56) as u8);
+ output.push(((value >> 48) & 255) as u8);
+ output.push(((value >> 40) & 255) as u8);
+ output.push(((value >> 32) & 255) as u8);
+ output.push(((value >> 24) & 255) as u8);
+ output.push(((value >> 16) & 255) as u8);
+ output.push(((value >> 8) & 255) as u8);
+ output.push((value & 255) as u8);
+ }
+ };
+}
+
+/// The major type is 0. For values 0 through 23, the 5 bits of additional information is just the
+/// value of the unsigned number. For values representable in one byte, the additional information
+/// has the value 24. If two bytes are necessary, the value is 25. If four bytes are necessary, the
+/// value is 26. If 8 bytes are necessary, the value is 27. The following bytes are the value of the
+/// unsigned number in as many bytes were indicated in network byte order (big endian).
+fn encode_unsigned(output: &mut Vec<u8>, unsigned: u64) {
+ common_encode_unsigned(output, 0, unsigned);
+}
+
+/// The major type is 1. The encoding is the same as for positive (i.e. unsigned) integers, except
+/// the value encoded is -1 minus the value of the negative number.
+fn encode_negative(output: &mut Vec<u8>, negative: i64) {
+ assert!(negative < 0);
+ let value_to_encode: u64 = (-1 - negative) as u64;
+ common_encode_unsigned(output, 1, value_to_encode);
+}
+
+/// The major type is 2. The length of the data is encoded as with positive integers, followed by
+/// the actual data.
+fn encode_bytes(output: &mut Vec<u8>, bstr: &[u8]) {
+ common_encode_unsigned(output, 2, bstr.len() as u64);
+ output.extend_from_slice(bstr);
+}
+
+/// The major type is 3. The length is as with bstr. The UTF-8-encoded bytes of the string follow.
+fn encode_string(output: &mut Vec<u8>, tstr: &str) {
+ let utf8_bytes = tstr.as_bytes();
+ common_encode_unsigned(output, 3, utf8_bytes.len() as u64);
+ output.extend_from_slice(utf8_bytes);
+}
+
+/// The major type is 4. The number of items is encoded as with positive integers. Then follows the
+/// encodings of the items themselves.
+fn encode_array(output: &mut Vec<u8>, array: &[CborType]) {
+ common_encode_unsigned(output, 4, array.len() as u64);
+ for element in array {
+ output.append(&mut element.serialize());
+ }
+}
+
+/// The major type is 5. The number of pairs is encoded as with positive integers. Then follows the
+/// encodings of each key, value pair. In Canonical CBOR, the keys must be sorted lowest value to
+/// highest.
+fn encode_map(output: &mut Vec<u8>, map: &BTreeMap<CborType, CborType>) {
+ common_encode_unsigned(output, 5, map.len() as u64);
+ for (key, value) in map {
+ output.append(&mut key.serialize());
+ output.append(&mut value.serialize());
+ }
+}
+
+fn encode_tag(output: &mut Vec<u8>, tag: &u64, val: &CborType) {
+ common_encode_unsigned(output, 6, *tag);
+ output.append(&mut val.serialize());
+}
+
+/// The major type is 7. The only supported value for this type is 22, which is Null.
+/// This makes the encoded value 246, or 0xf6.
+fn encode_null(output: &mut Vec<u8>) {
+ output.push(0xf6);
+}
+
+impl CborType {
+ /// Serialize a Cbor object. NB: if the object to be serialized consists of too many nested
+ /// Cbor objects (for example, Array(Array(Array(...(Array(0))))), it is possible that calling
+ /// serialize will exhaust the stack. It is considered the caller's responsibility to prevent
+ /// this.
+ pub fn serialize(&self) -> Vec<u8> {
+ let mut bytes: Vec<u8> = Vec::new();
+ match *self {
+ CborType::Integer(ref unsigned) => encode_unsigned(&mut bytes, *unsigned),
+ CborType::SignedInteger(ref negative) => encode_negative(&mut bytes, *negative),
+ CborType::Bytes(ref bstr) => encode_bytes(&mut bytes, bstr),
+ CborType::String(ref tstr) => encode_string(&mut bytes, tstr),
+ CborType::Array(ref arr) => encode_array(&mut bytes, arr),
+ CborType::Map(ref map) => encode_map(&mut bytes, map),
+ CborType::Tag(ref t, ref val) => encode_tag(&mut bytes, t, val),
+ CborType::Null => encode_null(&mut bytes),
+ };
+ bytes
+ }
+}
diff --git a/third_party/rust/moz_cbor/src/test_decoder.rs b/third_party/rust/moz_cbor/src/test_decoder.rs
new file mode 100644
index 0000000000..68db8724d9
--- /dev/null
+++ b/third_party/rust/moz_cbor/src/test_decoder.rs
@@ -0,0 +1,445 @@
+use decoder::{decode, MAX_ARRAY_SIZE};
+use std::collections::BTreeMap;
+use {CborError, CborType};
+
+// First test all the basic types
+fn test_decoder(bytes: Vec<u8>, expected: CborType) {
+ let result = decode(&bytes);
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), expected);
+}
+
+fn test_decoder_error(bytes: Vec<u8>, expected_error: CborError) {
+ let result = decode(&bytes);
+ assert!(result.is_err());
+ assert_eq!(result.unwrap_err(), expected_error);
+}
+
+fn test_integer(bytes: Vec<u8>, expected: u64) {
+ let decoded = decode(&bytes).unwrap();
+ match decoded {
+ CborType::Integer(val) => assert_eq!(val, expected),
+ _ => assert_eq!(1, 0),
+ }
+}
+
+fn test_integer_all(bytes: Vec<u8>, expected_value: u64) {
+ let expected = CborType::Integer(expected_value);
+ test_decoder(bytes.clone(), expected);
+ test_integer(bytes, expected_value);
+}
+
+#[test]
+fn test_integer_objects() {
+ let bytes: Vec<u8> = vec![0x00];
+ test_integer_all(bytes, 0);
+
+ let bytes = vec![0x01];
+ test_integer_all(bytes, 1);
+
+ let bytes = vec![0x0A];
+ test_integer_all(bytes, 10);
+
+ let bytes = vec![0x17];
+ test_integer_all(bytes, 23);
+
+ let bytes = vec![0x18, 0x18];
+ test_integer_all(bytes, 24);
+
+ let bytes = vec![0x18, 0x19];
+ test_integer_all(bytes, 25);
+
+ let bytes = vec![0x18, 0x64];
+ test_integer_all(bytes, 100);
+
+ let bytes = vec![0x19, 0x03, 0xe8];
+ test_integer_all(bytes, 1000);
+
+ let bytes = vec![0x1a, 0x00, 0x0f, 0x42, 0x40];
+ test_integer_all(bytes, 1000000);
+
+ let bytes = vec![0x1b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x10, 0x00];
+ test_integer_all(bytes, 1000000000000);
+
+ let bytes = vec![0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
+ test_integer_all(bytes, 18446744073709551615);
+}
+
+#[cfg(test)]
+fn test_tag(bytes: Vec<u8>, expected_tag: u64, expected_value: CborType) {
+ let decoded = decode(&bytes).unwrap();
+ match decoded {
+ CborType::Tag(tag, value) => {
+ assert_eq!(expected_tag, tag);
+ assert_eq!(expected_value, *value);
+ }
+ _ => assert_eq!(1, 0),
+ }
+}
+
+#[test]
+fn test_tagged_objects() {
+ let bytes: Vec<u8> = vec![0xD2, 0x02];
+ let expected_tag_value = 0x12;
+ let expected_value = CborType::Integer(2);
+ let expected = CborType::Tag(expected_tag_value, Box::new(expected_value.clone()));
+ test_decoder(bytes.clone(), expected);
+ test_tag(bytes, expected_tag_value, expected_value);
+}
+
+#[test]
+#[cfg_attr(rustfmt, rustfmt_skip)]
+fn test_arrays() {
+ // []
+ let bytes: Vec<u8> = vec![0x80];
+ let expected = CborType::Array(vec![]);
+ test_decoder(bytes, expected);
+
+ // [1, 2, 3]
+ let bytes: Vec<u8> = vec![0x83, 0x01, 0x02, 0x03];
+ let tmp = vec![
+ CborType::Integer(1),
+ CborType::Integer(2),
+ CborType::Integer(3),
+ ];
+ let expected = CborType::Array(tmp);
+ test_decoder(bytes, expected);
+
+ // [1, [2, 3], [4, 5]]
+ let bytes: Vec<u8> = vec![0x83, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05];
+ let tmp1 = vec![CborType::Integer(2), CborType::Integer(3)];
+ let tmp2 = vec![CborType::Integer(4), CborType::Integer(5)];
+ let tmp = vec![
+ CborType::Integer(1),
+ CborType::Array(tmp1),
+ CborType::Array(tmp2),
+ ];
+ let expected = CborType::Array(tmp);
+ test_decoder(bytes, expected);
+
+ // [1, [[[[1]]]], [1]]
+ let bytes: Vec<u8> = vec![0x83, 0x01, 0x81, 0x81, 0x81, 0x81, 0x01, 0x81, 0x02];
+ let tmp = vec![
+ CborType::Integer(1),
+ CborType::Array(vec![
+ CborType::Array(vec![
+ CborType::Array(vec![
+ CborType::Array(vec![
+ CborType::Integer(1)])])])]),
+ CborType::Array(vec![CborType::Integer(2)]),
+ ];
+ let expected = CborType::Array(tmp);
+ test_decoder(bytes, expected);
+
+ let bytes: Vec<u8> = vec![0x98, 0x1A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x17, 0x18, 0x18, 0x18, 0x19, 0x82, 0x81, 0x81,
+ 0x81, 0x05, 0x81, 0x1A, 0x49, 0x96, 0x02, 0xD2];
+ // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ // 21, 22, 23, 24, 25, [[[[5]]], [1234567890]]]
+ let tmp = vec![
+ CborType::Integer(1),
+ CborType::Integer(2),
+ CborType::Integer(3),
+ CborType::Integer(4),
+ CborType::Integer(5),
+ CborType::Integer(6),
+ CborType::Integer(7),
+ CborType::Integer(8),
+ CborType::Integer(9),
+ CborType::Integer(10),
+ CborType::Integer(11),
+ CborType::Integer(12),
+ CborType::Integer(13),
+ CborType::Integer(14),
+ CborType::Integer(15),
+ CborType::Integer(16),
+ CborType::Integer(17),
+ CborType::Integer(18),
+ CborType::Integer(19),
+ CborType::Integer(20),
+ CborType::Integer(21),
+ CborType::Integer(22),
+ CborType::Integer(23),
+ CborType::Integer(24),
+ CborType::Integer(25),
+ CborType::Array(vec![
+ CborType::Array(vec![
+ CborType::Array(vec![
+ CborType::Array(vec![
+ CborType::Integer(5)])])]),
+ CborType::Array(vec![CborType::Integer(1234567890)])])
+ ];
+ let expected = CborType::Array(tmp);
+ test_decoder(bytes, expected);
+}
+
+#[test]
+fn test_signed_integer() {
+ let bytes: Vec<u8> = vec![0x20];
+ let expected = CborType::SignedInteger(-1);
+ test_decoder(bytes, expected);
+
+ let bytes = vec![0x29];
+ let expected = CborType::SignedInteger(-10);
+ test_decoder(bytes, expected);
+
+ let bytes = vec![0x38, 0x63];
+ let expected = CborType::SignedInteger(-100);
+ test_decoder(bytes, expected);
+
+ let bytes = vec![0x39, 0x03, 0xe7];
+ let expected = CborType::SignedInteger(-1000);
+ test_decoder(bytes, expected);
+
+ let bytes = vec![0x39, 0x27, 0x0F];
+ let expected = CborType::SignedInteger(-10000);
+ test_decoder(bytes, expected);
+
+ let bytes = vec![0x3A, 0x00, 0x01, 0x86, 0x9F];
+ let expected = CborType::SignedInteger(-100000);
+ test_decoder(bytes, expected);
+
+ let bytes = vec![0x3B, 0x00, 0x00, 0x00, 0xE8, 0xD4, 0xA5, 0x0F, 0xFF];
+ let expected = CborType::SignedInteger(-1000000000000);
+ test_decoder(bytes, expected);
+}
+
+#[test]
+fn test_byte_strings() {
+ let bytes: Vec<u8> = vec![0x40];
+ let expected = CborType::Bytes(vec![]);
+ test_decoder(bytes, expected);
+
+ // 01020304
+ let bytes: Vec<u8> = vec![0x44, 0x01, 0x02, 0x03, 0x04];
+ let expected = CborType::Bytes(vec![0x01, 0x02, 0x03, 0x04]);
+ test_decoder(bytes, expected);
+
+ // 0102030405060708090A0B0C0D0E0F10203040506070
+ let bytes: Vec<u8> = vec![
+ 0x56, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 0x0f, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
+ ];
+ let expected = CborType::Bytes(vec![
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
+ ]);
+ test_decoder(bytes, expected);
+
+ let bytes: Vec<u8> = vec![
+ 0x59, 0x01, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF,
+ ];
+ let expected = CborType::Bytes(vec![
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ ]);
+ test_decoder(bytes, expected);
+}
+
+#[test]
+fn test_maps() {
+ // {}
+ let bytes: Vec<u8> = vec![0xa0];
+ let expected: BTreeMap<CborType, CborType> = BTreeMap::new();
+ test_decoder(bytes, CborType::Map(expected));
+
+ // {1: 2, 3: 4}
+ let bytes: Vec<u8> = vec![0xa2, 0x01, 0x02, 0x03, 0x04];
+ let mut expected: BTreeMap<CborType, CborType> = BTreeMap::new();
+ expected.insert(CborType::Integer(1), CborType::Integer(2));
+ expected.insert(CborType::Integer(3), CborType::Integer(4));
+ test_decoder(bytes, CborType::Map(expected));
+
+ // TODO: strings aren't properly supported as keys yet.
+ // {"a": 1, "b": [2, 3]}
+ // let bytes: Vec<u8> = vec![0xa2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03];
+ // let expected =
+ // CborType::Map(vec![
+ // CborMap{key: CborType::Integer(1), value: CborType::Integer(2)},
+ // CborMap{key: CborType::Integer(3), value: CborType::Integer(4)}]);
+ // test_decoder(bytes, expected);
+
+ // let bytes: Vec<u8> = vec![0x82, 0x61, 0x61, 0xa1, 0x61, 0x62, 0x61, 0x63];
+ // test_decoder(bytes, "[a, {b: c}]");
+
+ // let bytes: Vec<u8> = vec![0xa5, 0x61, 0x61, 0x61, 0x41, 0x61, 0x62, 0x61,
+ // 0x42, 0x61, 0x63, 0x61, 0x43, 0x61, 0x64, 0x61,
+ // 0x44, 0x61, 0x65, 0x61, 0x45];
+ // test_decoder(bytes, "{a: A, b: B, c: C, d: D, e: E}");
+}
+
+#[test]
+fn test_map_duplicate_keys() {
+ let bytes: Vec<u8> = vec![0xa4, 0x01, 0x02, 0x02, 0x03, 0x01, 0x03, 0x04, 0x04];
+ test_decoder_error(bytes, CborError::DuplicateMapKey);
+}
+
+#[test]
+fn test_tag_with_no_value() {
+ let bytes: Vec<u8> = vec![0xc0];
+ test_decoder_error(bytes, CborError::TruncatedInput);
+}
+
+#[test]
+fn test_truncated_int() {
+ let bytes: Vec<u8> = vec![0x19, 0x03];
+ test_decoder_error(bytes, CborError::TruncatedInput);
+}
+
+#[test]
+fn test_truncated_array() {
+ let bytes: Vec<u8> = vec![0x83, 0x01, 0x02];
+ test_decoder_error(bytes, CborError::TruncatedInput);
+}
+
+#[test]
+fn test_truncated_map() {
+ let bytes: Vec<u8> = vec![0xa2, 0x01, 0x02, 0x00];
+ test_decoder_error(bytes, CborError::TruncatedInput);
+}
+
+#[test]
+fn test_malformed_integer() {
+ let bytes: Vec<u8> = vec![0x1c];
+ test_decoder_error(bytes, CborError::MalformedInput);
+}
+
+#[test]
+fn test_signed_integer_too_large() {
+ let bytes = vec![0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
+ test_decoder_error(bytes, CborError::InputValueOutOfRange);
+}
+
+#[test]
+fn test_null() {
+ let bytes = vec![0xf6];
+ test_decoder(bytes, CborType::Null);
+}
+
+#[test]
+fn test_null_in_array() {
+ let bytes = vec![0x82, 0xf6, 0xf6];
+ test_decoder(bytes, CborType::Array(vec![CborType::Null, CborType::Null]));
+}
+
+#[test]
+fn test_major_type_7() {
+ for i in 0..0x20 {
+ if i != 22 {
+ let bytes = vec![0xe0 | i];
+ test_decoder_error(bytes, CborError::UnsupportedType);
+ }
+ }
+}
+
+#[test]
+fn test_large_input() {
+ let array = vec![0xFF; MAX_ARRAY_SIZE];
+ let expected = CborType::Bytes(array.clone());
+ let mut bytes = vec![0x5A, 0x08, 0x00, 0x00, 0x00];
+ bytes.extend_from_slice(&array);
+ test_decoder(bytes, expected);
+}
+
+#[test]
+fn test_too_large_input() {
+ let array = vec![0xFF; MAX_ARRAY_SIZE + 1];
+ let mut bytes = vec![0x5A, 0x08, 0x00, 0x00, 0x01];
+ bytes.extend_from_slice(&array);
+ test_decoder_error(bytes, CborError::InputTooLarge);
+}
+
+// We currently don't support CBOR strings (issue #39).
+#[test]
+fn test_invalid_input() {
+ let bytes = vec![0x60];
+ test_decoder_error(bytes, CborError::UnsupportedType);
+}
+
+#[test]
+fn test_avoid_stack_exhaustion_with_arrays() {
+ let mut bytes: Vec<u8> = Vec::new();
+ // Create a payload representing Array(Array(Array(Array(...(Array(0))))))
+ // If the implementation is not careful, this will exhaust the stack.
+ for _ in 1..10000 {
+ bytes.push(0b1000_0001);
+ }
+ bytes.push(0);
+ test_decoder_error(bytes, CborError::MalformedInput);
+}
+
+#[test]
+fn test_avoid_stack_exhaustion_with_maps_1() {
+ let mut bytes: Vec<u8> = Vec::new();
+ // Create a payload representing Map(0: Map(0: Map(0: Map(...Map()))))
+ // If the implementation is not careful, this will exhaust the stack.
+ for _ in 1..10000 {
+ bytes.push(0b1010_0001);
+ bytes.push(0);
+ }
+ bytes.push(0b1010_0000);
+ test_decoder_error(bytes, CborError::MalformedInput);
+}
+
+#[test]
+fn test_avoid_stack_exhaustion_with_maps_2() {
+ let mut bytes: Vec<u8> = Vec::new();
+ // Create a payload representing Map(Map(Map(...(Map(): 0): 0): 0): 0)
+ // If the implementation is not careful, this will exhaust the stack.
+ for _ in 1..10000 {
+ bytes.push(0b1010_0001);
+ }
+ bytes.push(0b1010_0000);
+ for _ in 1..9999 {
+ bytes.push(0);
+ }
+ test_decoder_error(bytes, CborError::MalformedInput);
+}
+
+#[test]
+fn test_avoid_stack_exhaustion_with_tags() {
+ let mut bytes: Vec<u8> = Vec::new();
+ // Create a payload representing Tag(6: Tag(6: Tag(6: Tag(...Tag(0)))))
+ // If the implementation is not careful, this will exhaust the stack.
+ for _ in 1..10000 {
+ bytes.push(0b1100_0110);
+ }
+ bytes.push(0);
+ test_decoder_error(bytes, CborError::MalformedInput);
+}
diff --git a/third_party/rust/moz_cbor/src/test_serializer.rs b/third_party/rust/moz_cbor/src/test_serializer.rs
new file mode 100644
index 0000000000..09800f5a50
--- /dev/null
+++ b/third_party/rust/moz_cbor/src/test_serializer.rs
@@ -0,0 +1,324 @@
+use std::collections::BTreeMap;
+use CborType;
+
+#[test]
+fn test_nint() {
+ struct Testcase {
+ value: i64,
+ expected: Vec<u8>,
+ }
+ let testcases: Vec<Testcase> = vec![
+ Testcase {
+ value: -1,
+ expected: vec![0x20],
+ },
+ Testcase {
+ value: -10,
+ expected: vec![0x29],
+ },
+ Testcase {
+ value: -100,
+ expected: vec![0x38, 0x63],
+ },
+ Testcase {
+ value: -1000,
+ expected: vec![0x39, 0x03, 0xe7],
+ },
+ Testcase {
+ value: -1000000,
+ expected: vec![0x3a, 0x00, 0x0f, 0x42, 0x3f],
+ },
+ Testcase {
+ value: -4611686018427387903,
+ expected: vec![0x3b, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe],
+ },
+ ];
+ for testcase in testcases {
+ let cbor = CborType::SignedInteger(testcase.value);
+ assert_eq!(testcase.expected, cbor.serialize());
+ }
+}
+
+#[test]
+fn test_bstr() {
+ struct Testcase {
+ value: Vec<u8>,
+ expected: Vec<u8>,
+ }
+ let testcases: Vec<Testcase> = vec![
+ Testcase {
+ value: vec![],
+ expected: vec![0x40],
+ },
+ Testcase {
+ value: vec![0x01, 0x02, 0x03, 0x04],
+ expected: vec![0x44, 0x01, 0x02, 0x03, 0x04],
+ },
+ Testcase {
+ value: vec![
+ 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
+ 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
+ ],
+ expected: vec![
+ 0x58, 0x19, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
+ 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
+ ],
+ },
+ ];
+ for testcase in testcases {
+ let cbor = CborType::Bytes(testcase.value);
+ assert_eq!(testcase.expected, cbor.serialize());
+ }
+}
+
+#[test]
+fn test_tstr() {
+ struct Testcase {
+ value: String,
+ expected: Vec<u8>,
+ }
+ let testcases: Vec<Testcase> = vec![
+ Testcase {
+ value: String::new(),
+ expected: vec![0x60],
+ },
+ Testcase {
+ value: String::from("a"),
+ expected: vec![0x61, 0x61],
+ },
+ Testcase {
+ value: String::from("IETF"),
+ expected: vec![0x64, 0x49, 0x45, 0x54, 0x46],
+ },
+ Testcase {
+ value: String::from("\"\\"),
+ expected: vec![0x62, 0x22, 0x5c],
+ },
+ Testcase {
+ value: String::from("水"),
+ expected: vec![0x63, 0xe6, 0xb0, 0xb4],
+ },
+ ];
+ for testcase in testcases {
+ let cbor = CborType::String(testcase.value);
+ assert_eq!(testcase.expected, cbor.serialize());
+ }
+}
+
+#[test]
+fn test_arr() {
+ struct Testcase {
+ value: Vec<CborType>,
+ expected: Vec<u8>,
+ }
+ let nested_arr_1 = vec![CborType::Integer(2), CborType::Integer(3)];
+ let nested_arr_2 = vec![CborType::Integer(4), CborType::Integer(5)];
+ let testcases: Vec<Testcase> = vec![
+ Testcase {
+ value: vec![],
+ expected: vec![0x80],
+ },
+ Testcase {
+ value: vec![
+ CborType::Integer(1),
+ CborType::Integer(2),
+ CborType::Integer(3),
+ ],
+ expected: vec![0x83, 0x01, 0x02, 0x03],
+ },
+ Testcase {
+ value: vec![
+ CborType::Integer(1),
+ CborType::Array(nested_arr_1),
+ CborType::Array(nested_arr_2),
+ ],
+ expected: vec![0x83, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05],
+ },
+ Testcase {
+ value: vec![
+ CborType::Integer(1),
+ CborType::Integer(2),
+ CborType::Integer(3),
+ CborType::Integer(4),
+ CborType::Integer(5),
+ CborType::Integer(6),
+ CborType::Integer(7),
+ CborType::Integer(8),
+ CborType::Integer(9),
+ CborType::Integer(10),
+ CborType::Integer(11),
+ CborType::Integer(12),
+ CborType::Integer(13),
+ CborType::Integer(14),
+ CborType::Integer(15),
+ CborType::Integer(16),
+ CborType::Integer(17),
+ CborType::Integer(18),
+ CborType::Integer(19),
+ CborType::Integer(20),
+ CborType::Integer(21),
+ CborType::Integer(22),
+ CborType::Integer(23),
+ CborType::Integer(24),
+ CborType::Integer(25),
+ ],
+ expected: vec![
+ 0x98, 0x19, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+ 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x18, 0x18,
+ 0x19,
+ ],
+ },
+ ];
+ for testcase in testcases {
+ let cbor = CborType::Array(testcase.value);
+ assert_eq!(testcase.expected, cbor.serialize());
+ }
+}
+
+#[test]
+fn test_map() {
+ let empty_map: BTreeMap<CborType, CborType> = BTreeMap::new();
+ assert_eq!(vec![0xa0], CborType::Map(empty_map).serialize());
+
+ let mut positive_map: BTreeMap<CborType, CborType> = BTreeMap::new();
+ positive_map.insert(CborType::Integer(20), CborType::Integer(10));
+ positive_map.insert(CborType::Integer(10), CborType::Integer(20));
+ positive_map.insert(CborType::Integer(15), CborType::Integer(15));
+ assert_eq!(
+ vec![0xa3, 0x0a, 0x14, 0x0f, 0x0f, 0x14, 0x0a],
+ CborType::Map(positive_map).serialize()
+ );
+
+ let mut negative_map: BTreeMap<CborType, CborType> = BTreeMap::new();
+ negative_map.insert(CborType::SignedInteger(-4), CborType::Integer(10));
+ negative_map.insert(CborType::SignedInteger(-1), CborType::Integer(20));
+ negative_map.insert(CborType::SignedInteger(-5), CborType::Integer(15));
+ negative_map.insert(CborType::SignedInteger(-6), CborType::Integer(10));
+ assert_eq!(
+ vec![0xa4, 0x20, 0x14, 0x23, 0x0a, 0x24, 0x0f, 0x25, 0x0a],
+ CborType::Map(negative_map).serialize()
+ );
+
+ let mut mixed_map: BTreeMap<CborType, CborType> = BTreeMap::new();
+ mixed_map.insert(CborType::Integer(0), CborType::Integer(10));
+ mixed_map.insert(CborType::SignedInteger(-10), CborType::Integer(20));
+ mixed_map.insert(CborType::Integer(15), CborType::Integer(15));
+ assert_eq!(
+ vec![0xa3, 0x00, 0x0a, 0x0f, 0x0f, 0x29, 0x14],
+ CborType::Map(mixed_map).serialize()
+ );
+
+ let mut very_mixed_map: BTreeMap<CborType, CborType> = BTreeMap::new();
+ very_mixed_map.insert(CborType::Integer(0), CborType::Integer(10));
+ very_mixed_map.insert(
+ CborType::SignedInteger(-10000),
+ CborType::String("low".to_string()),
+ );
+ very_mixed_map.insert(CborType::SignedInteger(-10), CborType::Integer(20));
+ very_mixed_map.insert(
+ CborType::Integer(10001),
+ CborType::String("high".to_string()),
+ );
+ very_mixed_map.insert(
+ CborType::Integer(10000),
+ CborType::String("high".to_string()),
+ );
+ very_mixed_map.insert(CborType::Integer(15), CborType::Integer(15));
+ let expected = vec![
+ 0xa6, 0x00, 0x0a, 0x0f, 0x0f, 0x29, 0x14, 0x19, 0x27, 0x10, 0x64, 0x68, 0x69, 0x67, 0x68,
+ 0x19, 0x27, 0x11, 0x64, 0x68, 0x69, 0x67, 0x68, 0x39, 0x27, 0x0F, 0x63, 0x6C, 0x6F, 0x77,
+ ];
+ assert_eq!(expected, CborType::Map(very_mixed_map).serialize());
+}
+
+#[test]
+#[ignore]
+// XXX: The string isn't put into the map at the moment, so we can't actually
+// test this.
+fn test_invalid_map() {
+ let mut invalid_map: BTreeMap<CborType, CborType> = BTreeMap::new();
+ invalid_map.insert(CborType::SignedInteger(-10), CborType::Integer(20));
+ invalid_map.insert(CborType::String("0".to_string()), CborType::Integer(10));
+ invalid_map.insert(CborType::Integer(15), CborType::Integer(15));
+ let expected: Vec<u8> = vec![];
+ assert_eq!(expected, CborType::Map(invalid_map).serialize());
+}
+
+#[test]
+fn test_integer() {
+ struct Testcase {
+ value: u64,
+ expected: Vec<u8>,
+ }
+ let testcases: Vec<Testcase> = vec![
+ Testcase {
+ value: 0,
+ expected: vec![0],
+ },
+ Testcase {
+ value: 1,
+ expected: vec![1],
+ },
+ Testcase {
+ value: 10,
+ expected: vec![0x0a],
+ },
+ Testcase {
+ value: 23,
+ expected: vec![0x17],
+ },
+ Testcase {
+ value: 24,
+ expected: vec![0x18, 0x18],
+ },
+ Testcase {
+ value: 25,
+ expected: vec![0x18, 0x19],
+ },
+ Testcase {
+ value: 100,
+ expected: vec![0x18, 0x64],
+ },
+ Testcase {
+ value: 1000,
+ expected: vec![0x19, 0x03, 0xe8],
+ },
+ Testcase {
+ value: 1000000,
+ expected: vec![0x1a, 0x00, 0x0f, 0x42, 0x40],
+ },
+ Testcase {
+ value: 1000000000000,
+ expected: vec![0x1b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x10, 0x00],
+ },
+ Testcase {
+ value: 18446744073709551615,
+ expected: vec![0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
+ },
+ ];
+ for testcase in testcases {
+ let cbor = CborType::Integer(testcase.value);
+ assert_eq!(testcase.expected, cbor.serialize());
+ }
+}
+
+#[test]
+fn test_tagged_item() {
+ let cbor = CborType::Tag(0x12, Box::new(CborType::Integer(2).clone()));
+ assert_eq!(vec![0xD2, 0x02], cbor.serialize());
+
+ let cbor = CborType::Tag(0x62, Box::new(CborType::Array(vec![]).clone()));
+ assert_eq!(vec![0xD8, 0x62, 0x80], cbor.serialize());
+}
+
+#[test]
+fn test_null() {
+ let cbor = CborType::Null;
+ assert_eq!(vec![0xf6], cbor.serialize());
+}
+
+#[test]
+fn test_null_in_array() {
+ let cbor = CborType::Array(vec![CborType::Null, CborType::Null]);
+ assert_eq!(vec![0x82, 0xf6, 0xf6], cbor.serialize());
+}