use super::values::{Constants, SimpleValue, Value};
use crate::{
cbor_array_vec, cbor_bytes_lit, cbor_map_collection, cbor_tagged, cbor_text, cbor_unsigned,
};
use alloc::str;
use alloc::vec::Vec;
#[derive(Debug, PartialEq)]
pub enum DecoderError {
UnsupportedMajorType,
UnknownAdditionalInfo,
IncompleteCborData,
TooMuchNesting,
InvalidUtf8,
ExtraneousData,
OutOfOrderKey,
NonMinimalCborEncoding,
UnsupportedSimpleValue,
UnsupportedFloatingPointValue,
OutOfRangeIntegerValue,
}
pub fn read(encoded_cbor: &[u8]) -> Result<Value, DecoderError> {
read_nested(encoded_cbor, None)
}
pub fn read_nested(encoded_cbor: &[u8], max_nest: Option<i8>) -> Result<Value, DecoderError> {
let mut reader = Reader::new(encoded_cbor);
let value = reader.decode_complete_data_item(max_nest)?;
if !reader.remaining_cbor.is_empty() {
return Err(DecoderError::ExtraneousData);
}
Ok(value)
}
struct Reader<'a> {
remaining_cbor: &'a [u8],
}
impl<'a> Reader<'a> {
pub fn new(cbor: &'a [u8]) -> Reader<'a> {
Reader {
remaining_cbor: cbor,
}
}
pub fn decode_complete_data_item(
&mut self,
remaining_depth: Option<i8>,
) -> Result<Value, DecoderError> {
if remaining_depth.map_or(false, |d| d < 0) {
return Err(DecoderError::TooMuchNesting);
}
match self.read_bytes(1) {
Some([first_byte]) => {
let major_type_value = first_byte >> Constants::MAJOR_TYPE_BIT_SHIFT;
let additional_info = first_byte & Constants::ADDITIONAL_INFORMATION_MASK;
let size_value = self.read_variadic_length_integer(additional_info)?;
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),
6 => self.read_tagged_content(size_value, remaining_depth),
7 => self.decode_to_simple_value(size_value, additional_info),
_ => Err(DecoderError::UnsupportedMajorType),
}
}
_ => 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::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: Option<i8>,
) -> Result<Value, DecoderError> {
let mut value_array = Vec::new();
for _ in 0..size_value {
value_array.push(self.decode_complete_data_item(remaining_depth.map(|d| d - 1))?);
}
Ok(cbor_array_vec!(value_array))
}
fn read_map_content(
&mut self,
size_value: u64,
remaining_depth: Option<i8>,
) -> Result<Value, DecoderError> {
let mut value_map = Vec::<(Value, Value)>::new();
for _ in 0..size_value {
let key = self.decode_complete_data_item(remaining_depth.map(|d| d - 1))?;
if let Some(last_item) = value_map.last() {
if last_item.0 >= key {
return Err(DecoderError::OutOfOrderKey);
}
}
value_map.push((
key,
self.decode_complete_data_item(remaining_depth.map(|d| d - 1))?,
));
}
Ok(cbor_map_collection!(value_map))
}
fn read_tagged_content(
&mut self,
tag_value: u64,
remaining_depth: Option<i8>,
) -> Result<Value, DecoderError> {
let inner_value = self.decode_complete_data_item(remaining_depth.map(|d| d - 1))?;
Ok(cbor_tagged!(tag_value, inner_value))
}
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
{
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::*;
use crate::{
cbor_array, cbor_bytes, cbor_false, cbor_int, cbor_map, cbor_null, cbor_true,
cbor_undefined,
};
use alloc::vec;
#[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],
),
(
core::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::ExtraneousData));
}
}
#[test]
fn test_read_unsigned_non_minimum_byte_length() {
let encodings = vec![
vec![0x18, 0x17],
vec![0x19, 0x00, 0xff],
vec![0x1a, 0x00, 0x00, 0xff, 0xff],
vec![0x1b, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff],
vec![
0xa2, 0x17, 0x61, 0x42, 0x18, 0x17, 0x61, 0x45, ],
vec![
0xa2, 0x18, 0x17, 0x61, 0x45, 0x17, 0x61, 0x42, ],
vec![
0xa2, 0x18, 0x17, 0x61, 0x45, 0x18, 0x17, 0x61, 0x42, ],
];
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]),
(
core::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::ExtraneousData));
}
}
#[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::ExtraneousData));
}
}
#[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]),
(
core::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::ExtraneousData));
}
}
#[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::ExtraneousData));
}
}
#[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::ExtraneousData));
}
#[test]
fn test_read_map() {
let value_map = cbor_map! {
24 => "abc",
"" => ".",
"b" => "B",
"aa" => "AA",
};
let mut test_cbor = vec![
0xa4, 0x18, 0x18, 0x63, 0x61, 0x62, 0x63, 0x60, 0x61, 0x2e, 0x61, 0x62, 0x61, 0x42, 0x62, 0x61, 0x61, 0x62, 0x41, 0x41, ];
assert_eq!(read(&test_cbor), Ok(value_map));
test_cbor.push(0x01);
assert_eq!(read(&test_cbor), Err(DecoderError::ExtraneousData));
}
#[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, 0x01, 0x61, 0x61, 0x09, 0x61, 0x62, 0x19, 0x03, 0xE7, 0x61, 0x63, 0x19, 0x04, 0x57, 0x61, 0x64, ];
assert_eq!(read(&test_cbor), Ok(value_map));
test_cbor.push(0x01);
assert_eq!(read(&test_cbor), Err(DecoderError::ExtraneousData));
}
#[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, 0x20, 0x01, 0x21, 0x02, 0x38, 0x63, 0x03, ];
assert_eq!(read(&test_cbor), Ok(value_map));
test_cbor.push(0x01);
assert_eq!(read(&test_cbor), Err(DecoderError::ExtraneousData));
}
#[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, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03,
];
assert_eq!(read(&test_cbor), Ok(value_map));
test_cbor.push(0x01);
assert_eq!(read(&test_cbor), Err(DecoderError::ExtraneousData));
}
#[test]
fn test_read_map_with_text_string_keys() {
let value_map = cbor_map! {
"k" => "v",
"foo" => "bar",
};
let mut test_cbor = vec![
0xa2, 0x61, b'k', 0x61, b'v', 0x63, b'f', b'o', b'o', 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::ExtraneousData));
}
#[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, 0x41, b'k', 0x41, b'v', 0x43, b'f', b'o', b'o', 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::ExtraneousData));
}
#[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, 0x61, 0x61, 0x01, 0x61, 0x62, 0xa2, 0x61, 0x63, 0x02, 0x61, 0x64, 0x03, ];
assert_eq!(read(&test_cbor), Ok(value_map));
test_cbor.push(0x01);
assert_eq!(read(&test_cbor), Err(DecoderError::ExtraneousData));
}
#[test]
fn test_read_tagged() {
let cases = vec![
(cbor_tagged!(6, cbor_int!(0x42)), vec![0xc6, 0x18, 0x42]),
(cbor_tagged!(1, cbor_true!()), vec![0xc1, 0xf5]),
(
cbor_tagged!(
1000,
cbor_map! {
"a" => 1,
"b" => cbor_array![2, 3],
}
),
vec![
0xd9, 0x03, 0xe8, 0xa2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03,
],
),
];
for (value, mut cbor) in cases {
assert_eq!(read(&cbor), Ok(value));
cbor.push(0x01);
assert_eq!(read(&cbor), Err(DecoderError::ExtraneousData));
}
}
#[test]
fn test_read_integer_out_of_range() {
let cases = vec![
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::ExtraneousData));
}
}
#[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_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(Some(0)).is_ok());
}
let map_cbor = vec![
0xa2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03,
];
let mut reader = Reader::new(&map_cbor);
assert_eq!(
reader.decode_complete_data_item(Some(1)),
Err(DecoderError::TooMuchNesting)
);
reader = Reader::new(&map_cbor);
assert!(reader.decode_complete_data_item(Some(2)).is_ok());
}
#[test]
fn test_read_out_of_order_key_error() {
let cases = vec![
vec![
0xa2, 0x61, 0x62, 0x61, 0x42, 0x61, 0x61, 0x61, 0x45, ],
vec![
0xa2, 0x61, 0x62, 0x02, 0x19, 0x03, 0xe8, 0x61, 0x61, ],
vec![
0xa2, 0x19, 0x03, 0xe8, 0x61, 0x61, 0x0a, 0x61, 0x62, ],
vec![
0xa2, 0x62, b'a', b'a', 0x02, 0x61, b'b', 0x01,
],
vec![
0xa2, 0x42, b'x', b'x', 0x02, 0x41, b'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, 0x60, 0x61, 0x2e, 0x61, 0x62, 0x61, 0x42, 0x61, 0x62, 0x61, 0x43, 0x61, 0x64, 0x61, 0x44, 0x61, 0x65, 0x61, 0x44, 0x62, 0x61, 0x61, 0x62, 0x41, 0x41, ];
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_extraneous_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::ExtraneousData));
}
}
#[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));
}
}
}