You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
distant/distant-net/src/common/packet.rs

738 lines
28 KiB
Rust

mod header;
mod request;
mod response;
pub use header::*;
pub use request::*;
pub use response::*;
use std::io::Cursor;
/// Represents a generic id type
pub type Id = String;
/// Reads the header bytes from msgpack input, including the marker and len bytes.
///
/// * If succeeds, returns (header, remaining).
/// * If fails, returns existing bytes.
fn read_header_bytes(input: &[u8]) -> Result<(&[u8], &[u8]), &[u8]> {
let mut cursor = Cursor::new(input);
let input_len = input.len();
// Determine size of header map in terms of total objects
let len = match rmp::decode::read_map_len(&mut cursor) {
Ok(x) => x,
Err(_) => return Err(input),
};
// For each object, we have a corresponding key in front of it has a string,
// so we need to iterate, advancing by a string key and then the object
for _i in 0..len {
// Read just the length of the key to avoid copying the key itself
let key_len = match rmp::decode::read_str_len(&mut cursor) {
Ok(x) => x as u64,
Err(_) => return Err(input),
};
// Advance forward past the key
cursor.set_position(cursor.position() + key_len);
// If we would have advanced past our input, fail
if cursor.position() as usize > input_len {
return Err(input);
}
// Point locally to just past the str key so we can determine next byte len to skip
let input = &input[cursor.position() as usize..];
// Read the type of object and advance accordingly
match find_msgpack_byte_len(input) {
Some(len) => cursor.set_position(cursor.position() + len),
None => return Err(input),
}
// If we would have advanced past our input, fail
if cursor.position() as usize > input_len {
return Err(input);
}
}
let pos = cursor.position() as usize;
// Check if we've read beyond the input (being equal to len is okay
// because we could consume all of the remaining input this way)
if pos > input_len {
return Err(input);
}
Ok((&input[..pos], &input[pos..]))
}
/// Determines the length of the next object based on its marker. From the marker, some objects
/// need to be traversed (e.g. map) in order to fully understand the total byte length.
///
/// This will include the marker bytes in the total byte len such that collecting all of the
/// bytes up to len will yield a valid msgpack object in byte form.
///
/// If the first byte does not signify a valid marker, this method returns None.
fn find_msgpack_byte_len(input: &[u8]) -> Option<u64> {
if input.is_empty() {
return None;
}
macro_rules! read_len {
(u8: $input:expr $(, start = $start:expr)?) => {{
let input = $input;
$(
if input.len() < $start {
return None;
}
let input = &input[$start..];
)?
if input.is_empty() {
return None;
} else {
input[0] as u64
}
}};
(u16: $input:expr $(, start = $start:expr)?) => {{
let input = $input;
$(
if input.len() < $start {
return None;
}
let input = &input[$start..];
)?
if input.len() < 2 {
return None;
} else {
u16::from_be_bytes([input[0], input[1]]) as u64
}
}};
(u32: $input:expr $(, start = $start:expr)?) => {{
let input = $input;
$(
if input.len() < $start {
return None;
}
let input = &input[$start..];
)?
if input.len() < 4 {
return None;
} else {
u32::from_be_bytes([input[0], input[1], input[2], input[3]]) as u64
}
}};
($cnt:expr => $input:expr $(, start = $start:expr)?) => {{
let input = $input;
$(
if input.len() < $start {
return None;
}
let input = &input[$start..];
)?
let cnt = $cnt;
let mut len = 0;
for _i in 0..cnt {
if input.len() < len {
return None;
}
let input = &input[len..];
match find_msgpack_byte_len(input) {
Some(x) => len += x as usize,
None => return None,
}
}
len as u64
}};
}
Some(match rmp::Marker::from_u8(input[0]) {
// Booleans and nil (aka null) are a combination of marker and value (single byte)
rmp::Marker::Null => 1,
rmp::Marker::True => 1,
rmp::Marker::False => 1,
// Integers are stored in 1, 2, 3, 5, or 9 bytes
rmp::Marker::FixPos(_) => 1,
rmp::Marker::FixNeg(_) => 1,
rmp::Marker::U8 => 2,
rmp::Marker::U16 => 3,
rmp::Marker::U32 => 5,
rmp::Marker::U64 => 9,
rmp::Marker::I8 => 2,
rmp::Marker::I16 => 3,
rmp::Marker::I32 => 5,
rmp::Marker::I64 => 9,
// Floats are stored in 5 or 9 bytes
rmp::Marker::F32 => 5,
rmp::Marker::F64 => 9,
// Str are stored in 1, 2, 3, or 5 bytes + the data buffer
rmp::Marker::FixStr(len) => 1 + len as u64,
rmp::Marker::Str8 => 2 + read_len!(u8: input, start = 1),
rmp::Marker::Str16 => 3 + read_len!(u16: input, start = 1),
rmp::Marker::Str32 => 5 + read_len!(u32: input, start = 1),
// Bin are stored in 2, 3, or 5 bytes + the data buffer
rmp::Marker::Bin8 => 2 + read_len!(u8: input, start = 1),
rmp::Marker::Bin16 => 3 + read_len!(u16: input, start = 1),
rmp::Marker::Bin32 => 5 + read_len!(u32: input, start = 1),
// Arrays are stored in 1, 3, or 5 bytes + N objects (where each object has its own len)
rmp::Marker::FixArray(cnt) => 1 + read_len!(cnt => input, start = 1),
rmp::Marker::Array16 => {
let cnt = read_len!(u16: input, start = 1);
3 + read_len!(cnt => input, start = 3)
}
rmp::Marker::Array32 => {
let cnt = read_len!(u32: input, start = 1);
5 + read_len!(cnt => input, start = 5)
}
// Maps are stored in 1, 3, or 5 bytes + 2*N objects (where each object has its own len)
rmp::Marker::FixMap(cnt) => 1 + read_len!(2 * cnt => input, start = 1),
rmp::Marker::Map16 => {
let cnt = read_len!(u16: input, start = 1);
3 + read_len!(2 * cnt => input, start = 3)
}
rmp::Marker::Map32 => {
let cnt = read_len!(u32: input, start = 1);
5 + read_len!(2 * cnt => input, start = 5)
}
// Ext are stored in an integer (8-bit, 16-bit, 32-bit), type (8-bit), and byte array
rmp::Marker::FixExt1 => 3,
rmp::Marker::FixExt2 => 4,
rmp::Marker::FixExt4 => 6,
rmp::Marker::FixExt8 => 10,
rmp::Marker::FixExt16 => 18,
rmp::Marker::Ext8 => 3 + read_len!(u8: input, start = 1),
rmp::Marker::Ext16 => 4 + read_len!(u16: input, start = 1),
rmp::Marker::Ext32 => 6 + read_len!(u32: input, start = 1),
// NOTE: This is marked in the msgpack spec as never being used, so we return none
// as this is signfies something has gone wrong!
rmp::Marker::Reserved => return None,
})
}
/// Reads the str bytes from msgpack input, including the marker and len bytes.
///
/// * If succeeds, returns (str, remaining).
/// * If fails, returns existing bytes.
fn read_str_bytes(input: &[u8]) -> Result<(&str, &[u8]), &[u8]> {
match rmp::decode::read_str_from_slice(input) {
Ok(x) => Ok(x),
Err(_) => Err(input),
}
}
#[cfg(test)]
mod tests {
use super::*;
mod read_str_bytes {
use super::*;
use test_log::test;
#[test]
fn should_fail_if_input_is_empty() {
let input = read_str_bytes(&[]).unwrap_err();
assert!(input.is_empty());
}
#[test]
fn should_fail_if_input_does_not_start_with_str() {
let input = read_str_bytes(&[0xff, 0xa5, b'h', b'e', b'l', b'l', b'o']).unwrap_err();
assert_eq!(input, [0xff, 0xa5, b'h', b'e', b'l', b'l', b'o']);
}
#[test]
fn should_succeed_if_input_starts_with_str() {
let (s, remaining) =
read_str_bytes(&[0xa5, b'h', b'e', b'l', b'l', b'o', 0xff]).unwrap();
assert_eq!(s, "hello");
assert_eq!(remaining, [0xff]);
}
}
mod read_header_bytes {
use super::*;
use test_log::test;
#[test]
fn should_fail_if_input_is_empty() {
let input = vec![];
assert!(read_header_bytes(&input).is_err());
}
#[test]
fn should_fail_if_not_a_map() {
// Provide an array instead of a map
let input = vec![0x93, 0xa3, b'a', b'b', b'c', 0xcc, 0xff, 0xc2];
assert!(read_header_bytes(&input).is_err());
}
#[test]
fn should_fail_if_cannot_read_str_key_length() {
let input = vec![
0x81, // valid map with 1 pair, but key is not a str
0x03, 0xa3, b'a', b'b', b'c', // 3 -> "abc"
];
assert!(read_header_bytes(&input).is_err());
}
#[test]
fn should_fail_if_key_length_exceeds_remaining_bytes() {
let input = vec![
0x81, // valid map with 1 pair, but key length is too long
0xa8, b'a', b'b', b'c', // key: "abc" (but len is much greater)
0xa3, b'a', b'b', b'c', // value: "abc"
];
assert!(read_header_bytes(&input).is_err());
}
#[test]
fn should_fail_if_missing_value_for_key() {
let input = vec![
0x81, // valid map with 1 pair, but value is missing
0xa3, b'a', b'b', b'c', // key: "abc"
];
assert!(read_header_bytes(&input).is_err());
}
#[test]
fn should_fail_if_unable_to_read_value_length() {
let input = vec![
0x81, // valid map with 1 pair, but value is missing
0xa3, b'a', b'b', b'c', // key: "abc"
0xd9, // value: str 8 with missing length
];
assert!(read_header_bytes(&input).is_err());
}
#[test]
fn should_fail_if_value_length_exceeds_remaining_bytes() {
let input = vec![
0x81, // valid map with 1 pair, but value is too long
0xa3, b'a', b'b', b'c', // key: "abc"
0xa2, b'd', // value: fixstr w/ len 1 too long
];
assert!(read_header_bytes(&input).is_err());
}
#[test]
fn should_succeed_with_empty_map() {
// fixmap with 0 pairs
let input = vec![0x80];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
// map 16 with 0 pairs
let input = vec![0xde, 0x00, 0x00];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
// map 32 with 0 pairs
let input = vec![0xdf, 0x00, 0x00, 0x00, 0x00];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
}
#[test]
fn should_succeed_with_single_key_value_map() {
// fixmap with single pair
let input = vec![
0x81, // valid map with 1 pair
0xa3, b'k', b'e', b'y', // key: "key"
0xa5, b'v', b'a', b'l', b'u', b'e', // value: "value"
];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
// map 16 with single pair
let input = vec![
0xde, 0x00, 0x01, // valid map with 1 pair
0xa3, b'k', b'e', b'y', // key: "key"
0xa5, b'v', b'a', b'l', b'u', b'e', // value: "value"
];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
// map 32 with single pair
let input = vec![
0xdf, 0x00, 0x00, 0x00, 0x01, // valid map with 1 pair
0xa3, b'k', b'e', b'y', // key: "key"
0xa5, b'v', b'a', b'l', b'u', b'e', // value: "value"
];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
}
#[test]
fn should_succeed_with_multiple_key_value_map() {
// fixmap with single pair
let input = vec![
0x82, // valid map with 2 pairs
0xa3, b'k', b'e', b'y', // key: "key"
0xa5, b'v', b'a', b'l', b'u', b'e', // value: "value"
0xa3, b'y', b'e', b'k', // key: "yek"
0x7b, // value: 123 (fixint)
];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
// map 16 with single pair
let input = vec![
0xde, 0x00, 0x02, // valid map with 2 pairs
0xa3, b'k', b'e', b'y', // key: "key"
0xa5, b'v', b'a', b'l', b'u', b'e', // value: "value"
0xa3, b'y', b'e', b'k', // key: "yek"
0x7b, // value: 123 (fixint)
];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
// map 32 with single pair
let input = vec![
0xdf, 0x00, 0x00, 0x00, 0x02, // valid map with 2 pairs
0xa3, b'k', b'e', b'y', // key: "key"
0xa5, b'v', b'a', b'l', b'u', b'e', // value: "value"
0xa3, b'y', b'e', b'k', // key: "yek"
0x7b, // value: 123 (fixint)
];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
}
#[test]
fn should_succeed_with_nested_map() {
// fixmap with single pair
let input = vec![
0x81, // valid map with 1 pair
0xa3, b'm', b'a', b'p', // key: "map"
0x81, // value: valid map with 1 pair
0xa3, b'k', b'e', b'y', // key: "key"
0xa5, b'v', b'a', b'l', b'u', b'e', // value: "value"
];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
}
#[test]
fn should_only_consume_map_from_input() {
// fixmap with single pair
let input = vec![
0x81, // valid map with 1 pair
0xa3, b'k', b'e', b'y', // key: "key"
0xa5, b'v', b'a', b'l', b'u', b'e', // value: "value"
0xa4, b'm', b'o', b'r', b'e', // "more" (fixstr)
];
let (header, remaining) = read_header_bytes(&input).unwrap();
assert_eq!(
header,
vec![
0x81, // valid map with 1 pair
0xa3, b'k', b'e', b'y', // key: "key"
0xa5, b'v', b'a', b'l', b'u', b'e', // value: "value"
]
);
assert_eq!(
remaining,
vec![
0xa4, b'm', b'o', b'r', b'e', // "more" (fixstr)
]
);
}
}
mod find_msgpack_byte_len {
use super::*;
use test_log::test;
#[test]
fn should_return_none_if_input_is_empty() {
let input = vec![];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, None, "Wrong len for {input:X?}");
}
#[test]
fn should_return_none_if_input_has_reserved_marker() {
let input = vec![rmp::Marker::Reserved.to_u8()];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, None, "Wrong len for {input:X?}");
}
#[test]
fn should_return_1_if_input_is_nil() {
let input = vec![0xc0];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(1), "Wrong len for {input:X?}");
}
#[test]
fn should_return_1_if_input_is_a_boolean() {
let input = vec![0xc2]; // false
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(1), "Wrong len for {input:X?}");
let input = vec![0xc3]; // true
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(1), "Wrong len for {input:X?}");
}
#[test]
fn should_return_appropriate_len_if_input_is_some_integer() {
let input = vec![0x00]; // positive fixint (0)
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(1), "Wrong len for {input:X?}");
let input = vec![0xff]; // negative fixint (-1)
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(1), "Wrong len for {input:X?}");
let input = vec![0xcc, 0xff]; // unsigned 8-bit (255)
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(2), "Wrong len for {input:X?}");
let input = vec![0xcd, 0xff, 0xff]; // unsigned 16-bit (65535)
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(3), "Wrong len for {input:X?}");
let input = vec![0xce, 0xff, 0xff, 0xff, 0xff]; // unsigned 32-bit (4294967295)
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(5), "Wrong len for {input:X?}");
let input = vec![0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00]; // unsigned 64-bit (4294967296)
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(9), "Wrong len for {input:X?}");
let input = vec![0xd0, 0x81]; // signed 8-bit (-127)
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(2), "Wrong len for {input:X?}");
let input = vec![0xd1, 0x80, 0x01]; // signed 16-bit (-32767)
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(3), "Wrong len for {input:X?}");
let input = vec![0xd2, 0x80, 0x00, 0x00, 0x01]; // signed 32-bit (-2147483647)
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(5), "Wrong len for {input:X?}");
let input = vec![0xd3, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00]; // signed 64-bit (-2147483648)
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(9), "Wrong len for {input:X?}");
}
#[test]
fn should_return_appropriate_len_if_input_is_some_float() {
let input = vec![0xca, 0x3d, 0xcc, 0xcc, 0xcd]; // f32 (0.1)
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(5), "Wrong len for {input:X?}");
let input = vec![0xcb, 0x3f, 0xb9, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a]; // f64 (0.1)
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(9), "Wrong len for {input:X?}");
}
#[test]
fn should_return_appropriate_len_if_input_is_some_str() {
// fixstr (31 bytes max)
let input = vec![0xa5, b'h', b'e', b'l', b'l', b'o'];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(5 + 1), "Wrong len for {input:X?}");
// str 8 will read second byte (u8) for size
let input = vec![0xd9, 0xff, b'd', b'a', b't', b'a'];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(u8::MAX as u64 + 2), "Wrong len for {input:X?}");
// str 16 will read second & third bytes (u16) for size
let input = vec![0xda, 0xff, 0xff, b'd', b'a', b't', b'a'];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(u16::MAX as u64 + 3), "Wrong len for {input:X?}");
// str 32 will read second, third, fourth, & fifth bytes (u32) for size
let input = vec![0xdb, 0xff, 0xff, 0xff, 0xff, b'd', b'a', b't', b'a'];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(u32::MAX as u64 + 5), "Wrong len for {input:X?}");
}
#[test]
fn should_return_appropriate_len_if_input_is_some_bin() {
// bin 8 will read second byte (u8) for size
let input = vec![0xc4, 0xff, b'd', b'a', b't', b'a'];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(u8::MAX as u64 + 2), "Wrong len for {input:X?}");
// bin 16 will read second & third bytes (u16) for size
let input = vec![0xc5, 0xff, 0xff, b'd', b'a', b't', b'a'];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(u16::MAX as u64 + 3), "Wrong len for {input:X?}");
// bin 32 will read second, third, fourth, & fifth bytes (u32) for size
let input = vec![0xc6, 0xff, 0xff, 0xff, 0xff, b'd', b'a', b't', b'a'];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(u32::MAX as u64 + 5), "Wrong len for {input:X?}");
}
#[test]
fn should_return_appropriate_len_if_input_is_some_array() {
// fixarray has a length up to 15 objects
//
// In this example, we have an array of 3 objects that are a str, integer, and bool
let input = vec![0x93, 0xa3, b'a', b'b', b'c', 0xcc, 0xff, 0xc2];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(1 + 4 + 2 + 1), "Wrong len for {input:X?}");
// Invalid fixarray count should return none
let input = vec![0x93, 0xa3, b'a', b'b', b'c', 0xcc, 0xff];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, None, "Wrong len for {input:X?}");
// array 16 will read second & third bytes (u16) for object length
//
// In this example, we have an array of 3 objects that are a str, integer, and bool
let input = vec![0xdc, 0x00, 0x03, 0xa3, b'a', b'b', b'c', 0xcc, 0xff, 0xc2];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(3 + 4 + 2 + 1), "Wrong len for {input:X?}");
// Invalid array 16 count should return none
let input = vec![0xdc, 0x00, 0x03, 0xa3, b'a', b'b', b'c', 0xcc, 0xff];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, None, "Wrong len for {input:X?}");
// array 32 will read second, third, fourth, & fifth bytes (u32) for object length
let input = vec![
0xdd, 0x00, 0x00, 0x00, 0x03, 0xa3, b'a', b'b', b'c', 0xcc, 0xff, 0xc2,
];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(5 + 4 + 2 + 1), "Wrong len for {input:X?}");
// Invalid array 32 count should return none
let input = vec![
0xdd, 0x00, 0x00, 0x00, 0x03, 0xa3, b'a', b'b', b'c', 0xcc, 0xff,
];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, None, "Wrong len for {input:X?}");
}
#[test]
fn should_return_appropriate_len_if_input_is_some_map() {
// fixmap has a length up to 2*15 objects
let input = vec![
0x83, // 3 objects /w keys
0x03, 0xa3, b'a', b'b', b'c', // 3 -> "abc"
0xa3, b'a', b'b', b'c', 0xcc, 0xff, // "abc" -> 255
0xc3, 0xc2, // true -> false
];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(1 + 5 + 6 + 2), "Wrong len for {input:X?}");
// Invalid fixmap count should return none
let input = vec![
0x83, // 3 objects /w keys
0x03, 0xa3, b'a', b'b', b'c', // 3 -> "abc"
0xa3, b'a', b'b', b'c', 0xcc, 0xff, // "abc" -> 255
0xc3, // true -> ???
];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, None, "Wrong len for {input:X?}");
// map 16 will read second & third bytes (u16) for object length
let input = vec![
0xde, 0x00, 0x03, // 3 objects w/ keys
0x03, 0xa3, b'a', b'b', b'c', // 3 -> "abc"
0xa3, b'a', b'b', b'c', 0xcc, 0xff, // "abc" -> 255
0xc3, 0xc2, // true -> false
];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(3 + 5 + 6 + 2), "Wrong len for {input:X?}");
// Invalid map 16 count should return none
let input = vec![
0xde, 0x00, 0x03, // 3 objects w/ keys
0x03, 0xa3, b'a', b'b', b'c', // 3 -> "abc"
0xa3, b'a', b'b', b'c', 0xcc, 0xff, // "abc" -> 255
0xc3, // true -> ???
];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, None, "Wrong len for {input:X?}");
// map 32 will read second, third, fourth, & fifth bytes (u32) for object length
let input = vec![
0xdf, 0x00, 0x00, 0x00, 0x03, // 3 objects w/ keys
0x03, 0xa3, b'a', b'b', b'c', // 3 -> "abc"
0xa3, b'a', b'b', b'c', 0xcc, 0xff, // "abc" -> 255
0xc3, 0xc2, // true -> false
];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(5 + 5 + 6 + 2), "Wrong len for {input:X?}");
// Invalid map 32 count should return none
let input = vec![
0xdf, 0x00, 0x00, 0x00, 0x03, // 3 objects w/ keys
0x03, 0xa3, b'a', b'b', b'c', // 3 -> "abc"
0xa3, b'a', b'b', b'c', 0xcc, 0xff, // "abc" -> 255
0xc3, // true -> ???
];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, None, "Wrong len for {input:X?}");
}
#[test]
fn should_return_appropriate_len_if_input_is_some_ext() {
// fixext 1 claims single data byte (excluding type)
let input = vec![0xd4, 0x00, 0x12];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(1 + 1 + 1), "Wrong len for {input:X?}");
// fixext 2 claims two data bytes (excluding type)
let input = vec![0xd5, 0x00, 0x12, 0x34];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(1 + 1 + 2), "Wrong len for {input:X?}");
// fixext 4 claims four data bytes (excluding type)
let input = vec![0xd6, 0x00, 0x12, 0x34, 0x56, 0x78];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(1 + 1 + 4), "Wrong len for {input:X?}");
// fixext 8 claims eight data bytes (excluding type)
let input = vec![0xd7, 0x00, 0x12, 0x34, 0x56, 0x78];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(1 + 1 + 8), "Wrong len for {input:X?}");
// fixext 16 claims sixteen data bytes (excluding type)
let input = vec![0xd8, 0x00, 0x12, 0x34, 0x56, 0x78];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(1 + 1 + 16), "Wrong len for {input:X?}");
// ext 8 will read second byte (u8) for size (excluding type)
let input = vec![0xc7, 0xff, 0x00, b'd', b'a', b't', b'a'];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(u8::MAX as u64 + 3), "Wrong len for {input:X?}");
// ext 16 will read second & third bytes (u16) for size (excluding type)
let input = vec![0xc8, 0xff, 0xff, 0x00, b'd', b'a', b't', b'a'];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(u16::MAX as u64 + 4), "Wrong len for {input:X?}");
// ext 32 will read second, third, fourth, & fifth bytes (u32) for size (excluding type)
let input = vec![0xc9, 0xff, 0xff, 0xff, 0xff, 0x00, b'd', b'a', b't', b'a'];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(u32::MAX as u64 + 6), "Wrong len for {input:X?}");
}
}
}