mod header;
mod request;
mod response;
mod value;
use std::io::Cursor;
pub use header::*;
pub use request::*;
pub use response::*;
pub use value::*;
pub type Id = String;
fn read_header_bytes(input: &[u8]) -> Result<(&[u8], &[u8]), &[u8]> {
let mut cursor = Cursor::new(input);
let input_len = input.len();
let len = match rmp::decode::read_map_len(&mut cursor) {
Ok(x) => x,
Err(_) => return Err(input),
};
for _i in 0..len {
let key_len = match rmp::decode::read_str_len(&mut cursor) {
Ok(x) => x as u64,
Err(_) => return Err(input),
};
cursor.set_position(cursor.position() + key_len);
if cursor.position() as usize > input_len {
return Err(input);
}
let input = &input[cursor.position() as usize..];
match find_msgpack_byte_len(input) {
Some(len) => cursor.set_position(cursor.position() + len),
None => return Err(input),
}
if cursor.position() as usize > input_len {
return Err(input);
}
}
let pos = cursor.position() as usize;
if pos > input_len {
return Err(input);
}
Ok((&input[..pos], &input[pos..]))
}
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]) {
rmp::Marker::Null => 1,
rmp::Marker::True => 1,
rmp::Marker::False => 1,
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,
rmp::Marker::F32 => 5,
rmp::Marker::F64 => 9,
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),
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),
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)
}
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)
}
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),
rmp::Marker::Reserved => return None,
})
}
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),
}
}
fn read_key_eq<'a>(input: &'a [u8], key: &str) -> Result<((), &'a [u8]), &'a [u8]> {
match read_str_bytes(input) {
Ok((s, input)) if s == key => Ok(((), input)),
_ => Err(input),
}
}
#[cfg(test)]
mod tests {
use super::*;
mod read_str_bytes {
use test_log::test;
use super::*;
#[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_key_eq {
use test_log::test;
use super::*;
#[test]
fn should_fail_if_input_is_empty() {
let input = read_key_eq(&[], "key").unwrap_err();
assert!(input.is_empty());
}
#[test]
fn should_fail_if_input_does_not_start_with_str() {
let input = &[
0xff,
rmp::Marker::FixStr(5).to_u8(),
b'h',
b'e',
b'l',
b'l',
b'o',
];
let remaining = read_key_eq(input, "key").unwrap_err();
assert_eq!(remaining, input);
}
#[test]
fn should_fail_if_read_key_does_not_match_specified_key() {
let input = &[
rmp::Marker::FixStr(5).to_u8(),
b'h',
b'e',
b'l',
b'l',
b'o',
0xff,
];
let remaining = read_key_eq(input, "key").unwrap_err();
assert_eq!(remaining, input);
}
#[test]
fn should_succeed_if_read_key_matches_specified_key() {
let input = &[
rmp::Marker::FixStr(5).to_u8(),
b'h',
b'e',
b'l',
b'l',
b'o',
0xff,
];
let (_, remaining) = read_key_eq(input, "hello").unwrap();
assert_eq!(remaining, [0xff]);
}
}
mod read_header_bytes {
use test_log::test;
use super::*;
#[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() {
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, 0x03, 0xa3, b'a', b'b', b'c', ];
assert!(read_header_bytes(&input).is_err());
}
#[test]
fn should_fail_if_key_length_exceeds_remaining_bytes() {
let input = vec![
0x81, 0xa8, b'a', b'b', b'c', 0xa3, b'a', b'b', b'c', ];
assert!(read_header_bytes(&input).is_err());
}
#[test]
fn should_fail_if_missing_value_for_key() {
let input = vec![
0x81, 0xa3, b'a', b'b', b'c', ];
assert!(read_header_bytes(&input).is_err());
}
#[test]
fn should_fail_if_unable_to_read_value_length() {
let input = vec![
0x81, 0xa3, b'a', b'b', b'c', 0xd9, ];
assert!(read_header_bytes(&input).is_err());
}
#[test]
fn should_fail_if_value_length_exceeds_remaining_bytes() {
let input = vec![
0x81, 0xa3, b'a', b'b', b'c', 0xa2, b'd', ];
assert!(read_header_bytes(&input).is_err());
}
#[test]
fn should_succeed_with_empty_map() {
let input = vec![0x80];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
let input = vec![0xde, 0x00, 0x00];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
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() {
let input = vec![
0x81, 0xa3, b'k', b'e', b'y', 0xa5, b'v', b'a', b'l', b'u', b'e', ];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
let input = vec![
0xde, 0x00, 0x01, 0xa3, b'k', b'e', b'y', 0xa5, b'v', b'a', b'l', b'u', b'e', ];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
let input = vec![
0xdf, 0x00, 0x00, 0x00, 0x01, 0xa3, b'k', b'e', b'y', 0xa5, b'v', b'a', b'l', b'u', b'e', ];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
}
#[test]
fn should_succeed_with_multiple_key_value_map() {
let input = vec![
0x82, 0xa3, b'k', b'e', b'y', 0xa5, b'v', b'a', b'l', b'u', b'e', 0xa3, b'y', b'e', b'k', 0x7b, ];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
let input = vec![
0xde, 0x00, 0x02, 0xa3, b'k', b'e', b'y', 0xa5, b'v', b'a', b'l', b'u', b'e', 0xa3, b'y', b'e', b'k', 0x7b, ];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
let input = vec![
0xdf, 0x00, 0x00, 0x00, 0x02, 0xa3, b'k', b'e', b'y', 0xa5, b'v', b'a', b'l', b'u', b'e', 0xa3, b'y', b'e', b'k', 0x7b, ];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
}
#[test]
fn should_succeed_with_nested_map() {
let input = vec![
0x81, 0xa3, b'm', b'a', b'p', 0x81, 0xa3, b'k', b'e', b'y', 0xa5, b'v', b'a', b'l', b'u', b'e', ];
let (header, _) = read_header_bytes(&input).unwrap();
assert_eq!(header, input);
}
#[test]
fn should_only_consume_map_from_input() {
let input = vec![
0x81, 0xa3, b'k', b'e', b'y', 0xa5, b'v', b'a', b'l', b'u', b'e', 0xa4, b'm', b'o', b'r', b'e', ];
let (header, remaining) = read_header_bytes(&input).unwrap();
assert_eq!(
header,
vec![
0x81, 0xa3, b'k', b'e', b'y', 0xa5, b'v', b'a', b'l', b'u', b'e', ]
);
assert_eq!(
remaining,
vec![
0xa4, b'm', b'o', b'r', b'e', ]
);
}
}
mod find_msgpack_byte_len {
use test_log::test;
use super::*;
#[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]; let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(1), "Wrong len for {input:X?}");
let input = vec![0xc3]; 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]; let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(1), "Wrong len for {input:X?}");
let input = vec![0xff]; let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(1), "Wrong len for {input:X?}");
let input = vec![0xcc, 0xff]; let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(2), "Wrong len for {input:X?}");
let input = vec![0xcd, 0xff, 0xff]; 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]; 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]; let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(9), "Wrong len for {input:X?}");
let input = vec![0xd0, 0x81]; let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(2), "Wrong len for {input:X?}");
let input = vec![0xd1, 0x80, 0x01]; 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]; 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]; 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]; 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]; 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() {
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?}");
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?}");
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?}");
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() {
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?}");
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?}");
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() {
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?}");
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?}");
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?}");
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?}");
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?}");
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() {
let input = vec![
0x83, 0x03, 0xa3, b'a', b'b', b'c', 0xa3, b'a', b'b', b'c', 0xcc, 0xff, 0xc3, 0xc2, ];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(1 + 5 + 6 + 2), "Wrong len for {input:X?}");
let input = vec![
0x83, 0x03, 0xa3, b'a', b'b', b'c', 0xa3, b'a', b'b', b'c', 0xcc, 0xff, 0xc3, ];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, None, "Wrong len for {input:X?}");
let input = vec![
0xde, 0x00, 0x03, 0x03, 0xa3, b'a', b'b', b'c', 0xa3, b'a', b'b', b'c', 0xcc, 0xff, 0xc3, 0xc2, ];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(3 + 5 + 6 + 2), "Wrong len for {input:X?}");
let input = vec![
0xde, 0x00, 0x03, 0x03, 0xa3, b'a', b'b', b'c', 0xa3, b'a', b'b', b'c', 0xcc, 0xff, 0xc3, ];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, None, "Wrong len for {input:X?}");
let input = vec![
0xdf, 0x00, 0x00, 0x00, 0x03, 0x03, 0xa3, b'a', b'b', b'c', 0xa3, b'a', b'b', b'c', 0xcc, 0xff, 0xc3, 0xc2, ];
let len = find_msgpack_byte_len(&input);
assert_eq!(len, Some(5 + 5 + 6 + 2), "Wrong len for {input:X?}");
let input = vec![
0xdf, 0x00, 0x00, 0x00, 0x03, 0x03, 0xa3, b'a', b'b', b'c', 0xa3, b'a', b'b', b'c', 0xcc, 0xff, 0xc3, ];
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() {
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?}");
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?}");
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?}");
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?}");
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?}");
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?}");
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?}");
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?}");
}
}
}