#![allow(clippy::missing_safety_doc)]
use super::jit_debug;
pub mod tags {
pub const FALSE: u8 = 0xC2;
pub const TRUE: u8 = 0xC3;
pub const BIN8: u8 = 0xC4;
pub const BIN16: u8 = 0xC5;
pub const BIN32: u8 = 0xC6;
pub const U8: u8 = 0xCC;
pub const U16: u8 = 0xCD;
pub const U32: u8 = 0xCE;
pub const U64: u8 = 0xCF;
pub const I8: u8 = 0xD0;
pub const I16: u8 = 0xD1;
pub const I32: u8 = 0xD2;
pub const I64: u8 = 0xD3;
pub const ARRAY16: u8 = 0xDC;
pub const ARRAY32: u8 = 0xDD;
pub const POSITIVE_FIXINT_MAX: u8 = 0x7F;
pub const FIXARRAY_MIN: u8 = 0x90;
pub const FIXARRAY_MAX: u8 = 0x9F;
pub const NEGATIVE_FIXINT_MIN: u8 = 0xE0;
#[inline]
pub const fn is_positive_fixint(tag: u8) -> bool {
tag <= POSITIVE_FIXINT_MAX
}
#[inline]
pub const fn is_negative_fixint(tag: u8) -> bool {
tag >= NEGATIVE_FIXINT_MIN
}
#[inline]
pub const fn is_fixarray(tag: u8) -> bool {
tag >= FIXARRAY_MIN && tag <= FIXARRAY_MAX
}
}
#[repr(C)]
pub struct MsgPackJitPosError {
pub new_pos: usize,
pub error: i32,
}
#[repr(C)]
pub struct MsgPackJitPosEndError {
pub packed_pos_end: usize,
pub error: i32,
}
impl MsgPackJitPosEndError {
pub fn new(pos: usize, is_end: bool, error: i32) -> Self {
let packed_pos_end = if is_end { pos | (1usize << 63) } else { pos };
Self {
packed_pos_end,
error,
}
}
#[allow(dead_code)]
pub fn pos(&self) -> usize {
self.packed_pos_end & 0x7FFFFFFFFFFFFFFF
}
#[allow(dead_code)]
pub fn is_end(&self) -> bool {
(self.packed_pos_end >> 63) != 0
}
}
#[repr(C)]
pub struct MsgPackJitPosValueError {
pub packed_pos_value: usize,
pub error: i32,
}
impl MsgPackJitPosValueError {
pub fn new(new_pos: usize, value: bool, error: i32) -> Self {
let packed_pos_value = if value {
new_pos | (1usize << 63)
} else {
new_pos
};
Self {
packed_pos_value,
error,
}
}
#[allow(dead_code)]
pub fn new_pos(&self) -> usize {
self.packed_pos_value & 0x7FFFFFFFFFFFFFFF
}
#[allow(dead_code)]
pub fn value(&self) -> bool {
(self.packed_pos_value >> 63) != 0
}
}
#[repr(C)]
pub struct MsgPackJitU8Result {
pub new_pos: usize,
pub value: u8,
pub error: i32,
}
#[repr(C)]
pub struct MsgPackJitI64Result {
pub new_pos: usize,
pub value: i64,
pub error: i32,
}
#[repr(C)]
pub struct MsgPackJitSeqBeginResult {
pub new_pos: usize,
pub count: usize,
pub error: i32,
}
#[repr(C)]
pub struct MsgPackJitBinHeaderResult {
pub new_pos: usize,
pub len: usize,
pub error: i32,
}
pub mod error {
pub const UNEXPECTED_EOF: i32 = -100;
pub const EXPECTED_BOOL: i32 = -101;
pub const EXPECTED_ARRAY: i32 = -102;
pub const EXPECTED_BIN: i32 = -103;
pub const EXPECTED_INT: i32 = -104;
pub const INT_OVERFLOW: i32 = -105;
#[allow(dead_code)]
pub const COUNT_OVERFLOW: i32 = -106;
pub const SEQ_UNDERFLOW: i32 = -107;
pub const UNSUPPORTED: i32 = -1;
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msgpack_jit_parse_bool(
input: *const u8,
len: usize,
pos: usize,
) -> MsgPackJitPosValueError {
jit_debug!("[msgpack_jit_parse_bool] pos={}, len={}", pos, len);
if pos >= len {
jit_debug!("[msgpack_jit_parse_bool] EOF!");
return MsgPackJitPosValueError::new(pos, false, error::UNEXPECTED_EOF);
}
let tag = unsafe { *input.add(pos) };
jit_debug!("[msgpack_jit_parse_bool] tag=0x{:02X}", tag);
match tag {
tags::FALSE => {
jit_debug!("[msgpack_jit_parse_bool] -> false");
MsgPackJitPosValueError::new(pos + 1, false, 0)
}
tags::TRUE => {
jit_debug!("[msgpack_jit_parse_bool] -> true");
MsgPackJitPosValueError::new(pos + 1, true, 0)
}
_ => {
jit_debug!("[msgpack_jit_parse_bool] -> invalid tag!");
MsgPackJitPosValueError::new(pos, false, error::EXPECTED_BOOL)
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msgpack_jit_parse_u8(
input: *const u8,
len: usize,
pos: usize,
) -> MsgPackJitU8Result {
jit_debug!("[msgpack_jit_parse_u8] pos={}, len={}", pos, len);
if pos >= len {
return MsgPackJitU8Result {
new_pos: pos,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let tag = unsafe { *input.add(pos) };
jit_debug!("[msgpack_jit_parse_u8] tag=0x{:02X}", tag);
if tags::is_positive_fixint(tag) {
return MsgPackJitU8Result {
new_pos: pos + 1,
value: tag,
error: 0,
};
}
match tag {
tags::U8 => {
if pos + 1 >= len {
return MsgPackJitU8Result {
new_pos: pos + 1,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let value = unsafe { *input.add(pos + 1) };
MsgPackJitU8Result {
new_pos: pos + 2,
value,
error: 0,
}
}
tags::U16 => {
if pos + 2 >= len {
return MsgPackJitU8Result {
new_pos: pos + 1,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let value = u16::from_be_bytes(unsafe { [*input.add(pos + 1), *input.add(pos + 2)] });
if value > u8::MAX as u16 {
return MsgPackJitU8Result {
new_pos: pos,
value: 0,
error: error::INT_OVERFLOW,
};
}
MsgPackJitU8Result {
new_pos: pos + 3,
value: value as u8,
error: 0,
}
}
tags::U32 => {
if pos + 4 >= len {
return MsgPackJitU8Result {
new_pos: pos + 1,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let value = u32::from_be_bytes(unsafe {
[
*input.add(pos + 1),
*input.add(pos + 2),
*input.add(pos + 3),
*input.add(pos + 4),
]
});
if value > u8::MAX as u32 {
return MsgPackJitU8Result {
new_pos: pos,
value: 0,
error: error::INT_OVERFLOW,
};
}
MsgPackJitU8Result {
new_pos: pos + 5,
value: value as u8,
error: 0,
}
}
tags::U64 => {
if pos + 8 >= len {
return MsgPackJitU8Result {
new_pos: pos + 1,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let value = u64::from_be_bytes(unsafe {
[
*input.add(pos + 1),
*input.add(pos + 2),
*input.add(pos + 3),
*input.add(pos + 4),
*input.add(pos + 5),
*input.add(pos + 6),
*input.add(pos + 7),
*input.add(pos + 8),
]
});
if value > u8::MAX as u64 {
return MsgPackJitU8Result {
new_pos: pos,
value: 0,
error: error::INT_OVERFLOW,
};
}
MsgPackJitU8Result {
new_pos: pos + 9,
value: value as u8,
error: 0,
}
}
_ => MsgPackJitU8Result {
new_pos: pos,
value: 0,
error: error::EXPECTED_INT,
},
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msgpack_jit_parse_u64(
input: *const u8,
len: usize,
pos: usize,
) -> MsgPackJitI64Result {
jit_debug!("[msgpack_jit_parse_u64] pos={}, len={}", pos, len);
if pos >= len {
return MsgPackJitI64Result {
new_pos: pos,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let tag = unsafe { *input.add(pos) };
jit_debug!("[msgpack_jit_parse_u64] tag=0x{:02X}", tag);
if tags::is_positive_fixint(tag) {
return MsgPackJitI64Result {
new_pos: pos + 1,
value: tag as i64,
error: 0,
};
}
match tag {
tags::U8 => {
if pos + 1 >= len {
return MsgPackJitI64Result {
new_pos: pos + 1,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let value = unsafe { *input.add(pos + 1) };
MsgPackJitI64Result {
new_pos: pos + 2,
value: value as i64,
error: 0,
}
}
tags::U16 => {
if pos + 2 >= len {
return MsgPackJitI64Result {
new_pos: pos + 1,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let value = u16::from_be_bytes(unsafe { [*input.add(pos + 1), *input.add(pos + 2)] });
MsgPackJitI64Result {
new_pos: pos + 3,
value: value as i64,
error: 0,
}
}
tags::U32 => {
if pos + 4 >= len {
return MsgPackJitI64Result {
new_pos: pos + 1,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let value = u32::from_be_bytes(unsafe {
[
*input.add(pos + 1),
*input.add(pos + 2),
*input.add(pos + 3),
*input.add(pos + 4),
]
});
MsgPackJitI64Result {
new_pos: pos + 5,
value: value as i64,
error: 0,
}
}
tags::U64 => {
if pos + 8 >= len {
return MsgPackJitI64Result {
new_pos: pos + 1,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let value = u64::from_be_bytes(unsafe {
[
*input.add(pos + 1),
*input.add(pos + 2),
*input.add(pos + 3),
*input.add(pos + 4),
*input.add(pos + 5),
*input.add(pos + 6),
*input.add(pos + 7),
*input.add(pos + 8),
]
});
MsgPackJitI64Result {
new_pos: pos + 9,
value: value as i64,
error: 0,
}
}
_ => MsgPackJitI64Result {
new_pos: pos,
value: 0,
error: error::EXPECTED_INT,
},
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msgpack_jit_parse_i64(
input: *const u8,
len: usize,
pos: usize,
) -> MsgPackJitI64Result {
jit_debug!("[msgpack_jit_parse_i64] pos={}, len={}", pos, len);
if pos >= len {
return MsgPackJitI64Result {
new_pos: pos,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let tag = unsafe { *input.add(pos) };
jit_debug!("[msgpack_jit_parse_i64] tag=0x{:02X}", tag);
if tags::is_positive_fixint(tag) {
return MsgPackJitI64Result {
new_pos: pos + 1,
value: tag as i64,
error: 0,
};
}
if tags::is_negative_fixint(tag) {
return MsgPackJitI64Result {
new_pos: pos + 1,
value: (tag as i8) as i64,
error: 0,
};
}
match tag {
tags::I8 => {
if pos + 1 >= len {
return MsgPackJitI64Result {
new_pos: pos + 1,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let value = unsafe { *input.add(pos + 1) } as i8;
MsgPackJitI64Result {
new_pos: pos + 2,
value: value as i64,
error: 0,
}
}
tags::I16 => {
if pos + 2 >= len {
return MsgPackJitI64Result {
new_pos: pos + 1,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let value = i16::from_be_bytes(unsafe { [*input.add(pos + 1), *input.add(pos + 2)] });
MsgPackJitI64Result {
new_pos: pos + 3,
value: value as i64,
error: 0,
}
}
tags::I32 => {
if pos + 4 >= len {
return MsgPackJitI64Result {
new_pos: pos + 1,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let value = i32::from_be_bytes(unsafe {
[
*input.add(pos + 1),
*input.add(pos + 2),
*input.add(pos + 3),
*input.add(pos + 4),
]
});
MsgPackJitI64Result {
new_pos: pos + 5,
value: value as i64,
error: 0,
}
}
tags::I64 => {
if pos + 8 >= len {
return MsgPackJitI64Result {
new_pos: pos + 1,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let value = i64::from_be_bytes(unsafe {
[
*input.add(pos + 1),
*input.add(pos + 2),
*input.add(pos + 3),
*input.add(pos + 4),
*input.add(pos + 5),
*input.add(pos + 6),
*input.add(pos + 7),
*input.add(pos + 8),
]
});
MsgPackJitI64Result {
new_pos: pos + 9,
value,
error: 0,
}
}
tags::U8 => {
if pos + 1 >= len {
return MsgPackJitI64Result {
new_pos: pos + 1,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let value = unsafe { *input.add(pos + 1) };
MsgPackJitI64Result {
new_pos: pos + 2,
value: value as i64,
error: 0,
}
}
tags::U16 => {
if pos + 2 >= len {
return MsgPackJitI64Result {
new_pos: pos + 1,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let value = u16::from_be_bytes(unsafe { [*input.add(pos + 1), *input.add(pos + 2)] });
MsgPackJitI64Result {
new_pos: pos + 3,
value: value as i64,
error: 0,
}
}
tags::U32 => {
if pos + 4 >= len {
return MsgPackJitI64Result {
new_pos: pos + 1,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let value = u32::from_be_bytes(unsafe {
[
*input.add(pos + 1),
*input.add(pos + 2),
*input.add(pos + 3),
*input.add(pos + 4),
]
});
MsgPackJitI64Result {
new_pos: pos + 5,
value: value as i64,
error: 0,
}
}
tags::U64 => {
if pos + 8 >= len {
return MsgPackJitI64Result {
new_pos: pos + 1,
value: 0,
error: error::UNEXPECTED_EOF,
};
}
let value = u64::from_be_bytes(unsafe {
[
*input.add(pos + 1),
*input.add(pos + 2),
*input.add(pos + 3),
*input.add(pos + 4),
*input.add(pos + 5),
*input.add(pos + 6),
*input.add(pos + 7),
*input.add(pos + 8),
]
});
if value > i64::MAX as u64 {
return MsgPackJitI64Result {
new_pos: pos,
value: 0,
error: error::INT_OVERFLOW,
};
}
MsgPackJitI64Result {
new_pos: pos + 9,
value: value as i64,
error: 0,
}
}
_ => MsgPackJitI64Result {
new_pos: pos,
value: 0,
error: error::EXPECTED_INT,
},
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msgpack_jit_seq_begin(
input: *const u8,
len: usize,
pos: usize,
state_ptr: *mut u64,
) -> MsgPackJitSeqBeginResult {
jit_debug!(
"[msgpack_jit_seq_begin] pos={}, len={}, state_ptr={:p}",
pos,
len,
state_ptr
);
if pos >= len {
return MsgPackJitSeqBeginResult {
new_pos: pos,
count: 0,
error: error::UNEXPECTED_EOF,
};
}
let tag = unsafe { *input.add(pos) };
jit_debug!("[msgpack_jit_seq_begin] tag=0x{:02X}", tag);
let (new_pos, count): (usize, usize) = if tags::is_fixarray(tag) {
let count = (tag & 0x0F) as usize;
(pos + 1, count)
} else {
match tag {
tags::ARRAY16 => {
if pos + 2 >= len {
return MsgPackJitSeqBeginResult {
new_pos: pos + 1,
count: 0,
error: error::UNEXPECTED_EOF,
};
}
let count =
u16::from_be_bytes(unsafe { [*input.add(pos + 1), *input.add(pos + 2)] })
as usize;
(pos + 3, count)
}
tags::ARRAY32 => {
if pos + 4 >= len {
return MsgPackJitSeqBeginResult {
new_pos: pos + 1,
count: 0,
error: error::UNEXPECTED_EOF,
};
}
let count_u32 = u32::from_be_bytes(unsafe {
[
*input.add(pos + 1),
*input.add(pos + 2),
*input.add(pos + 3),
*input.add(pos + 4),
]
});
#[cfg(target_pointer_width = "32")]
if count_u32 > usize::MAX as u32 {
return MsgPackJitSeqBeginResult {
new_pos: pos,
count: 0,
error: error::COUNT_OVERFLOW,
};
}
(pos + 5, count_u32 as usize)
}
_ => {
return MsgPackJitSeqBeginResult {
new_pos: pos,
count: 0,
error: error::EXPECTED_ARRAY,
};
}
}
};
unsafe {
*state_ptr = count as u64;
}
jit_debug!(
"[msgpack_jit_seq_begin] count={}, new_pos={}",
count,
new_pos
);
MsgPackJitSeqBeginResult {
new_pos,
count,
error: 0,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msgpack_jit_seq_is_end(
pos: usize,
state_ptr: *const u64,
) -> MsgPackJitPosEndError {
let remaining = unsafe { *state_ptr };
jit_debug!(
"[msgpack_jit_seq_is_end] pos={}, remaining={}",
pos,
remaining
);
let is_end = remaining == 0;
jit_debug!("[msgpack_jit_seq_is_end] -> is_end={}", is_end);
MsgPackJitPosEndError::new(pos, is_end, 0)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msgpack_jit_seq_next(
pos: usize,
state_ptr: *mut u64,
) -> MsgPackJitPosError {
let remaining = unsafe { *state_ptr };
jit_debug!(
"[msgpack_jit_seq_next] pos={}, remaining={}",
pos,
remaining
);
if remaining == 0 {
return MsgPackJitPosError {
new_pos: pos,
error: error::SEQ_UNDERFLOW,
};
}
unsafe {
*state_ptr = remaining - 1;
}
jit_debug!("[msgpack_jit_seq_next] -> new_remaining={}", remaining - 1);
MsgPackJitPosError {
new_pos: pos,
error: 0,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msgpack_jit_read_bin_header(
input: *const u8,
len: usize,
pos: usize,
) -> MsgPackJitBinHeaderResult {
jit_debug!("[msgpack_jit_read_bin_header] pos={}, len={}", pos, len);
if pos >= len {
return MsgPackJitBinHeaderResult {
new_pos: pos,
len: 0,
error: error::UNEXPECTED_EOF,
};
}
let tag = unsafe { *input.add(pos) };
jit_debug!("[msgpack_jit_read_bin_header] tag=0x{:02X}", tag);
let (new_pos, data_len): (usize, usize) = match tag {
tags::BIN8 => {
if pos + 1 >= len {
return MsgPackJitBinHeaderResult {
new_pos: pos + 1,
len: 0,
error: error::UNEXPECTED_EOF,
};
}
let data_len = unsafe { *input.add(pos + 1) } as usize;
(pos + 2, data_len)
}
tags::BIN16 => {
if pos + 2 >= len {
return MsgPackJitBinHeaderResult {
new_pos: pos + 1,
len: 0,
error: error::UNEXPECTED_EOF,
};
}
let data_len =
u16::from_be_bytes(unsafe { [*input.add(pos + 1), *input.add(pos + 2)] }) as usize;
(pos + 3, data_len)
}
tags::BIN32 => {
if pos + 4 >= len {
return MsgPackJitBinHeaderResult {
new_pos: pos + 1,
len: 0,
error: error::UNEXPECTED_EOF,
};
}
let data_len_u32 = u32::from_be_bytes(unsafe {
[
*input.add(pos + 1),
*input.add(pos + 2),
*input.add(pos + 3),
*input.add(pos + 4),
]
});
#[cfg(target_pointer_width = "32")]
if data_len_u32 > usize::MAX as u32 {
return MsgPackJitBinHeaderResult {
new_pos: pos,
len: 0,
error: error::COUNT_OVERFLOW,
};
}
(pos + 5, data_len_u32 as usize)
}
_ => {
return MsgPackJitBinHeaderResult {
new_pos: pos,
len: 0,
error: error::EXPECTED_BIN,
};
}
};
if new_pos + data_len > len {
return MsgPackJitBinHeaderResult {
new_pos,
len: 0,
error: error::UNEXPECTED_EOF,
};
}
jit_debug!(
"[msgpack_jit_read_bin_header] data_len={}, new_pos={}",
data_len,
new_pos
);
MsgPackJitBinHeaderResult {
new_pos,
len: data_len,
error: 0,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msgpack_jit_bulk_copy_u8(dest: *mut u8, src: *const u8, count: usize) {
jit_debug!(
"[msgpack_jit_bulk_copy_u8] dest={:p}, src={:p}, count={}",
dest,
src,
count
);
unsafe {
core::ptr::copy_nonoverlapping(src, dest, count);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_bool() {
let input = [0xC2];
let result = unsafe { msgpack_jit_parse_bool(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, 0);
assert!(!result.value());
assert_eq!(result.new_pos(), 1);
let input = [0xC3];
let result = unsafe { msgpack_jit_parse_bool(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, 0);
assert!(result.value());
assert_eq!(result.new_pos(), 1);
let input = [0x00];
let result = unsafe { msgpack_jit_parse_bool(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, error::EXPECTED_BOOL);
}
#[test]
fn test_parse_u64_fixint() {
let input = [0x00];
let result = unsafe { msgpack_jit_parse_u64(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, 0);
assert_eq!(result.value, 0);
assert_eq!(result.new_pos, 1);
let input = [0x7F];
let result = unsafe { msgpack_jit_parse_u64(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, 0);
assert_eq!(result.value, 127);
assert_eq!(result.new_pos, 1);
}
#[test]
fn test_parse_u64_typed() {
let input = [0xCC, 200];
let result = unsafe { msgpack_jit_parse_u64(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, 0);
assert_eq!(result.value, 200);
assert_eq!(result.new_pos, 2);
let input = [0xCD, 0x03, 0xE8]; let result = unsafe { msgpack_jit_parse_u64(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, 0);
assert_eq!(result.value, 1000);
assert_eq!(result.new_pos, 3);
let input = [0xCE, 0x00, 0x01, 0x86, 0xA0]; let result = unsafe { msgpack_jit_parse_u64(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, 0);
assert_eq!(result.value, 100000);
assert_eq!(result.new_pos, 5);
}
#[test]
fn test_parse_i64_fixint() {
let input = [42];
let result = unsafe { msgpack_jit_parse_i64(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, 0);
assert_eq!(result.value, 42);
assert_eq!(result.new_pos, 1);
let input = [0xFF];
let result = unsafe { msgpack_jit_parse_i64(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, 0);
assert_eq!(result.value, -1);
assert_eq!(result.new_pos, 1);
let input = [0xE0];
let result = unsafe { msgpack_jit_parse_i64(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, 0);
assert_eq!(result.value, -32);
assert_eq!(result.new_pos, 1);
}
#[test]
fn test_parse_i64_typed() {
let input = [0xD0, 0x9C]; let result = unsafe { msgpack_jit_parse_i64(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, 0);
assert_eq!(result.value, -100);
assert_eq!(result.new_pos, 2);
let input = [0xD1, 0xFC, 0x18]; let result = unsafe { msgpack_jit_parse_i64(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, 0);
assert_eq!(result.value, -1000);
assert_eq!(result.new_pos, 3);
}
#[test]
fn test_seq_begin_fixarray() {
let input = [0x93, 0x01, 0x02, 0x03];
let mut state: u64 = 0;
let result = unsafe { msgpack_jit_seq_begin(input.as_ptr(), input.len(), 0, &mut state) };
assert_eq!(result.error, 0);
assert_eq!(result.count, 3);
assert_eq!(result.new_pos, 1);
assert_eq!(state, 3);
}
#[test]
fn test_seq_begin_array16() {
let input = [0xDC, 0x01, 0x00];
let mut state: u64 = 0;
let result = unsafe { msgpack_jit_seq_begin(input.as_ptr(), input.len(), 0, &mut state) };
assert_eq!(result.error, 0);
assert_eq!(result.count, 256);
assert_eq!(result.new_pos, 3);
assert_eq!(state, 256);
}
#[test]
fn test_seq_operations() {
let input = [0x93, 0xC3, 0xC2, 0xC3];
let mut state: u64 = 0;
let result = unsafe { msgpack_jit_seq_begin(input.as_ptr(), input.len(), 0, &mut state) };
assert_eq!(result.error, 0);
assert_eq!(result.count, 3);
assert_eq!(result.new_pos, 1);
assert_eq!(state, 3);
let result = unsafe { msgpack_jit_seq_is_end(result.new_pos, &state) };
assert_eq!(result.error, 0);
assert!(!result.is_end());
let result = unsafe { msgpack_jit_seq_next(result.pos(), &mut state) };
assert_eq!(result.error, 0);
assert_eq!(state, 2);
let result = unsafe { msgpack_jit_seq_next(result.new_pos, &mut state) };
assert_eq!(result.error, 0);
assert_eq!(state, 1);
let result = unsafe { msgpack_jit_seq_next(result.new_pos, &mut state) };
assert_eq!(result.error, 0);
assert_eq!(state, 0);
let result = unsafe { msgpack_jit_seq_is_end(result.new_pos, &state) };
assert_eq!(result.error, 0);
assert!(result.is_end());
}
#[test]
fn test_bin_header() {
let input = [0xC4, 0x03, 0xAA, 0xBB, 0xCC];
let result = unsafe { msgpack_jit_read_bin_header(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, 0);
assert_eq!(result.len, 3);
assert_eq!(result.new_pos, 2);
let mut input = vec![0xC5, 0x01, 0x00];
input.extend(vec![0u8; 256]);
let result = unsafe { msgpack_jit_read_bin_header(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, 0);
assert_eq!(result.len, 256);
assert_eq!(result.new_pos, 3);
}
#[test]
fn test_eof_errors() {
let input: [u8; 0] = [];
let result = unsafe { msgpack_jit_parse_bool(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, error::UNEXPECTED_EOF);
let result = unsafe { msgpack_jit_parse_u64(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, error::UNEXPECTED_EOF);
let input = [0xCD, 0x00]; let result = unsafe { msgpack_jit_parse_u64(input.as_ptr(), input.len(), 0) };
assert_eq!(result.error, error::UNEXPECTED_EOF);
}
}