summaryrefslogtreecommitdiffstats
path: root/third_party/rust/moz_cbor/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/rust/moz_cbor/src
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/moz_cbor/src')
-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
5 files changed, 1109 insertions, 0 deletions
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());
+}