Initial commit

This commit is contained in:
Jean-Michel Picod
2020-01-28 15:09:10 +01:00
commit f91d2fd3db
90 changed files with 31123 additions and 0 deletions

29
libraries/cbor/src/lib.rs Normal file
View File

@@ -0,0 +1,29 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
#[cfg(feature = "std")]
extern crate core;
#[macro_use]
pub mod macros;
pub mod reader;
pub mod values;
pub mod writer;
pub use self::reader::read;
pub use self::values::{KeyType, SimpleValue, Value};
pub use self::writer::write;

View File

@@ -0,0 +1,500 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#[macro_export]
macro_rules! cbor_map {
// trailing comma case
( $( $key:expr => $value:expr, )+ ) => {
cbor_map! ( $($key => $value),+ )
};
( $( $key:expr => $value:expr ),* ) => {
{
// The import is unused if the list is empty.
#[allow(unused_imports)]
use $crate::values::{IntoCborKey, IntoCborValue};
let mut _map = ::alloc::collections::BTreeMap::new();
$(
_map.insert($key.into_cbor_key(), $value.into_cbor_value());
)*
$crate::values::Value::Map(_map)
}
};
}
#[macro_export]
macro_rules! cbor_map_options {
// trailing comma case
( $( $key:expr => $value:expr, )+ ) => {
cbor_map_options! ( $($key => $value),+ )
};
( $( $key:expr => $value:expr ),* ) => {
{
// The import is unused if the list is empty.
#[allow(unused_imports)]
use $crate::values::{IntoCborKey, IntoCborValueOption};
let mut _map = ::alloc::collections::BTreeMap::<_, $crate::values::Value>::new();
$(
{
let opt: Option<$crate::values::Value> = $value.into_cbor_value_option();
if let Some(val) = opt {
_map.insert($key.into_cbor_key(), val);
}
}
)*
$crate::values::Value::Map(_map)
}
};
}
#[macro_export]
macro_rules! cbor_map_btree {
( $tree:expr ) => {
$crate::values::Value::Map($tree)
};
}
#[macro_export]
macro_rules! cbor_array {
// trailing comma case
( $( $value:expr, )+ ) => {
cbor_array! ( $($value),+ )
};
( $( $value:expr ),* ) => {
{
// The import is unused if the list is empty.
#[allow(unused_imports)]
use $crate::values::IntoCborValue;
$crate::values::Value::Array(vec![ $( $value.into_cbor_value(), )* ])
}
};
}
#[macro_export]
macro_rules! cbor_array_vec {
( $vec:expr ) => {{
use $crate::values::IntoCborValue;
$crate::values::Value::Array($vec.into_iter().map(|x| x.into_cbor_value()).collect())
}};
}
#[cfg(test)]
macro_rules! cbor_true {
( ) => {
$crate::values::Value::Simple($crate::values::SimpleValue::TrueValue)
};
}
#[macro_export]
macro_rules! cbor_false {
( ) => {
$crate::values::Value::Simple($crate::values::SimpleValue::FalseValue)
};
}
#[macro_export]
macro_rules! cbor_null {
( ) => {
$crate::values::Value::Simple($crate::values::SimpleValue::NullValue)
};
}
#[cfg(test)]
macro_rules! cbor_undefined {
( ) => {
$crate::values::Value::Simple($crate::values::SimpleValue::Undefined)
};
}
#[macro_export]
macro_rules! cbor_bool {
( $x:expr ) => {
$crate::values::Value::bool_value($x)
};
}
// For key types, we construct a KeyType and call .into(), which will automatically convert it to a
// KeyType or a Value depending on the context.
#[macro_export]
macro_rules! cbor_unsigned {
( $x:expr ) => {
cbor_key_unsigned!($x).into()
};
}
#[macro_export]
macro_rules! cbor_int {
( $x:expr ) => {
cbor_key_int!($x).into()
};
}
#[macro_export]
macro_rules! cbor_text {
( $x:expr ) => {
cbor_key_text!($x).into()
};
}
#[macro_export]
macro_rules! cbor_bytes {
( $x:expr ) => {
cbor_key_bytes!($x).into()
};
}
// Macro to use with a literal, e.g. cbor_bytes_lit!(b"foo")
#[macro_export]
macro_rules! cbor_bytes_lit {
( $x:expr ) => {
cbor_bytes!(($x as &[u8]).to_vec())
};
}
// Some explicit macros are also available for contexts where the type is not explicit.
#[macro_export]
macro_rules! cbor_key_unsigned {
( $x:expr ) => {
$crate::values::KeyType::Unsigned($x)
};
}
#[macro_export]
macro_rules! cbor_key_int {
( $x:expr ) => {
$crate::values::KeyType::integer($x)
};
}
#[macro_export]
macro_rules! cbor_key_text {
( $x:expr ) => {
$crate::values::KeyType::TextString($x.into())
};
}
#[macro_export]
macro_rules! cbor_key_bytes {
( $x:expr ) => {
$crate::values::KeyType::ByteString($x)
};
}
#[cfg(test)]
mod test {
use super::super::values::{KeyType, SimpleValue, Value};
use alloc::collections::BTreeMap;
#[test]
fn test_cbor_simple_values() {
assert_eq!(cbor_true!(), Value::Simple(SimpleValue::TrueValue));
assert_eq!(cbor_false!(), Value::Simple(SimpleValue::FalseValue));
assert_eq!(cbor_null!(), Value::Simple(SimpleValue::NullValue));
assert_eq!(cbor_undefined!(), Value::Simple(SimpleValue::Undefined));
}
#[test]
fn test_cbor_bool() {
assert_eq!(cbor_bool!(true), Value::Simple(SimpleValue::TrueValue));
assert_eq!(cbor_bool!(false), Value::Simple(SimpleValue::FalseValue));
}
#[test]
fn test_cbor_int_unsigned() {
assert_eq!(cbor_key_int!(0), KeyType::Unsigned(0));
assert_eq!(cbor_key_int!(1), KeyType::Unsigned(1));
assert_eq!(cbor_key_int!(123456), KeyType::Unsigned(123456));
assert_eq!(
cbor_key_int!(std::i64::MAX),
KeyType::Unsigned(std::i64::MAX as u64)
);
}
#[test]
fn test_cbor_int_negative() {
assert_eq!(cbor_key_int!(-1), KeyType::Negative(-1));
assert_eq!(cbor_key_int!(-123456), KeyType::Negative(-123456));
assert_eq!(
cbor_key_int!(std::i64::MIN),
KeyType::Negative(std::i64::MIN)
);
}
#[test]
fn test_cbor_int_literals() {
let a = cbor_array![
std::i64::MIN,
std::i32::MIN,
-123456,
-1,
0,
1,
123456,
std::i32::MAX,
std::i64::MAX,
std::u64::MAX,
];
let b = Value::Array(vec![
Value::KeyValue(KeyType::Negative(std::i64::MIN)),
Value::KeyValue(KeyType::Negative(std::i32::MIN as i64)),
Value::KeyValue(KeyType::Negative(-123456)),
Value::KeyValue(KeyType::Negative(-1)),
Value::KeyValue(KeyType::Unsigned(0)),
Value::KeyValue(KeyType::Unsigned(1)),
Value::KeyValue(KeyType::Unsigned(123456)),
Value::KeyValue(KeyType::Unsigned(std::i32::MAX as u64)),
Value::KeyValue(KeyType::Unsigned(std::i64::MAX as u64)),
Value::KeyValue(KeyType::Unsigned(std::u64::MAX)),
]);
assert_eq!(a, b);
}
#[test]
fn test_cbor_array() {
let a = cbor_array![
-123,
456,
true,
cbor_null!(),
"foo",
b"bar",
cbor_array![],
cbor_array![0, 1],
cbor_map! {},
cbor_map! {2 => 3},
];
let b = Value::Array(vec![
Value::KeyValue(KeyType::Negative(-123)),
Value::KeyValue(KeyType::Unsigned(456)),
Value::Simple(SimpleValue::TrueValue),
Value::Simple(SimpleValue::NullValue),
Value::KeyValue(KeyType::TextString(String::from("foo"))),
Value::KeyValue(KeyType::ByteString(b"bar".to_vec())),
Value::Array(Vec::new()),
Value::Array(vec![
Value::KeyValue(KeyType::Unsigned(0)),
Value::KeyValue(KeyType::Unsigned(1)),
]),
Value::Map(BTreeMap::new()),
Value::Map(
[(KeyType::Unsigned(2), Value::KeyValue(KeyType::Unsigned(3)))]
.iter()
.cloned()
.collect(),
),
]);
assert_eq!(a, b);
}
#[test]
fn test_cbor_array_vec_empty() {
let a = cbor_array_vec!(Vec::<bool>::new());
let b = Value::Array(Vec::new());
assert_eq!(a, b);
}
#[test]
fn test_cbor_array_vec_int() {
let a = cbor_array_vec!(vec![1, 2, 3, 4]);
let b = Value::Array(vec![
Value::KeyValue(KeyType::Unsigned(1)),
Value::KeyValue(KeyType::Unsigned(2)),
Value::KeyValue(KeyType::Unsigned(3)),
Value::KeyValue(KeyType::Unsigned(4)),
]);
assert_eq!(a, b);
}
#[test]
fn test_cbor_array_vec_text() {
let a = cbor_array_vec!(vec!["a", "b", "c"]);
let b = Value::Array(vec![
Value::KeyValue(KeyType::TextString(String::from("a"))),
Value::KeyValue(KeyType::TextString(String::from("b"))),
Value::KeyValue(KeyType::TextString(String::from("c"))),
]);
assert_eq!(a, b);
}
#[test]
fn test_cbor_array_vec_bytes() {
let a = cbor_array_vec!(vec![b"a", b"b", b"c"]);
let b = Value::Array(vec![
Value::KeyValue(KeyType::ByteString(b"a".to_vec())),
Value::KeyValue(KeyType::ByteString(b"b".to_vec())),
Value::KeyValue(KeyType::ByteString(b"c".to_vec())),
]);
assert_eq!(a, b);
}
#[test]
fn test_cbor_map() {
let a = cbor_map! {
-1 => -23,
4 => 56,
"foo" => true,
b"bar" => cbor_null!(),
5 => "foo",
6 => b"bar",
7 => cbor_array![],
8 => cbor_array![0, 1],
9 => cbor_map!{},
10 => cbor_map!{2 => 3},
};
let b = Value::Map(
[
(
KeyType::Negative(-1),
Value::KeyValue(KeyType::Negative(-23)),
),
(KeyType::Unsigned(4), Value::KeyValue(KeyType::Unsigned(56))),
(
KeyType::TextString(String::from("foo")),
Value::Simple(SimpleValue::TrueValue),
),
(
KeyType::ByteString(b"bar".to_vec()),
Value::Simple(SimpleValue::NullValue),
),
(
KeyType::Unsigned(5),
Value::KeyValue(KeyType::TextString(String::from("foo"))),
),
(
KeyType::Unsigned(6),
Value::KeyValue(KeyType::ByteString(b"bar".to_vec())),
),
(KeyType::Unsigned(7), Value::Array(Vec::new())),
(
KeyType::Unsigned(8),
Value::Array(vec![
Value::KeyValue(KeyType::Unsigned(0)),
Value::KeyValue(KeyType::Unsigned(1)),
]),
),
(KeyType::Unsigned(9), Value::Map(BTreeMap::new())),
(
KeyType::Unsigned(10),
Value::Map(
[(KeyType::Unsigned(2), Value::KeyValue(KeyType::Unsigned(3)))]
.iter()
.cloned()
.collect(),
),
),
]
.iter()
.cloned()
.collect(),
);
assert_eq!(a, b);
}
#[test]
fn test_cbor_map_options() {
let a = cbor_map_options! {
-1 => -23,
4 => Some(56),
11 => None::<String>,
"foo" => true,
12 => None::<&str>,
b"bar" => Some(cbor_null!()),
13 => None::<Vec<u8>>,
5 => "foo",
14 => None::<&[u8]>,
6 => Some(b"bar" as &[u8]),
15 => None::<bool>,
7 => cbor_array![],
16 => None::<i32>,
8 => Some(cbor_array![0, 1]),
17 => None::<i64>,
9 => cbor_map!{},
18 => None::<u64>,
10 => Some(cbor_map!{2 => 3}),
};
let b = Value::Map(
[
(
KeyType::Negative(-1),
Value::KeyValue(KeyType::Negative(-23)),
),
(KeyType::Unsigned(4), Value::KeyValue(KeyType::Unsigned(56))),
(
KeyType::TextString(String::from("foo")),
Value::Simple(SimpleValue::TrueValue),
),
(
KeyType::ByteString(b"bar".to_vec()),
Value::Simple(SimpleValue::NullValue),
),
(
KeyType::Unsigned(5),
Value::KeyValue(KeyType::TextString(String::from("foo"))),
),
(
KeyType::Unsigned(6),
Value::KeyValue(KeyType::ByteString(b"bar".to_vec())),
),
(KeyType::Unsigned(7), Value::Array(Vec::new())),
(
KeyType::Unsigned(8),
Value::Array(vec![
Value::KeyValue(KeyType::Unsigned(0)),
Value::KeyValue(KeyType::Unsigned(1)),
]),
),
(KeyType::Unsigned(9), Value::Map(BTreeMap::new())),
(
KeyType::Unsigned(10),
Value::Map(
[(KeyType::Unsigned(2), Value::KeyValue(KeyType::Unsigned(3)))]
.iter()
.cloned()
.collect(),
),
),
]
.iter()
.cloned()
.collect(),
);
assert_eq!(a, b);
}
#[test]
fn test_cbor_map_btree_empty() {
let a = cbor_map_btree!(BTreeMap::new());
let b = Value::Map(BTreeMap::new());
assert_eq!(a, b);
}
#[test]
fn test_cbor_map_btree_foo() {
let a = cbor_map_btree!(
[(KeyType::Unsigned(2), Value::KeyValue(KeyType::Unsigned(3)))]
.iter()
.cloned()
.collect()
);
let b = Value::Map(
[(KeyType::Unsigned(2), Value::KeyValue(KeyType::Unsigned(3)))]
.iter()
.cloned()
.collect(),
);
assert_eq!(a, b);
}
}

View File

@@ -0,0 +1,811 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use super::values::{Constants, KeyType, SimpleValue, Value};
use alloc::collections::BTreeMap;
use alloc::str;
use alloc::vec::Vec;
#[derive(Debug, PartialEq)]
pub enum DecoderError {
UnsupportedMajorType,
UnknownAdditionalInfo,
IncompleteCborData,
IncorrectMapKeyType,
TooMuchNesting,
InvalidUtf8,
ExtranousData,
OutOfOrderKey,
NonMinimalCborEncoding,
UnsupportedSimpleValue,
UnsupportedFloatingPointValue,
OutOfRangeIntegerValue,
}
pub fn read(encoded_cbor: &[u8]) -> Result<Value, DecoderError> {
let mut reader = Reader::new(encoded_cbor);
let value = reader.decode_complete_data_item(Reader::MAX_NESTING_DEPTH)?;
if !reader.remaining_cbor.is_empty() {
return Err(DecoderError::ExtranousData);
}
Ok(value)
}
struct Reader<'a> {
remaining_cbor: &'a [u8],
}
impl<'a> Reader<'a> {
const MAX_NESTING_DEPTH: i8 = 4;
pub fn new(cbor: &'a [u8]) -> Reader<'a> {
Reader {
remaining_cbor: cbor,
}
}
pub fn decode_complete_data_item(
&mut self,
remaining_depth: i8,
) -> Result<Value, DecoderError> {
if remaining_depth < 0 {
return Err(DecoderError::TooMuchNesting);
}
match self.read_bytes(1) {
Some([first_byte]) => {
// Unsigned byte means logical shift, so only zeros get shifted in.
let major_type_value = first_byte >> Constants::MAJOR_TYPE_BIT_SHIFT;
let additional_info = first_byte & Constants::ADDITIONAL_INFORMATION_MASK;
let size_result = self.read_variadic_length_integer(additional_info);
match size_result {
Ok(size_value) => match major_type_value {
0 => self.decode_value_to_unsigned(size_value),
1 => self.decode_value_to_negative(size_value),
2 => self.read_byte_string_content(size_value),
3 => self.read_text_string_content(size_value),
4 => self.read_array_content(size_value, remaining_depth),
5 => self.read_map_content(size_value, remaining_depth),
7 => self.decode_to_simple_value(size_value, additional_info),
_ => Err(DecoderError::UnsupportedMajorType),
},
Err(decode_error) => Err(decode_error),
}
}
_ => Err(DecoderError::IncompleteCborData),
}
}
fn read_bytes(&mut self, num_bytes: usize) -> Option<&[u8]> {
if num_bytes > self.remaining_cbor.len() {
None
} else {
let (left, right) = self.remaining_cbor.split_at(num_bytes);
self.remaining_cbor = right;
Some(left)
}
}
fn read_variadic_length_integer(&mut self, additional_info: u8) -> Result<u64, DecoderError> {
let additional_bytes_num = match additional_info {
0..=Constants::ADDITIONAL_INFORMATION_MAX_INT => return Ok(additional_info as u64),
Constants::ADDITIONAL_INFORMATION_1_BYTE => 1,
Constants::ADDITIONAL_INFORMATION_2_BYTES => 2,
Constants::ADDITIONAL_INFORMATION_4_BYTES => 4,
Constants::ADDITIONAL_INFORMATION_8_BYTES => 8,
_ => return Err(DecoderError::UnknownAdditionalInfo),
};
match self.read_bytes(additional_bytes_num) {
Some(bytes) => {
let mut size_value = 0u64;
for byte in bytes {
size_value <<= 8;
size_value += *byte as u64;
}
if (additional_bytes_num == 1 && size_value < 24)
|| size_value < (1u64 << (8 * (additional_bytes_num >> 1)))
{
Err(DecoderError::NonMinimalCborEncoding)
} else {
Ok(size_value)
}
}
None => Err(DecoderError::IncompleteCborData),
}
}
fn decode_value_to_unsigned(&self, size_value: u64) -> Result<Value, DecoderError> {
Ok(cbor_unsigned!(size_value))
}
fn decode_value_to_negative(&self, size_value: u64) -> Result<Value, DecoderError> {
let signed_size = size_value as i64;
if signed_size < 0 {
Err(DecoderError::OutOfRangeIntegerValue)
} else {
Ok(Value::KeyValue(KeyType::Negative(-(size_value as i64) - 1)))
}
}
fn read_byte_string_content(&mut self, size_value: u64) -> Result<Value, DecoderError> {
match self.read_bytes(size_value as usize) {
Some(bytes) => Ok(cbor_bytes_lit!(bytes)),
None => Err(DecoderError::IncompleteCborData),
}
}
fn read_text_string_content(&mut self, size_value: u64) -> Result<Value, DecoderError> {
match self.read_bytes(size_value as usize) {
Some(bytes) => match str::from_utf8(bytes) {
Ok(s) => Ok(cbor_text!(s)),
Err(_) => Err(DecoderError::InvalidUtf8),
},
None => Err(DecoderError::IncompleteCborData),
}
}
fn read_array_content(
&mut self,
size_value: u64,
remaining_depth: i8,
) -> Result<Value, DecoderError> {
// Don't set the capacity already, it is an unsanitized input.
let mut value_array = Vec::new();
for _ in 0..size_value {
value_array.push(self.decode_complete_data_item(remaining_depth - 1)?);
}
Ok(cbor_array_vec!(value_array))
}
fn read_map_content(
&mut self,
size_value: u64,
remaining_depth: i8,
) -> Result<Value, DecoderError> {
let mut value_map = BTreeMap::new();
let mut last_key_option = None;
for _ in 0..size_value {
let key_value = self.decode_complete_data_item(remaining_depth - 1)?;
if let Value::KeyValue(key) = key_value {
if let Some(last_key) = last_key_option {
if last_key >= key {
return Err(DecoderError::OutOfOrderKey);
}
}
last_key_option = Some(key.clone());
value_map.insert(key, self.decode_complete_data_item(remaining_depth - 1)?);
} else {
return Err(DecoderError::IncorrectMapKeyType);
}
}
Ok(cbor_map_btree!(value_map))
}
fn decode_to_simple_value(
&self,
size_value: u64,
additional_info: u8,
) -> Result<Value, DecoderError> {
if additional_info > Constants::ADDITIONAL_INFORMATION_MAX_INT
&& additional_info != Constants::ADDITIONAL_INFORMATION_1_BYTE
{
// TODO(kaczmarczyck) the chromium C++ reference allows equality to 24 here, why?
// Also, why not just disallow ANY additional_info != size_value?
return Err(DecoderError::UnsupportedFloatingPointValue);
}
match SimpleValue::from_integer(size_value) {
Some(simple_value) => Ok(Value::Simple(simple_value)),
None => Err(DecoderError::UnsupportedSimpleValue),
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_read_unsigned() {
let cases = vec![
(0, vec![0x00]),
(1, vec![0x01]),
(10, vec![0x0A]),
(23, vec![0x17]),
(24, vec![0x18, 0x18]),
(255, vec![0x18, 0xFF]),
(256, vec![0x19, 0x01, 0x00]),
(65535, vec![0x19, 0xFF, 0xFF]),
(65536, vec![0x1A, 0x00, 0x01, 0x00, 0x00]),
(0xFFFFFFFF, vec![0x1A, 0xFF, 0xFF, 0xFF, 0xFF]),
(
0x100000000,
vec![0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00],
),
(
std::i64::MAX,
vec![0x1B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
),
];
for (unsigned, mut cbor) in cases {
assert_eq!(read(&cbor), Ok(cbor_int!(unsigned)));
cbor.push(0x01);
assert_eq!(read(&cbor), Err(DecoderError::ExtranousData));
}
}
#[test]
fn test_read_unsigned_non_minimum_byte_length() {
let encodings = vec![
// Uint 23 encoded with 1 byte.
vec![0x18, 0x17],
// Uint 255 encoded with 2 bytes.
vec![0x19, 0x00, 0xff],
// Uint 65535 encoded with 4 bytes.
vec![0x1a, 0x00, 0x00, 0xff, 0xff],
// Uint 4294967295 encoded with 8 bytes.
vec![0x1b, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff],
// When decoding byte has more than one syntax error, the first syntax
// error encountered during deserialization is returned as the error code.
vec![
0xa2, // map with non-minimally encoded key
0x17, // key 24
0x61, 0x42, // value :"B"
0x18, 0x17, // key 23 encoded with extra byte
0x61, 0x45, // value "E"
],
vec![
0xa2, // map with out of order and non-minimally encoded key
0x18, 0x17, // key 23 encoded with extra byte
0x61, 0x45, // value "E"
0x17, // key 23
0x61, 0x42, // value :"B"
],
vec![
0xa2, // map with duplicate non-minimally encoded key
0x18, 0x17, // key 23 encoded with extra byte
0x61, 0x45, // value "E"
0x18, 0x17, // key 23 encoded with extra byte
0x61, 0x42, // value :"B"
],
];
for encoding in encodings {
assert_eq!(read(&encoding), Err(DecoderError::NonMinimalCborEncoding));
}
}
#[test]
fn test_read_negative() {
let cases = vec![
(-1, vec![0x20]),
(-24, vec![0x37]),
(-25, vec![0x38, 0x18]),
(-256, vec![0x38, 0xFF]),
(-1000, vec![0x39, 0x03, 0xE7]),
(-1000000, vec![0x3A, 0x00, 0x0F, 0x42, 0x3F]),
(-4294967296, vec![0x3A, 0xFF, 0xFF, 0xFF, 0xFF]),
(
std::i64::MIN,
vec![0x3B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
),
];
for (negative, mut cbor) in cases {
assert_eq!(read(&cbor), Ok(cbor_int!(negative)));
cbor.push(0x01);
assert_eq!(read(&cbor), Err(DecoderError::ExtranousData));
}
}
#[test]
fn test_read_byte_string() {
let cases = vec![
(Vec::new(), vec![0x40]),
(
vec![0x01, 0x02, 0x03, 0x04],
vec![0x44, 0x01, 0x02, 0x03, 0x04],
),
];
for (byte_string, mut cbor) in cases {
assert_eq!(read(&cbor), Ok(cbor_bytes!(byte_string)));
cbor.push(0x01);
assert_eq!(read(&cbor), Err(DecoderError::ExtranousData));
}
}
#[test]
fn test_read_text_string() {
let unicode_3byte = vec![0xE6, 0xB0, 0xB4];
let cases = vec![
("", vec![0x60]),
("a", vec![0x61, 0x61]),
("IETF", vec![0x64, 0x49, 0x45, 0x54, 0x46]),
("\"\\", vec![0x62, 0x22, 0x5C]),
("ü", vec![0x62, 0xC3, 0xBC]),
(
std::str::from_utf8(&unicode_3byte).unwrap(),
vec![0x63, 0xE6, 0xB0, 0xB4],
),
("𐅑", vec![0x64, 0xF0, 0x90, 0x85, 0x91]),
];
for (text_string, mut cbor) in cases {
assert_eq!(read(&cbor), Ok(cbor_text!(text_string)));
cbor.push(0x01);
assert_eq!(read(&cbor), Err(DecoderError::ExtranousData));
}
}
#[test]
fn test_read_text_string_with_nul() {
let cases = vec![
(
"string_without_nul",
vec![
0x72, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x5F, 0x77, 0x69, 0x74, 0x68, 0x6F,
0x75, 0x74, 0x5F, 0x6E, 0x75, 0x6C,
],
),
(
"nul_terminated_string\0",
vec![
0x76, 0x6E, 0x75, 0x6C, 0x5F, 0x74, 0x65, 0x72, 0x6D, 0x69, 0x6E, 0x61, 0x74,
0x65, 0x64, 0x5F, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x00,
],
),
(
"embedded\0nul",
vec![
0x6C, 0x65, 0x6D, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x00, 0x6E, 0x75, 0x6C,
],
),
(
"trailing_nuls\0\0",
vec![
0x6F, 0x74, 0x72, 0x61, 0x69, 0x6C, 0x69, 0x6E, 0x67, 0x5F, 0x6E, 0x75, 0x6C,
0x73, 0x00, 0x00,
],
),
];
for (text_string, mut cbor) in cases {
assert_eq!(read(&cbor), Ok(cbor_text!(text_string)));
cbor.push(0x01);
assert_eq!(read(&cbor), Err(DecoderError::ExtranousData));
}
}
#[test]
fn test_read_text_string_with_invalid_byte_sequence_after_nul() {
assert_eq!(
read(&vec![0x63, 0x00, 0x00, 0xA6]),
Err(DecoderError::InvalidUtf8)
);
}
#[test]
fn test_read_array() {
let value_vec: Vec<_> = (1..26).collect();
let mut test_cbor = 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,
];
assert_eq!(read(&test_cbor.clone()), Ok(cbor_array_vec!(value_vec)));
test_cbor.push(0x01);
assert_eq!(read(&test_cbor), Err(DecoderError::ExtranousData));
}
#[test]
fn test_read_map() {
let value_map = cbor_map! {
24 => "abc",
"" => ".",
"b" => "B",
"aa" => "AA",
};
let mut test_cbor = vec![
0xa4, // map with 4 key value pairs:
0x18, 0x18, // 24
0x63, 0x61, 0x62, 0x63, // "abc"
0x60, // ""
0x61, 0x2e, // "."
0x61, 0x62, // "b"
0x61, 0x42, // "B"
0x62, 0x61, 0x61, // "aa"
0x62, 0x41, 0x41, // "AA"
];
assert_eq!(read(&test_cbor), Ok(value_map));
test_cbor.push(0x01);
assert_eq!(read(&test_cbor), Err(DecoderError::ExtranousData));
}
#[test]
fn test_read_map_with_unsigned_keys() {
let value_map = cbor_map! {
1 => "a",
9 => "b",
999 => "c",
1111 => "d",
};
let mut test_cbor = vec![
0xa4, // map with 4 key value pairs:
0x01, // key : 1
0x61, 0x61, // value : "a"
0x09, // key : 9
0x61, 0x62, // value : "b"
0x19, 0x03, 0xE7, // key : 999
0x61, 0x63, // value "c"
0x19, 0x04, 0x57, // key : 1111
0x61, 0x64, // value : "d"
];
assert_eq!(read(&test_cbor), Ok(value_map));
test_cbor.push(0x01);
assert_eq!(read(&test_cbor), Err(DecoderError::ExtranousData));
}
#[test]
fn test_read_map_with_negative_keys() {
let value_map = cbor_map! {
-1 => 1,
-2 => 2,
-100 => 3,
};
let mut test_cbor = vec![
0xA3, // map with 3 key value pairs
0x20, // key : -1
0x01, // value : 1
0x21, // key : -2
0x02, // value : 2
0x38, 0x63, // key : -100
0x03, // value : 3
];
assert_eq!(read(&test_cbor), Ok(value_map));
test_cbor.push(0x01);
assert_eq!(read(&test_cbor), Err(DecoderError::ExtranousData));
}
#[test]
fn test_read_map_with_array() {
let value_map = cbor_map! {
"a" => 1,
"b" => cbor_array![2, 3],
};
let mut test_cbor = vec![
0xa2, // map of 2 pairs
0x61, 0x61, // "a"
0x01, 0x61, 0x62, // "b"
0x82, // array with 2 elements
0x02, 0x03,
];
assert_eq!(read(&test_cbor), Ok(value_map));
test_cbor.push(0x01);
assert_eq!(read(&test_cbor), Err(DecoderError::ExtranousData));
}
#[test]
fn test_read_map_with_text_string_keys() {
let value_map = cbor_map! {
"k" => "v",
"foo" => "bar",
};
let mut test_cbor = vec![
0xa2, // map of 2 pairs
0x61, b'k', // text string "k"
0x61, b'v', 0x63, b'f', b'o', b'o', // text string "foo"
0x63, b'b', b'a', b'r',
];
assert_eq!(read(&test_cbor), Ok(value_map));
test_cbor.push(0x01);
assert_eq!(read(&test_cbor), Err(DecoderError::ExtranousData));
}
#[test]
fn test_read_map_with_byte_string_keys() {
let value_map = cbor_map! {
b"k" => b"v",
b"foo" => b"bar",
};
let mut test_cbor = vec![
0xa2, // map of 2 pairs
0x41, b'k', // text string "k"
0x41, b'v', 0x43, b'f', b'o', b'o', // text string "foo"
0x43, b'b', b'a', b'r',
];
assert_eq!(read(&test_cbor), Ok(value_map));
test_cbor.push(0x01);
assert_eq!(read(&test_cbor), Err(DecoderError::ExtranousData));
}
#[test]
fn test_read_nested_map() {
let value_map = cbor_map! {
"a" => 1,
"b" => cbor_map! {
"c" => 2,
"d" => 3,
},
};
let mut test_cbor = vec![
0xa2, // map of 2 pairs
0x61, 0x61, 0x01, // "a"
0x61, 0x62, // "b"
0xa2, // map of 2 pairs
0x61, 0x63, 0x02, // "c"
0x61, 0x64, 0x03, // "d"
];
assert_eq!(read(&test_cbor), Ok(value_map));
test_cbor.push(0x01);
assert_eq!(read(&test_cbor), Err(DecoderError::ExtranousData));
}
#[test]
fn test_read_integer_out_of_range() {
let cases = vec![
// The positive case is impossible since we support u64.
// vec![0x1B, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
vec![0x3B, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
];
for cbor in cases {
assert_eq!(read(&cbor), Err(DecoderError::OutOfRangeIntegerValue));
}
}
#[test]
fn test_read_simple_value() {
let cases = vec![
(cbor_false!(), vec![0xF4]),
(cbor_true!(), vec![0xF5]),
(cbor_null!(), vec![0xF6]),
(cbor_undefined!(), vec![0xF7]),
];
for (simple, mut cbor) in cases {
assert_eq!(read(&cbor.clone()), Ok(simple));
cbor.push(0x01);
assert_eq!(read(&cbor), Err(DecoderError::ExtranousData));
}
}
#[test]
fn test_read_unsupported_floating_point_numbers() {
let cases = vec![
vec![0xF9, 0x10, 0x00],
vec![0xFA, 0x10, 0x00, 0x00, 0x00],
vec![0xFB, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
];
for cbor in cases {
assert_eq!(
read(&cbor),
Err(DecoderError::UnsupportedFloatingPointValue)
);
}
}
#[test]
fn test_read_incomplete_cbor_data_error() {
let cases = vec![
vec![0x19, 0x03],
vec![0x44, 0x01, 0x02, 0x03],
vec![0x65, 0x49, 0x45, 0x54, 0x46],
vec![0x82, 0x02],
vec![0xA2, 0x61, 0x61, 0x01],
vec![0x18],
vec![0x99],
vec![0xBA],
vec![0x5B],
vec![0x3B],
vec![0x99, 0x01],
vec![0xBA, 0x01, 0x02, 0x03],
vec![0x3B, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07],
];
for cbor in cases {
assert_eq!(read(&cbor), Err(DecoderError::IncompleteCborData));
}
}
#[test]
fn test_read_unsupported_map_key_format_error() {
// While CBOR can handle all types as map keys, we only support a subset.
let bad_map_cbor = vec![
0xa2, // map of 2 pairs
0x82, 0x01, 0x02, // invalid key : [1, 2]
0x02, // value : 2
0x61, 0x64, // key : "d"
0x03, // value : 3
];
assert_eq!(read(&bad_map_cbor), Err(DecoderError::IncorrectMapKeyType));
}
#[test]
fn test_read_unknown_additional_info_error() {
let cases = vec![
vec![0x7C, 0x49, 0x45, 0x54, 0x46],
vec![0x7D, 0x22, 0x5C],
vec![0x7E, 0xC3, 0xBC],
vec![0x7F, 0xE6, 0xB0, 0xB4],
vec![0xFC],
vec![0xFD],
vec![0xFE],
vec![0xFF],
];
for cbor in cases {
assert_eq!(read(&cbor), Err(DecoderError::UnknownAdditionalInfo));
}
}
#[test]
fn test_read_too_much_nesting_error() {
let cases = vec![
vec![0x18, 0x64],
vec![0x44, 0x01, 0x02, 0x03, 0x04],
vec![0x64, 0x49, 0x45, 0x54, 0x46],
vec![0x80],
vec![0xA0],
];
for cbor in cases {
let mut reader = Reader::new(&cbor);
assert!(reader.decode_complete_data_item(0).is_ok());
}
let map_cbor = vec![
0xa2, // map of 2 pairs
0x61, 0x61, // "a"
0x01, 0x61, 0x62, // "b"
0x82, // array with 2 elements
0x02, 0x03,
];
let mut reader = Reader::new(&map_cbor);
assert_eq!(
reader.decode_complete_data_item(1),
Err(DecoderError::TooMuchNesting)
);
reader = Reader::new(&map_cbor);
assert!(reader.decode_complete_data_item(2).is_ok());
}
#[test]
fn test_read_out_of_order_key_error() {
let cases = vec![
vec![
0xa2, // map with 2 keys with same major type and length
0x61, 0x62, // key "b"
0x61, 0x42, // value "B"
0x61, 0x61, // key "a" (out of order byte-wise lexically)
0x61, 0x45, // value "E"
],
vec![
0xa2, // map with 2 keys with different major type
0x61, 0x62, // key "b"
0x02, // value 2
// key 1000 (out of order since lower major type sorts first)
0x19, 0x03, 0xe8, 0x61, 0x61, // value a
],
vec![
0xa2, // map with 2 keys with same major type
0x19, 0x03, 0xe8, // key 1000 (out of order due to longer length)
0x61, 0x61, //value "a"
0x0a, // key 10
0x61, 0x62, // value "b"
],
vec![
0xa2, // map with 2 text string keys
0x62, b'a', b'a', // key text string "aa"
// (out of order due to longer length)
0x02, 0x61, b'b', // key "b"
0x01,
],
vec![
0xa2, // map with 2 byte string keys
0x42, b'x', b'x', // key byte string "xx"
// (out of order due to longer length)
0x02, 0x41, b'y', // key byte string "y"
0x01,
],
];
for cbor in cases {
assert_eq!(read(&cbor), Err(DecoderError::OutOfOrderKey));
}
}
#[test]
fn test_read_duplicate_key_error() {
let map_with_duplicate_key = vec![
0xa6, // map of 6 pairs:
0x60, // ""
0x61, 0x2e, // "."
0x61, 0x62, // "b"
0x61, 0x42, // "B"
0x61, 0x62, // "b" (Duplicate key)
0x61, 0x43, // "C"
0x61, 0x64, // "d"
0x61, 0x44, // "D"
0x61, 0x65, // "e"
0x61, 0x44, // "D"
0x62, 0x61, 0x61, // "aa"
0x62, 0x41, 0x41, // "AA"
];
assert_eq!(
read(&map_with_duplicate_key),
Err(DecoderError::OutOfOrderKey)
);
}
#[test]
fn test_read_incorrect_string_encoding_error() {
let cases = vec![
vec![0x63, 0xED, 0x9F, 0xBF],
vec![0x63, 0xEE, 0x80, 0x80],
vec![0x63, 0xEF, 0xBF, 0xBD],
];
for cbor in cases {
assert!(read(&cbor).is_ok());
}
let impossible_utf_byte = vec![0x64, 0xFE, 0xFE, 0xFF, 0xFF];
assert_eq!(read(&impossible_utf_byte), Err(DecoderError::InvalidUtf8));
}
#[test]
fn test_read_extranous_cbor_data_error() {
let cases = vec![
vec![0x19, 0x03, 0x05, 0x00],
vec![0x44, 0x01, 0x02, 0x03, 0x04, 0x00],
vec![0x64, 0x49, 0x45, 0x54, 0x46, 0x00],
vec![0x82, 0x01, 0x02, 0x00],
vec![0xa1, 0x61, 0x63, 0x02, 0x61, 0x64, 0x03],
];
for cbor in cases {
assert_eq!(read(&cbor), Err(DecoderError::ExtranousData));
}
}
#[test]
fn test_read_unsupported_simple_type() {
let cases = vec![
vec![0xE0],
vec![0xF3],
vec![0xF8, 0x18],
vec![0xF8, 0x1C],
vec![0xF8, 0x1D],
vec![0xF8, 0x1E],
vec![0xF8, 0x1F],
vec![0xF8, 0x20],
vec![0xF8, 0xFF],
];
for cbor in cases {
assert_eq!(read(&cbor), Err(DecoderError::UnsupportedSimpleValue));
}
}
#[test]
fn test_read_super_long_content_dont_crash() {
let cases = vec![
vec![0x9B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
vec![0xBB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
];
for cbor in cases {
assert_eq!(read(&cbor), Err(DecoderError::IncompleteCborData));
}
}
#[test]
fn test_read_unsupported_major_type() {
let cases = vec![
vec![0xC0],
vec![0xD8, 0xFF],
// multi-dimensional array example using tags
vec![
0x82, 0x82, 0x02, 0x03, 0xd8, 0x41, 0x4a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
0x03, 0x00, 0x04, 0x00, 0x05,
],
];
for cbor in cases {
assert_eq!(read(&cbor), Err(DecoderError::UnsupportedMajorType));
}
}
}

View File

@@ -0,0 +1,268 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use alloc::collections::BTreeMap;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use core::cmp::Ordering;
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
KeyValue(KeyType),
Array(Vec<Value>),
Map(BTreeMap<KeyType, Value>),
// TAG is omitted
Simple(SimpleValue),
}
// The specification recommends to limit the available keys.
// Currently supported are both integer and string types.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum KeyType {
Unsigned(u64),
// We only use 63 bits of information here.
Negative(i64),
ByteString(Vec<u8>),
TextString(String),
}
#[derive(Clone, Debug, PartialEq)]
pub enum SimpleValue {
FalseValue = 20,
TrueValue = 21,
NullValue = 22,
Undefined = 23,
}
pub struct Constants {}
impl Constants {
pub const MAJOR_TYPE_BIT_SHIFT: u8 = 5;
pub const ADDITIONAL_INFORMATION_MASK: u8 = 0x1F;
pub const ADDITIONAL_INFORMATION_MAX_INT: u8 = 23;
pub const ADDITIONAL_INFORMATION_1_BYTE: u8 = 24;
pub const ADDITIONAL_INFORMATION_2_BYTES: u8 = 25;
pub const ADDITIONAL_INFORMATION_4_BYTES: u8 = 26;
pub const ADDITIONAL_INFORMATION_8_BYTES: u8 = 27;
}
impl Value {
pub fn bool_value(b: bool) -> Value {
if b {
Value::Simple(SimpleValue::TrueValue)
} else {
Value::Simple(SimpleValue::FalseValue)
}
}
pub fn type_label(&self) -> u8 {
match self {
Value::KeyValue(key) => key.type_label(),
Value::Array(_) => 4,
Value::Map(_) => 5,
Value::Simple(_) => 7,
}
}
}
impl KeyType {
// For simplicity, this only takes i64. Construct directly for the last bit.
pub fn integer(int: i64) -> KeyType {
if int >= 0 {
KeyType::Unsigned(int as u64)
} else {
KeyType::Negative(int)
}
}
pub fn type_label(&self) -> u8 {
match self {
KeyType::Unsigned(_) => 0,
KeyType::Negative(_) => 1,
KeyType::ByteString(_) => 2,
KeyType::TextString(_) => 3,
}
}
}
impl Ord for KeyType {
fn cmp(&self, other: &KeyType) -> Ordering {
use super::values::KeyType::{ByteString, Negative, TextString, Unsigned};
let self_type_value = self.type_label();
let other_type_value = other.type_label();
if self_type_value != other_type_value {
return self_type_value.cmp(&other_type_value);
}
match (self, other) {
(Unsigned(u1), Unsigned(u2)) => u1.cmp(u2),
(Negative(n1), Negative(n2)) => n1.cmp(n2).reverse(),
(ByteString(b1), ByteString(b2)) => b1.len().cmp(&b2.len()).then(b1.cmp(b2)),
(TextString(t1), TextString(t2)) => t1.len().cmp(&t2.len()).then(t1.cmp(t2)),
_ => unreachable!(),
}
}
}
impl PartialOrd for KeyType {
fn partial_cmp(&self, other: &KeyType) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl SimpleValue {
pub fn from_integer(int: u64) -> Option<SimpleValue> {
match int {
20 => Some(SimpleValue::FalseValue),
21 => Some(SimpleValue::TrueValue),
22 => Some(SimpleValue::NullValue),
23 => Some(SimpleValue::Undefined),
_ => None,
}
}
}
impl From<u64> for KeyType {
fn from(unsigned: u64) -> Self {
KeyType::Unsigned(unsigned)
}
}
impl From<i64> for KeyType {
fn from(i: i64) -> Self {
KeyType::integer(i)
}
}
impl From<i32> for KeyType {
fn from(i: i32) -> Self {
KeyType::integer(i as i64)
}
}
impl From<Vec<u8>> for KeyType {
fn from(bytes: Vec<u8>) -> Self {
KeyType::ByteString(bytes)
}
}
impl From<&[u8]> for KeyType {
fn from(bytes: &[u8]) -> Self {
KeyType::ByteString(bytes.to_vec())
}
}
impl From<String> for KeyType {
fn from(text: String) -> Self {
KeyType::TextString(text)
}
}
impl From<&str> for KeyType {
fn from(text: &str) -> Self {
KeyType::TextString(text.to_string())
}
}
impl<T> From<T> for Value
where
KeyType: From<T>,
{
fn from(t: T) -> Self {
Value::KeyValue(KeyType::from(t))
}
}
impl From<bool> for Value {
fn from(b: bool) -> Self {
Value::bool_value(b)
}
}
pub trait IntoCborKey {
fn into_cbor_key(self) -> KeyType;
}
impl<T> IntoCborKey for T
where
KeyType: From<T>,
{
fn into_cbor_key(self) -> KeyType {
KeyType::from(self)
}
}
pub trait IntoCborValue {
fn into_cbor_value(self) -> Value;
}
impl<T> IntoCborValue for T
where
Value: From<T>,
{
fn into_cbor_value(self) -> Value {
Value::from(self)
}
}
pub trait IntoCborValueOption {
fn into_cbor_value_option(self) -> Option<Value>;
}
impl<T> IntoCborValueOption for T
where
Value: From<T>,
{
fn into_cbor_value_option(self) -> Option<Value> {
Some(Value::from(self))
}
}
impl<T> IntoCborValueOption for Option<T>
where
Value: From<T>,
{
fn into_cbor_value_option(self) -> Option<Value> {
self.map(Value::from)
}
}
#[cfg(test)]
mod test {
#[test]
fn test_key_type_ordering() {
assert!(cbor_key_int!(0) < cbor_key_int!(23));
assert!(cbor_key_int!(23) < cbor_key_int!(24));
assert!(cbor_key_int!(24) < cbor_key_int!(1000));
assert!(cbor_key_int!(1000) < cbor_key_int!(1000000));
assert!(cbor_key_int!(1000000) < cbor_key_int!(std::i64::MAX));
assert!(cbor_key_int!(std::i64::MAX) < cbor_key_int!(-1));
assert!(cbor_key_int!(-1) < cbor_key_int!(-23));
assert!(cbor_key_int!(-23) < cbor_key_int!(-24));
assert!(cbor_key_int!(-24) < cbor_key_int!(-1000));
assert!(cbor_key_int!(-1000) < cbor_key_int!(-1000000));
assert!(cbor_key_int!(-1000000) < cbor_key_int!(std::i64::MIN));
assert!(cbor_key_int!(std::i64::MIN) < cbor_key_bytes!(vec![]));
assert!(cbor_key_bytes!(vec![]) < cbor_key_bytes!(vec![0x00]));
assert!(cbor_key_bytes!(vec![0x00]) < cbor_key_bytes!(vec![0x01]));
assert!(cbor_key_bytes!(vec![0x01]) < cbor_key_bytes!(vec![0xFF]));
assert!(cbor_key_bytes!(vec![0xFF]) < cbor_key_bytes!(vec![0x00, 0x00]));
assert!(cbor_key_bytes!(vec![0x00, 0x00]) < cbor_key_text!(""));
assert!(cbor_key_text!("") < cbor_key_text!("a"));
assert!(cbor_key_text!("a") < cbor_key_text!("b"));
assert!(cbor_key_text!("b") < cbor_key_text!("aa"));
assert!(cbor_key_int!(1) < cbor_key_bytes!(vec![0x00]));
assert!(cbor_key_int!(1) < cbor_key_text!("s"));
assert!(cbor_key_int!(-1) < cbor_key_text!("s"));
}
}

View File

@@ -0,0 +1,429 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use super::values::{Constants, KeyType, Value};
use alloc::vec::Vec;
pub fn write(value: Value, encoded_cbor: &mut Vec<u8>) -> bool {
let mut writer = Writer::new(encoded_cbor);
writer.encode_cbor(value, Writer::MAX_NESTING_DEPTH)
}
struct Writer<'a> {
encoded_cbor: &'a mut Vec<u8>,
}
impl<'a> Writer<'a> {
const MAX_NESTING_DEPTH: i8 = 4;
pub fn new(encoded_cbor: &mut Vec<u8>) -> Writer {
Writer { encoded_cbor }
}
fn encode_cbor(&mut self, value: Value, remaining_depth: i8) -> bool {
if remaining_depth < 0 {
return false;
}
match value {
Value::KeyValue(KeyType::Unsigned(unsigned)) => self.start_item(0, unsigned as u64),
Value::KeyValue(KeyType::Negative(negative)) => {
self.start_item(1, -(negative + 1) as u64)
}
Value::KeyValue(KeyType::ByteString(byte_string)) => {
self.start_item(2, byte_string.len() as u64);
self.encoded_cbor.extend(byte_string);
}
Value::KeyValue(KeyType::TextString(text_string)) => {
self.start_item(3, text_string.len() as u64);
self.encoded_cbor.extend(text_string.into_bytes());
}
Value::Array(array) => {
self.start_item(4, array.len() as u64);
for el in array {
if !self.encode_cbor(el, remaining_depth - 1) {
return false;
}
}
}
Value::Map(map) => {
self.start_item(5, map.len() as u64);
for (k, v) in map {
if !self.encode_cbor(Value::KeyValue(k), remaining_depth - 1) {
return false;
}
if !self.encode_cbor(v, remaining_depth - 1) {
return false;
}
}
}
Value::Simple(simple_value) => self.start_item(7, simple_value as u64),
}
true
}
fn start_item(&mut self, type_label: u8, size: u64) {
let (mut first_byte, shift) = match size {
0..=23 => (size as u8, 0),
24..=0xFF => (Constants::ADDITIONAL_INFORMATION_1_BYTE, 1),
0x100..=0xFFFF => (Constants::ADDITIONAL_INFORMATION_2_BYTES, 2),
0x10000..=0xFFFF_FFFF => (Constants::ADDITIONAL_INFORMATION_4_BYTES, 4),
_ => (Constants::ADDITIONAL_INFORMATION_8_BYTES, 8),
};
first_byte |= type_label << Constants::MAJOR_TYPE_BIT_SHIFT;
self.encoded_cbor.push(first_byte);
for i in (0..shift).rev() {
self.encoded_cbor.push((size >> (i * 8)) as u8);
}
}
}
#[cfg(test)]
mod test {
use super::*;
fn write_return(value: Value) -> Option<Vec<u8>> {
let mut encoded_cbor = Vec::new();
if write(value, &mut encoded_cbor) {
Some(encoded_cbor)
} else {
None
}
}
#[test]
fn test_write_unsigned() {
let cases = vec![
(0, vec![0x00]),
(1, vec![0x01]),
(10, vec![0x0A]),
(23, vec![0x17]),
(24, vec![0x18, 0x18]),
(25, vec![0x18, 0x19]),
(100, vec![0x18, 0x64]),
(1000, vec![0x19, 0x03, 0xE8]),
(1000000, vec![0x1A, 0x00, 0x0F, 0x42, 0x40]),
(0xFFFFFFFF, vec![0x1A, 0xFF, 0xFF, 0xFF, 0xFF]),
(
0x100000000,
vec![0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00],
),
(
std::i64::MAX,
vec![0x1B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
),
];
for (unsigned, correct_cbor) in cases {
assert_eq!(write_return(cbor_int!(unsigned)), Some(correct_cbor));
}
}
#[test]
fn test_write_negative() {
let cases = vec![
(-1, vec![0x20]),
(-10, vec![0x29]),
(-23, vec![0x36]),
(-24, vec![0x37]),
(-25, vec![0x38, 0x18]),
(-100, vec![0x38, 0x63]),
(-1000, vec![0x39, 0x03, 0xE7]),
(-4294967296, vec![0x3A, 0xFF, 0xFF, 0xFF, 0xFF]),
(
-4294967297,
vec![0x3B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00],
),
(
std::i64::MIN,
vec![0x3B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
),
];
for (negative, correct_cbor) in cases {
assert_eq!(write_return(cbor_int!(negative)), Some(correct_cbor));
}
}
#[test]
fn test_write_byte_string() {
let cases = vec![
(vec![], vec![0x40]),
(
vec![0x01, 0x02, 0x03, 0x04],
vec![0x44, 0x01, 0x02, 0x03, 0x04],
),
];
for (byte_string, correct_cbor) in cases {
assert_eq!(write_return(cbor_bytes!(byte_string)), Some(correct_cbor));
}
}
#[test]
fn test_write_text_string() {
let unicode_3byte = vec![0xE6, 0xB0, 0xB4];
let cases = vec![
("", vec![0x60]),
("a", vec![0x61, 0x61]),
("IETF", vec![0x64, 0x49, 0x45, 0x54, 0x46]),
("\"\\", vec![0x62, 0x22, 0x5C]),
("ü", vec![0x62, 0xC3, 0xBC]),
(
std::str::from_utf8(&unicode_3byte).unwrap(),
vec![0x63, 0xE6, 0xB0, 0xB4],
),
("𐅑", vec![0x64, 0xF0, 0x90, 0x85, 0x91]),
];
for (text_string, correct_cbor) in cases {
assert_eq!(write_return(cbor_text!(text_string)), Some(correct_cbor));
}
}
#[test]
fn test_write_array() {
let value_vec: Vec<_> = (1..26).collect();
let expected_cbor = vec![
0x98, 0x19, // array of 25 elements
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,
];
assert_eq!(
write_return(cbor_array_vec!(value_vec)),
Some(expected_cbor)
);
}
#[test]
fn test_write_map() {
let value_map = cbor_map! {
"aa" => "AA",
"e" => "E",
"" => ".",
-1 => "k",
-24 => "l",
-25 => "m",
-256 => "n",
-257 => "o",
-65537 => "p",
-4294967296_i64 => "q",
-4294967297_i64 => "r",
std::i64::MIN => "s",
b"a" => 2,
b"bar" => 3,
b"foo" => 4,
0 => "a",
23 => "b",
24 => "c",
std::u8::MAX as i64 => "d",
256 => "e",
std::u16::MAX as i64 => "f",
65536 => "g",
std::u32::MAX as i64 => "h",
4294967296_i64 => "i",
std::i64::MAX => "j",
};
let expected_cbor = vec![
0xb8, 0x19, // map of 25 pairs:
0x00, // key 0
0x61, 0x61, // value "a"
0x17, // key 23
0x61, 0x62, // value "b"
0x18, 0x18, // key 24
0x61, 0x63, // value "c"
0x18, 0xFF, // key 255
0x61, 0x64, // value "d"
0x19, 0x01, 0x00, // key 256
0x61, 0x65, // value "e"
0x19, 0xFF, 0xFF, // key 65535
0x61, 0x66, // value "f"
0x1A, 0x00, 0x01, 0x00, 0x00, // key 65536
0x61, 0x67, // value "g"
0x1A, 0xFF, 0xFF, 0xFF, 0xFF, // key 4294967295
0x61, 0x68, // value "h"
// key 4294967296
0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x61, 0x69, // value "i"
// key INT64_MAX
0x1b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x61, 0x6a, // value "j"
0x20, // key -1
0x61, 0x6b, // value "k"
0x37, // key -24
0x61, 0x6c, // value "l"
0x38, 0x18, // key -25
0x61, 0x6d, // value "m"
0x38, 0xFF, // key -256
0x61, 0x6e, // value "n"
0x39, 0x01, 0x00, // key -257
0x61, 0x6f, // value "o"
0x3A, 0x00, 0x01, 0x00, 0x00, // key -65537
0x61, 0x70, // value "p"
0x3A, 0xFF, 0xFF, 0xFF, 0xFF, // key -4294967296
0x61, 0x71, // value "q"
// key -4294967297
0x3B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x61, 0x72, // value "r"
// key INT64_MIN
0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x61, 0x73, // value "s"
0x41, b'a', // byte string "a"
0x02, 0x43, b'b', b'a', b'r', // byte string "bar"
0x03, 0x43, b'f', b'o', b'o', // byte string "foo"
0x04, 0x60, // key ""
0x61, 0x2e, // value "."
0x61, 0x65, // key "e"
0x61, 0x45, // value "E"
0x62, 0x61, 0x61, // key "aa"
0x62, 0x41, 0x41, // value "AA"
];
assert_eq!(write_return(value_map), Some(expected_cbor));
}
#[test]
fn test_write_map_with_array() {
let value_map = cbor_map! {
"a" => 1,
"b" => cbor_array![2, 3],
};
let expected_cbor = vec![
0xa2, // map of 2 pairs
0x61, 0x61, // "a"
0x01, 0x61, 0x62, // "b"
0x82, // array with 2 elements
0x02, 0x03,
];
assert_eq!(write_return(value_map), Some(expected_cbor));
}
#[test]
fn test_write_nested_map() {
let value_map = cbor_map! {
"a" => 1,
"b" => cbor_map! {
"c" => 2,
"d" => 3,
},
};
let expected_cbor = vec![
0xa2, // map of 2 pairs
0x61, 0x61, // "a"
0x01, 0x61, 0x62, // "b"
0xa2, // map of 2 pairs
0x61, 0x63, // "c"
0x02, 0x61, 0x64, // "d"
0x03,
];
assert_eq!(write_return(value_map), Some(expected_cbor));
}
#[test]
fn test_write_simple() {
let cases = vec![
(cbor_false!(), vec![0xF4]),
(cbor_true!(), vec![0xF5]),
(cbor_null!(), vec![0xF6]),
(cbor_undefined!(), vec![0xF7]),
];
for (value, correct_cbor) in cases {
assert_eq!(write_return(value), Some(correct_cbor));
}
}
#[test]
fn test_write_single_levels() {
let simple_array: Value = cbor_array![2];
let simple_map: Value = cbor_map! {"b" => 3};
let positive_cases = vec![
(cbor_int!(1), 0),
(cbor_bytes!(vec![0x01, 0x02, 0x03, 0x04]), 0),
(cbor_text!("a"), 0),
(cbor_array![], 0),
(cbor_map! {}, 0),
(simple_array.clone(), 1),
(simple_map.clone(), 1),
];
let negative_cases = vec![(simple_array.clone(), 0), (simple_map.clone(), 0)];
for (value, level) in positive_cases {
let mut buf = Vec::new();
let mut writer = Writer::new(&mut buf);
assert!(writer.encode_cbor(value, level));
}
for (value, level) in negative_cases {
let mut buf = Vec::new();
let mut writer = Writer::new(&mut buf);
assert!(!writer.encode_cbor(value, level));
}
}
#[test]
fn test_write_nested_map_levels() {
let cbor_map: Value = cbor_map! {
"a" => 1,
"b" => cbor_map! {
"c" => 2,
"d" => 3,
},
};
let mut buf = Vec::new();
let mut writer = Writer::new(&mut buf);
assert!(writer.encode_cbor(cbor_map.clone(), 2));
writer = Writer::new(&mut buf);
assert!(!writer.encode_cbor(cbor_map, 1));
}
#[test]
fn test_write_unbalanced_nested_containers() {
let cbor_array: Value = cbor_array![
1,
2,
3,
cbor_map! {
"a" => 1,
"b" => cbor_map! {
"c" => 2,
"d" => 3,
},
},
];
let mut buf = Vec::new();
let mut writer = Writer::new(&mut buf);
assert!(writer.encode_cbor(cbor_array.clone(), 3));
writer = Writer::new(&mut buf);
assert!(!writer.encode_cbor(cbor_array, 2));
}
#[test]
fn test_write_overly_nested() {
let cbor_map: Value = cbor_map! {
"a" => 1,
"b" => cbor_map! {
"c" => 2,
"d" => 3,
"h" => cbor_map! {
"e" => 4,
"f" => 5,
"g" => cbor_array![
6,
7,
cbor_array![
8
]
],
},
},
};
let mut buf = Vec::new();
let mut writer = Writer::new(&mut buf);
assert!(writer.encode_cbor(cbor_map.clone(), 5));
writer = Writer::new(&mut buf);
assert!(!writer.encode_cbor(cbor_map, 4));
}
}