#![cfg(feature = "use_std")]
use std::convert::Infallible;
use anyhow::Context;
use cbor4ii::core::Value;
use cbor4ii::core::enc::{ self, Encode };
use cbor4ii::core::dec::{ self, Decode };
use cbor4ii::core::types;
use cbor4ii::core::utils::{ BufWriter, SliceReader };
#[test]
fn test_decode_value() {
macro_rules! test {
( @ $input:expr ) => {
let buf = data_encoding::BASE64.decode($input.as_bytes()).unwrap();
let mut reader = SliceReader::new(buf.as_slice());
let _ = Value::decode(&mut reader);
};
( $( $input:expr );* $( ; )? ) => {
$(
test!(@ $input );
)*
}
}
test!{
"ig==";
"eoY=";
"v6a/v6a/v7+/pq6urq6urq6urq6urq6urq6urq6urq6urq6urqaurq6urq6urq4krq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6uv7+mv7+/v6aurq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urr+/pr+/v7+mrq6urq6urq6urq6urq6urq6urq6urq6upq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6uQK6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urqSurq6urq6urq6urq6urq6urq6urq6urq6urq6uv7+uJa6urq6urq6urq6urq6urq6urq6urq6urq6urq6uv7+uJa6urq6urq6urq6urq6urq6uQK6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq5Arq6urq6urq6urq6urq6urq6urq6urq6urq5Arq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6upK6urq6urq6urq6urq6urq6urq6urq6urq6urq6/v64lrq6urq6urq6urq6urq6urq6urq6urq6urq6urq6/v64lrq6urq6urq6urq6urq6urq5Arq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urkCurq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6krq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6upq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6upK6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urqaurq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq5Arq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6upK6urq6urq6urq6urq6urq6urq6urq6urq6urq6mrq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq5Arq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6upK6urq6urq6urq6urq6urq6urq6urq6urq6urq6/v64lrq6urq6urq6urq6urq6urq6urq6urq6urq6urq6/v64lrq6urq6urq6urq6urq6urq5Arq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urkCurq6urq6urq6urq6urq6urq6urq6urq6urkCurq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6krq6urq6urq6urq6urq6urq6urq6urq6urq6urr+/riWurq6urq6urq6urq6urq6urq6urq6urq6urq6urr+/riWurq6urq6urq6urq6urq6urkCurq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6uQK6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urqSurq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6mrq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6krq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6upq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urkCurq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6krq6urq6urq6urq6urq6urq6urq6urq6urqSurq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6upK6urq6urq6urq6urq6urq6urq6urq6urq6urq6/v64lrq6urq6urq6urq6urq6urq6urq6urq6urq6urq6/v64lrq6urq6urq6urq6urq6urq5Arq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urkCurq6urq6urq6urq6urq6urq6urq6urq6urkCurq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6krq6urq6urq6urq6urq6urq6urq6urq6urq6urr+/riWurq6urq6urq6urq6urg0AAAAAAAAArq6urq6urr+/riWurq6urq6urq6urq6urq6urkCurq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6uQK6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urqSurq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6mrq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6krq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6upq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urkCurq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6krq6urq6urq6urq6urq6urq6urq6urq6urq6urr+/riWurq6urq6urq6urq6urq6urkCurq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6krq6urq6urq6vrq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urrCwsLCwsLCwsLCwsLCwsLCwsLCwrq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6upq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urkCurq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6/v64lrq6urq6urq6urq6urq6urq5Arq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6upK6urq6urq6ur66urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6wsLCwsLCwsLCwsLCwsLCwsLCwsK6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urqaurq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq5Arq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6upK6urq6urq6urq6urq6urq6urq6urq6urq6urq6/v64lrq6urq6urq6urq6urq6urq5Arq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6upK6urq6urq6ur66urq6urq6urq6urq6urq6urq6/v64lrq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6wsLCwsLCwsLCwsLCwsLCwsLCwsK6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urrCwsLCwsLCwsLCwsLCwsLCwsLCwsIQEAAAAgQCwsLCwsLCwsLCwsK6urq6urq6u";
"v/b29vYBAAAAAAAABPb29gn29vb29pkAEfb29vb29vb2f3///39//3//f/9//3//f/9//3//f///f/9//3//f/8ICAgICAgI9vf39wgICAgICAgI+EAKCgr39wv1CAgICCgILggItAgICAgICAgICAgAAACgAAgICAAICAgICAgI9vf39wgICAgICAgI+EAKCgr39wv1CAgICCgILggItAgICAgICAgICAgAAACgAAgICA=="
}
}
#[test]
fn test_decode_buf_segment() -> anyhow::Result<()> {
let mut writer = BufWriter::new(Vec::new());
types::UncheckedStr::unbounded(&mut writer)?;
"test".encode(&mut writer)?;
"test2".encode(&mut writer)?;
"test3".encode(&mut writer)?;
types::UncheckedStr::end(&mut writer)?;
let mut reader = SliceReader::new(writer.buffer());
let output = String::decode(&mut reader)?;
assert_eq!("testtest2test3", output);
Ok(())
}
#[test]
fn test_decode_bad_reader_buf() -> anyhow::Result<()> {
let mut writer = BufWriter::new(Vec::new());
"test".encode(&mut writer)?;
struct LongReader<'a>(&'a [u8]);
impl<'de> dec::Read<'de> for LongReader<'de> {
type Error = Infallible;
#[inline]
fn fill<'b>(&'b mut self, _want: usize) -> Result<dec::Reference<'de, 'b>, Self::Error> {
Ok(dec::Reference::Short(&self.0))
}
#[inline]
fn advance(&mut self, n: usize) {
let len = core::cmp::min(self.0.len(), n);
self.0 = &self.0[len..];
}
}
let mut buf = writer.into_inner();
buf.resize(1024, 0);
let mut reader = LongReader(&buf);
let output = String::decode(&mut reader)?;
assert_eq!("test", output);
Ok(())
}
#[test]
fn test_decode_array_map() -> anyhow::Result<()> {
// array bounded
let mut writer = BufWriter::new(Vec::new());
(&[0u32, 1, 2, 3, 4, 5][..]).encode(&mut writer)?;
let mut reader = SliceReader::new(writer.buffer());
let len = types::Array::len(&mut reader)?;
let len = len.context("expect len")?;
for i in 0..len {
let n = u64::decode(&mut reader)?;
assert_eq!(n, i as u64);
}
// map unbounded
let mut writer = BufWriter::new(Vec::new());
types::Map::unbounded(&mut writer)?;
for i in 0u64..6 {
i.encode(&mut writer)?;
}
types::Map::end(&mut writer)?;
let mut reader = SliceReader::new(writer.buffer());
let len = types::Map::len(&mut reader)?;
assert_eq!(len, None);
let mut count = 0u64;
while !dec::is_break(&mut reader)? {
let n = u64::decode(&mut reader)?;
assert_eq!(n, count);
count += 1;
}
Ok(())
}
#[test]
fn test_value_i128() -> anyhow::Result<()> {
#[inline]
fn strip_zero(input: &[u8]) -> &[u8] {
let pos = input.iter()
.position(|&n| n != 0x0)
.unwrap_or(input.len());
&input[pos..]
}
let n = u64::MAX as i128 + 99;
let mut writer = BufWriter::new(Vec::new());
Value::Integer(n).encode(&mut writer)?;
let mut reader = SliceReader::new(writer.buffer());
let value = Value::decode(&mut reader)?;
let int_bytes = n.to_be_bytes();
let int_bytes = strip_zero(&int_bytes);
assert_eq!(value, Value::Tag(2, Box::new(Value::Bytes(int_bytes.into()))));
Ok(())
}
#[test]
fn test_mut_ref_write_read() -> anyhow::Result<()> {
fn test_write_str<W: enc::Write>(mut writer: W, input: &str) {
input.encode(&mut writer).unwrap()
}
fn test_read_str<'de, R: dec::Read<'de>>(mut reader: R) -> &'de str {
<&str>::decode(&mut reader).unwrap()
}
let input = "123";
let mut writer = BufWriter::new(Vec::new());
test_write_str(&mut writer, input);
let mut reader = SliceReader::new(writer.buffer());
let output = test_read_str(&mut reader);
assert_eq!(input, output);
Ok(())
}
#[test]
fn test_regression_ignore_tag() {
let tag = Value::Tag(u64::MAX - 1, Box::new(Value::Text("hello world".into())));
let mut buf = BufWriter::new(Vec::new());
tag.encode(&mut buf).unwrap();
{
let mut reader = SliceReader::new(buf.buffer());
let tag2 = Value::decode(&mut reader).unwrap();
assert_eq!(tag, tag2);
}
{
let mut reader = SliceReader::new(buf.buffer());
let _ignored = dec::IgnoredAny::decode(&mut reader).unwrap();
}
}
#[test]
fn test_regression_min_i64() {
let mut buf = BufWriter::new(Vec::new());
i64::MIN.encode(&mut buf).unwrap();
let mut reader = SliceReader::new(buf.buffer());
let min_i64 = i64::decode(&mut reader).unwrap();
assert_eq!(min_i64, i64::MIN);
}
#[test]
fn test_regression_min_i128() {
let mut buf = BufWriter::new(Vec::new());
i128::MIN.encode(&mut buf).unwrap();
let mut reader = SliceReader::new(buf.buffer());
let min_i128 = i128::decode(&mut reader).unwrap();
assert_eq!(min_i128, i128::MIN);
}
#[test]
fn test_regression_max_neg_64_as_i128() {
let mut buf = BufWriter::new(Vec::new());
let max_neg_64 = -i128::from(u64::MAX) - 1;
max_neg_64.encode(&mut buf).unwrap();
assert_eq!(buf.buffer(), [0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
let mut reader = SliceReader::new(buf.buffer());
let decoded = i128::decode(&mut reader).unwrap();
assert_eq!(decoded, -18446744073709551616);
}
#[test]
fn test_max_neg_32_as_i64() {
let mut buf = BufWriter::new(Vec::new());
let max_neg_32 = -i64::from(u32::MAX) - 1;
max_neg_32.encode(&mut buf).unwrap();
assert_eq!(buf.buffer(), [0x3a, 0xff, 0xff, 0xff, 0xff]);
let mut reader = SliceReader::new(buf.buffer());
let decoded = i64::decode(&mut reader).unwrap();
assert_eq!(decoded, -4294967296);
}
#[test]
fn test_max_neg_16_as_i32() {
let mut buf = BufWriter::new(Vec::new());
let max_neg_16 = -i32::from(u16::MAX) - 1;
max_neg_16.encode(&mut buf).unwrap();
assert_eq!(buf.buffer(), [0x39, 0xff, 0xff]);
let mut reader = SliceReader::new(buf.buffer());
let decoded = i32::decode(&mut reader).unwrap();
assert_eq!(decoded, -65536);
}
#[test]
fn test_max_neg_8_as_i16() {
let mut buf = BufWriter::new(Vec::new());
let max_neg_8 = -i16::from(u8::MAX) - 1;
max_neg_8.encode(&mut buf).unwrap();
assert_eq!(buf.buffer(), [0x38, 0xff]);
let mut reader = SliceReader::new(buf.buffer());
let decoded = i16::decode(&mut reader).unwrap();
assert_eq!(decoded, -256);
}
#[test]
fn test_tag() {
let mut reader_tag_len1 = SliceReader::new(&[0xd8, 0x2a]);
let tag_len1 = types::Tag::tag(&mut reader_tag_len1).unwrap();
assert_eq!(tag_len1, 42);
let mut reader_tag_len2 = SliceReader::new(&[0xd9, 0x00, 0x2a]);
let tag_len2 = types::Tag::tag(&mut reader_tag_len2).unwrap();
assert_eq!(tag_len2, 42);
let mut reader_tag_len4 = SliceReader::new(&[0xda, 0x00, 0x00, 0x00, 0x2a]);
let tag_len4 = types::Tag::tag(&mut reader_tag_len4).unwrap();
assert_eq!(tag_len4, 42);
let mut reader_tag_len8 = SliceReader::new(
&[0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a]);
let tag_len8 = types::Tag::tag(&mut reader_tag_len8).unwrap();
assert_eq!(tag_len8, 42);
}
#[test]
fn test_ignored_any_eof_loop() {
let mut buf = BufWriter::new(Vec::new());
"aaa".encode(&mut buf).unwrap();
// bad input
let mut buf = buf.into_inner();
buf.pop();
let mut reader = SliceReader::new(&buf);
let ret = dec::IgnoredAny::decode(&mut reader);
match ret {
Err(dec::Error::Eof { name, .. }) => {
assert_eq!(name, &"ignored-any");
},
_ => panic!()
}
}
#[test]
fn test_cov_case() {
let mut buf = BufWriter::new(Vec::new());
// u16
u16::MAX.encode(&mut buf).unwrap();
let v = u16::decode(&mut SliceReader::new(buf.buffer())).unwrap();
assert_eq!(v, u16::MAX);
// i128
buf.clear();
i128::MAX.encode(&mut buf).unwrap();
let v = i128::decode(&mut SliceReader::new(buf.buffer())).unwrap();
assert_eq!(v, i128::MAX);
// bytes
buf.clear();
types::Bytes("123".as_bytes()).encode(&mut buf).unwrap();
let v = <types::Bytes<&[u8]>>::decode(&mut SliceReader::new(buf.buffer())).unwrap();
assert_eq!(v.0, b"123");
// unchecked str
buf.clear();
types::UncheckedStr(&[0xff][..]).encode(&mut buf).unwrap();
let v = <types::UncheckedStr<&[u8]>>::decode(&mut SliceReader::new(buf.buffer())).unwrap();
assert_eq!(v.0, &[0xff]);
// unbounded + bool + ignore
buf.clear();
<types::Array<()>>::unbounded(&mut buf).unwrap();
true.encode(&mut buf).unwrap();
false.encode(&mut buf).unwrap();
<types::Array<()>>::end(&mut buf).unwrap();
let v = <Vec<bool>>::decode(&mut SliceReader::new(buf.buffer())).unwrap();
assert_eq!(v, vec![true, false]);
let _ignore = dec::IgnoredAny::decode(&mut SliceReader::new(buf.buffer())).unwrap();
// option + f32
buf.clear();
f32::MAX.encode(&mut buf).unwrap();
let v = <Option<f32>>::decode(&mut SliceReader::new(buf.buffer())).unwrap();
assert_eq!(v, Some(f32::MAX));
buf.clear();
types::Null.encode(&mut buf).unwrap();
let v = <Option<f32>>::decode(&mut SliceReader::new(buf.buffer())).unwrap();
assert_eq!(v, None);
buf.clear();
types::Undefined.encode(&mut buf).unwrap();
let v = <Option<f32>>::decode(&mut SliceReader::new(buf.buffer())).unwrap();
assert_eq!(v, None);
// simple
buf.clear();
types::Simple(21).encode(&mut buf).unwrap();
let v = types::Simple::decode(&mut SliceReader::new(buf.buffer())).unwrap();
assert_eq!(v.0, 21);
let v = bool::decode(&mut SliceReader::new(buf.buffer())).unwrap();
assert_eq!(v, true);
}
#[test]
fn test_string_from_zero() {
let buf = &[0];
let v = <String>::decode(&mut SliceReader::new(buf));
match v.as_ref().err() {
Some(cbor4ii::core::error::DecodeError::Mismatch { name, found }) => {
assert_eq!(**name, "str");
assert_eq!(*found, 0);
},
_ => panic!("{:?}", v)
}
}
#[test]
fn test_nothing() {
let mut writer = BufWriter::new(Vec::new());
types::Nothing.encode(&mut writer).unwrap();
let buf = writer.into_inner();
assert!(buf.is_empty());
let mut reader = SliceReader::new(&buf);
<types::Nothing>::decode(&mut reader).unwrap();
}
#[test]
fn test_string_box_vec_maybe() {
// work
{
let obj = Some(Box::new(vec![
"1".to_owned(),
"2".to_owned(),
]));
let mut writer = BufWriter::new(Vec::new());
types::Maybe(&obj).encode(&mut writer).unwrap();
let buf = writer.into_inner();
let mut reader = SliceReader::new(&buf);
let obj2 = <types::Maybe<Option<Box<Vec<String>>>>>::decode(&mut reader).unwrap();
assert_eq!(obj, obj2.0);
}
// none
{
let obj: Option<String> = None;
let mut writer = BufWriter::new(Vec::new());
types::Maybe(&obj).encode(&mut writer).unwrap();
let buf = writer.into_inner();
let mut reader = SliceReader::new(&buf);
let obj2 = <types::Maybe<Option<Box<Vec<String>>>>>::decode(&mut reader).unwrap();
assert!(obj2.0.is_none());
}
// bad slice
{
let obj: Vec<String> = vec!["1".into(), "2".into(), "3".into()];
let mut writer = BufWriter::new(Vec::new());
obj.encode(&mut writer).unwrap();
let buf = writer.into_inner();
let mut reader = SliceReader::new(&buf);
match <types::Maybe<Option<String>>>::decode(&mut reader) {
Ok(_) => panic!(),
Err(dec::Error::RequireLength { name, .. }) => {
assert_eq!(name, &"maybe");
},
Err(_) => panic!()
}
}
}
#[test]
fn test_mock_chunk_string() {
struct ChunkReader(Vec<u8>, usize);
impl<'de> dec::Read<'de> for ChunkReader {
type Error = std::io::Error;
#[inline]
fn fill<'b>(&'b mut self, _want: usize) -> Result<dec::Reference<'de, 'b>, Self::Error> {
let range = self.1..(self.1+1);
let buf = &self.0[range];
Ok(dec::Reference::Short(buf))
}
#[inline]
fn advance(&mut self, n: usize) {
self.1 += n;
}
}
let mut writer = BufWriter::new(Vec::new());
types::UncheckedStr::unbounded(&mut writer).unwrap();
"123".encode(&mut writer).unwrap();
"456".encode(&mut writer).unwrap();
types::UncheckedStr::end(&mut writer).unwrap();
let buf = writer.into_inner();
let mut reader = ChunkReader(buf, 0);
let s = String::decode(&mut reader).unwrap();
assert_eq!(s, "123456");
}