use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use integer_encoding::{VarIntReader, VarIntWriter};
use std::convert::{From, TryFrom};
use std::io;
use super::{
TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier, TMapIdentifier,
TMessageIdentifier, TMessageType,
};
use super::{TOutputProtocol, TOutputProtocolFactory, TSetIdentifier, TStructIdentifier, TType};
use crate::transport::{TReadTransport, TWriteTransport};
const COMPACT_PROTOCOL_ID: u8 = 0x82;
const COMPACT_VERSION: u8 = 0x01;
const COMPACT_VERSION_MASK: u8 = 0x1F;
#[derive(Debug)]
pub struct TCompactInputProtocol<T>
where
T: TReadTransport,
{
last_read_field_id: i16,
read_field_id_stack: Vec<i16>,
pending_read_bool_value: Option<bool>,
transport: T,
}
impl<T> TCompactInputProtocol<T>
where
T: TReadTransport,
{
pub fn new(transport: T) -> TCompactInputProtocol<T> {
TCompactInputProtocol {
last_read_field_id: 0,
read_field_id_stack: Vec::new(),
pending_read_bool_value: None,
transport,
}
}
fn read_list_set_begin(&mut self) -> crate::Result<(TType, i32)> {
let header = self.read_byte()?;
let element_type = collection_u8_to_type(header & 0x0F)?;
let element_count;
let possible_element_count = (header & 0xF0) >> 4;
if possible_element_count != 15 {
element_count = possible_element_count as i32;
} else {
element_count = self.transport.read_varint::<u32>()? as i32;
}
Ok((element_type, element_count))
}
}
impl<T> TInputProtocol for TCompactInputProtocol<T>
where
T: TReadTransport,
{
fn read_message_begin(&mut self) -> crate::Result<TMessageIdentifier> {
let compact_id = self.read_byte()?;
if compact_id != COMPACT_PROTOCOL_ID {
Err(crate::Error::Protocol(crate::ProtocolError {
kind: crate::ProtocolErrorKind::BadVersion,
message: format!("invalid compact protocol header {:?}", compact_id),
}))
} else {
Ok(())
}?;
let type_and_byte = self.read_byte()?;
let received_version = type_and_byte & COMPACT_VERSION_MASK;
if received_version != COMPACT_VERSION {
Err(crate::Error::Protocol(crate::ProtocolError {
kind: crate::ProtocolErrorKind::BadVersion,
message: format!(
"cannot process compact protocol version {:?}",
received_version
),
}))
} else {
Ok(())
}?;
let message_type: TMessageType = TMessageType::try_from(type_and_byte >> 5)?;
let sequence_number = self.transport.read_varint::<u32>()? as i32;
let service_call_name = self.read_string()?;
self.last_read_field_id = 0;
Ok(TMessageIdentifier::new(
service_call_name,
message_type,
sequence_number,
))
}
fn read_message_end(&mut self) -> crate::Result<()> {
Ok(())
}
fn read_struct_begin(&mut self) -> crate::Result<Option<TStructIdentifier>> {
self.read_field_id_stack.push(self.last_read_field_id);
self.last_read_field_id = 0;
Ok(None)
}
fn read_struct_end(&mut self) -> crate::Result<()> {
self.last_read_field_id = self
.read_field_id_stack
.pop()
.expect("should have previous field ids");
Ok(())
}
fn read_field_begin(&mut self) -> crate::Result<TFieldIdentifier> {
let field_type = self.read_byte()?;
let field_delta = (field_type & 0xF0) >> 4;
let field_type = match field_type & 0x0F {
0x01 => {
self.pending_read_bool_value = Some(true);
Ok(TType::Bool)
}
0x02 => {
self.pending_read_bool_value = Some(false);
Ok(TType::Bool)
}
ttu8 => u8_to_type(ttu8),
}?;
match field_type {
TType::Stop => Ok(
TFieldIdentifier::new::<Option<String>, String, Option<i16>>(
None,
TType::Stop,
None,
),
),
_ => {
if field_delta != 0 {
self.last_read_field_id += field_delta as i16;
} else {
self.last_read_field_id = self.read_i16()?;
};
Ok(TFieldIdentifier {
name: None,
field_type,
id: Some(self.last_read_field_id),
})
}
}
}
fn read_field_end(&mut self) -> crate::Result<()> {
Ok(())
}
fn read_bool(&mut self) -> crate::Result<bool> {
match self.pending_read_bool_value.take() {
Some(b) => Ok(b),
None => {
let b = self.read_byte()?;
match b {
0x01 => Ok(true),
0x02 => Ok(false),
unkn => Err(crate::Error::Protocol(crate::ProtocolError {
kind: crate::ProtocolErrorKind::InvalidData,
message: format!("cannot convert {} into bool", unkn),
})),
}
}
}
}
fn read_bytes(&mut self) -> crate::Result<Vec<u8>> {
let len = self.transport.read_varint::<u32>()?;
let mut buf = vec![0u8; len as usize];
self.transport
.read_exact(&mut buf)
.map_err(From::from)
.map(|_| buf)
}
fn read_i8(&mut self) -> crate::Result<i8> {
self.read_byte().map(|i| i as i8)
}
fn read_i16(&mut self) -> crate::Result<i16> {
self.transport.read_varint::<i16>().map_err(From::from)
}
fn read_i32(&mut self) -> crate::Result<i32> {
self.transport.read_varint::<i32>().map_err(From::from)
}
fn read_i64(&mut self) -> crate::Result<i64> {
self.transport.read_varint::<i64>().map_err(From::from)
}
fn read_double(&mut self) -> crate::Result<f64> {
self.transport
.read_f64::<LittleEndian>()
.map_err(From::from)
}
fn read_string(&mut self) -> crate::Result<String> {
let bytes = self.read_bytes()?;
String::from_utf8(bytes).map_err(From::from)
}
fn read_list_begin(&mut self) -> crate::Result<TListIdentifier> {
let (element_type, element_count) = self.read_list_set_begin()?;
Ok(TListIdentifier::new(element_type, element_count))
}
fn read_list_end(&mut self) -> crate::Result<()> {
Ok(())
}
fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier> {
let (element_type, element_count) = self.read_list_set_begin()?;
Ok(TSetIdentifier::new(element_type, element_count))
}
fn read_set_end(&mut self) -> crate::Result<()> {
Ok(())
}
fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier> {
let element_count = self.transport.read_varint::<u32>()? as i32;
if element_count == 0 {
Ok(TMapIdentifier::new(None, None, 0))
} else {
let type_header = self.read_byte()?;
let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
let val_type = collection_u8_to_type(type_header & 0x0F)?;
Ok(TMapIdentifier::new(key_type, val_type, element_count))
}
}
fn read_map_end(&mut self) -> crate::Result<()> {
Ok(())
}
fn read_byte(&mut self) -> crate::Result<u8> {
let mut buf = [0u8; 1];
self.transport
.read_exact(&mut buf)
.map_err(From::from)
.map(|_| buf[0])
}
}
impl<T> io::Seek for TCompactInputProtocol<T>
where
T: io::Seek + TReadTransport,
{
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
self.transport.seek(pos)
}
}
#[derive(Default)]
pub struct TCompactInputProtocolFactory;
impl TCompactInputProtocolFactory {
pub fn new() -> TCompactInputProtocolFactory {
TCompactInputProtocolFactory {}
}
}
impl TInputProtocolFactory for TCompactInputProtocolFactory {
fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send> {
Box::new(TCompactInputProtocol::new(transport))
}
}
#[derive(Debug)]
pub struct TCompactOutputProtocol<T>
where
T: TWriteTransport,
{
last_write_field_id: i16,
write_field_id_stack: Vec<i16>,
pending_write_bool_field_identifier: Option<TFieldIdentifier>,
transport: T,
}
impl<T> TCompactOutputProtocol<T>
where
T: TWriteTransport,
{
pub fn new(transport: T) -> TCompactOutputProtocol<T> {
TCompactOutputProtocol {
last_write_field_id: 0,
write_field_id_stack: Vec::new(),
pending_write_bool_field_identifier: None,
transport,
}
}
fn write_field_header(&mut self, field_type: u8, field_id: i16) -> crate::Result<()> {
let field_delta = field_id - self.last_write_field_id;
if field_delta > 0 && field_delta < 15 {
self.write_byte(((field_delta as u8) << 4) | field_type)?;
} else {
self.write_byte(field_type)?;
self.write_i16(field_id)?;
}
self.last_write_field_id = field_id;
Ok(())
}
fn write_list_set_begin(
&mut self,
element_type: TType,
element_count: i32,
) -> crate::Result<()> {
let elem_identifier = collection_type_to_u8(element_type);
if element_count <= 14 {
let header = (element_count as u8) << 4 | elem_identifier;
self.write_byte(header)
} else {
let header = 0xF0 | elem_identifier;
self.write_byte(header)?;
self.transport
.write_varint(element_count as u32)
.map_err(From::from)
.map(|_| ())
}
}
fn assert_no_pending_bool_write(&self) {
if let Some(ref f) = self.pending_write_bool_field_identifier {
panic!("pending bool field {:?} not written", f)
}
}
}
impl<T> TOutputProtocol for TCompactOutputProtocol<T>
where
T: TWriteTransport,
{
fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> {
self.write_byte(COMPACT_PROTOCOL_ID)?;
self.write_byte((u8::from(identifier.message_type) << 5) | COMPACT_VERSION)?;
self.transport
.write_varint(identifier.sequence_number as u32)?;
self.write_string(&identifier.name)?;
Ok(())
}
fn write_message_end(&mut self) -> crate::Result<()> {
self.assert_no_pending_bool_write();
Ok(())
}
fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> {
self.write_field_id_stack.push(self.last_write_field_id);
self.last_write_field_id = 0;
Ok(())
}
fn write_struct_end(&mut self) -> crate::Result<()> {
self.assert_no_pending_bool_write();
self.last_write_field_id = self
.write_field_id_stack
.pop()
.expect("should have previous field ids");
Ok(())
}
fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> {
match identifier.field_type {
TType::Bool => {
if self.pending_write_bool_field_identifier.is_some() {
panic!(
"should not have a pending bool while writing another bool with id: \
{:?}",
identifier
)
}
self.pending_write_bool_field_identifier = Some(identifier.clone());
Ok(())
}
_ => {
let field_type = type_to_u8(identifier.field_type);
let field_id = identifier.id.expect("non-stop field should have field id");
self.write_field_header(field_type, field_id)
}
}
}
fn write_field_end(&mut self) -> crate::Result<()> {
self.assert_no_pending_bool_write();
Ok(())
}
fn write_field_stop(&mut self) -> crate::Result<()> {
self.assert_no_pending_bool_write();
self.write_byte(type_to_u8(TType::Stop))
}
fn write_bool(&mut self, b: bool) -> crate::Result<()> {
match self.pending_write_bool_field_identifier.take() {
Some(pending) => {
let field_id = pending.id.expect("bool field should have a field id");
let field_type_as_u8 = if b { 0x01 } else { 0x02 };
self.write_field_header(field_type_as_u8, field_id)
}
None => {
if b {
self.write_byte(0x01)
} else {
self.write_byte(0x02)
}
}
}
}
fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> {
self.transport.write_varint(b.len() as u32)?;
self.transport.write_all(b).map_err(From::from)
}
fn write_i8(&mut self, i: i8) -> crate::Result<()> {
self.write_byte(i as u8)
}
fn write_i16(&mut self, i: i16) -> crate::Result<()> {
self.transport
.write_varint(i)
.map_err(From::from)
.map(|_| ())
}
fn write_i32(&mut self, i: i32) -> crate::Result<()> {
self.transport
.write_varint(i)
.map_err(From::from)
.map(|_| ())
}
fn write_i64(&mut self, i: i64) -> crate::Result<()> {
self.transport
.write_varint(i)
.map_err(From::from)
.map(|_| ())
}
fn write_double(&mut self, d: f64) -> crate::Result<()> {
self.transport
.write_f64::<LittleEndian>(d)
.map_err(From::from)
}
fn write_string(&mut self, s: &str) -> crate::Result<()> {
self.write_bytes(s.as_bytes())
}
fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> {
self.write_list_set_begin(identifier.element_type, identifier.size)
}
fn write_list_end(&mut self) -> crate::Result<()> {
Ok(())
}
fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> {
self.write_list_set_begin(identifier.element_type, identifier.size)
}
fn write_set_end(&mut self) -> crate::Result<()> {
Ok(())
}
fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> {
if identifier.size == 0 {
self.write_byte(0)
} else {
self.transport.write_varint(identifier.size as u32)?;
let key_type = identifier
.key_type
.expect("map identifier to write should contain key type");
let key_type_byte = collection_type_to_u8(key_type) << 4;
let val_type = identifier
.value_type
.expect("map identifier to write should contain value type");
let val_type_byte = collection_type_to_u8(val_type);
let map_type_header = key_type_byte | val_type_byte;
self.write_byte(map_type_header)
}
}
fn write_map_end(&mut self) -> crate::Result<()> {
Ok(())
}
fn flush(&mut self) -> crate::Result<()> {
self.transport.flush().map_err(From::from)
}
fn write_byte(&mut self, b: u8) -> crate::Result<()> {
self.transport.write(&[b]).map_err(From::from).map(|_| ())
}
}
#[derive(Default)]
pub struct TCompactOutputProtocolFactory;
impl TCompactOutputProtocolFactory {
pub fn new() -> TCompactOutputProtocolFactory {
TCompactOutputProtocolFactory {}
}
}
impl TOutputProtocolFactory for TCompactOutputProtocolFactory {
fn create(
&self,
transport: Box<dyn TWriteTransport + Send>,
) -> Box<dyn TOutputProtocol + Send> {
Box::new(TCompactOutputProtocol::new(transport))
}
}
fn collection_type_to_u8(field_type: TType) -> u8 {
match field_type {
TType::Bool => 0x01,
f => type_to_u8(f),
}
}
fn type_to_u8(field_type: TType) -> u8 {
match field_type {
TType::Stop => 0x00,
TType::I08 => 0x03, TType::I16 => 0x04,
TType::I32 => 0x05,
TType::I64 => 0x06,
TType::Double => 0x07,
TType::String => 0x08,
TType::List => 0x09,
TType::Set => 0x0A,
TType::Map => 0x0B,
TType::Struct => 0x0C,
_ => panic!(format!(
"should not have attempted to convert {} to u8",
field_type
)),
}
}
fn collection_u8_to_type(b: u8) -> crate::Result<TType> {
match b {
0x01 => Ok(TType::Bool),
o => u8_to_type(o),
}
}
fn u8_to_type(b: u8) -> crate::Result<TType> {
match b {
0x00 => Ok(TType::Stop),
0x03 => Ok(TType::I08), 0x04 => Ok(TType::I16),
0x05 => Ok(TType::I32),
0x06 => Ok(TType::I64),
0x07 => Ok(TType::Double),
0x08 => Ok(TType::String),
0x09 => Ok(TType::List),
0x0A => Ok(TType::Set),
0x0B => Ok(TType::Map),
0x0C => Ok(TType::Struct),
unkn => Err(crate::Error::Protocol(crate::ProtocolError {
kind: crate::ProtocolErrorKind::InvalidData,
message: format!("cannot convert {} into TType", unkn),
})),
}
}
#[cfg(test)]
mod tests {
use std::i32;
use crate::protocol::{
TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
};
use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
use super::*;
#[test]
fn must_write_message_begin_largest_maximum_positive_sequence_number() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
"bar",
TMessageType::Reply,
i32::MAX
)));
#[rustfmt::skip]
let expected: [u8; 11] = [
0x82, 0x41, 0xFF,
0xFF,
0xFF,
0xFF,
0x07, 0x03, 0x62,
0x61,
0x72 ,
];
assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_read_message_begin_largest_maximum_positive_sequence_number() {
let (mut i_prot, _) = test_objects();
#[rustfmt::skip]
let source_bytes: [u8; 11] = [
0x82, 0x41, 0xFF,
0xFF,
0xFF,
0xFF,
0x07, 0x03, 0x62,
0x61,
0x72 ,
];
i_prot.transport.set_readable_bytes(&source_bytes);
let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MAX);
let res = assert_success!(i_prot.read_message_begin());
assert_eq!(&expected, &res);
}
#[test]
fn must_write_message_begin_positive_sequence_number_0() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
"foo",
TMessageType::Call,
431
)));
#[rustfmt::skip]
let expected: [u8; 8] = [
0x82, 0x21, 0xAF,
0x03, 0x03, 0x66,
0x6F,
0x6F ,
];
assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_read_message_begin_positive_sequence_number_0() {
let (mut i_prot, _) = test_objects();
#[rustfmt::skip]
let source_bytes: [u8; 8] = [
0x82, 0x21, 0xAF,
0x03, 0x03, 0x66,
0x6F,
0x6F ,
];
i_prot.transport.set_readable_bytes(&source_bytes);
let expected = TMessageIdentifier::new("foo", TMessageType::Call, 431);
let res = assert_success!(i_prot.read_message_begin());
assert_eq!(&expected, &res);
}
#[test]
fn must_write_message_begin_positive_sequence_number_1() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
"bar",
TMessageType::Reply,
991_828
)));
#[rustfmt::skip]
let expected: [u8; 9] = [
0x82, 0x41, 0xD4,
0xC4,
0x3C, 0x03, 0x62,
0x61,
0x72 ,
];
assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_read_message_begin_positive_sequence_number_1() {
let (mut i_prot, _) = test_objects();
#[rustfmt::skip]
let source_bytes: [u8; 9] = [
0x82, 0x41, 0xD4,
0xC4,
0x3C, 0x03, 0x62,
0x61,
0x72 ,
];
i_prot.transport.set_readable_bytes(&source_bytes);
let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 991_828);
let res = assert_success!(i_prot.read_message_begin());
assert_eq!(&expected, &res);
}
#[test]
fn must_write_message_begin_zero_sequence_number() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
"bar",
TMessageType::Reply,
0
)));
#[rustfmt::skip]
let expected: [u8; 7] = [
0x82, 0x41, 0x00, 0x03, 0x62,
0x61,
0x72 ,
];
assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_read_message_begin_zero_sequence_number() {
let (mut i_prot, _) = test_objects();
#[rustfmt::skip]
let source_bytes: [u8; 7] = [
0x82, 0x41, 0x00, 0x03, 0x62,
0x61,
0x72 ,
];
i_prot.transport.set_readable_bytes(&source_bytes);
let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 0);
let res = assert_success!(i_prot.read_message_begin());
assert_eq!(&expected, &res);
}
#[test]
fn must_write_message_begin_largest_minimum_negative_sequence_number() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
"bar",
TMessageType::Reply,
i32::MIN
)));
#[rustfmt::skip]
let expected: [u8; 11] = [
0x82, 0x41, 0x80,
0x80,
0x80,
0x80,
0x08, 0x03, 0x62,
0x61,
0x72 ,
];
assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_read_message_begin_largest_minimum_negative_sequence_number() {
let (mut i_prot, _) = test_objects();
#[rustfmt::skip]
let source_bytes: [u8; 11] = [
0x82, 0x41, 0x80,
0x80,
0x80,
0x80,
0x08, 0x03, 0x62,
0x61,
0x72 ,
];
i_prot.transport.set_readable_bytes(&source_bytes);
let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MIN);
let res = assert_success!(i_prot.read_message_begin());
assert_eq!(&expected, &res);
}
#[test]
fn must_write_message_begin_negative_sequence_number_0() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
"foo",
TMessageType::Call,
-431
)));
#[rustfmt::skip]
let expected: [u8; 11] = [
0x82, 0x21, 0xD1,
0xFC,
0xFF,
0xFF,
0x0F, 0x03, 0x66,
0x6F,
0x6F ,
];
assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_read_message_begin_negative_sequence_number_0() {
let (mut i_prot, _) = test_objects();
#[rustfmt::skip]
let source_bytes: [u8; 11] = [
0x82, 0x21, 0xD1,
0xFC,
0xFF,
0xFF,
0x0F, 0x03, 0x66,
0x6F,
0x6F ,
];
i_prot.transport.set_readable_bytes(&source_bytes);
let expected = TMessageIdentifier::new("foo", TMessageType::Call, -431);
let res = assert_success!(i_prot.read_message_begin());
assert_eq!(&expected, &res);
}
#[test]
fn must_write_message_begin_negative_sequence_number_1() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
"foo",
TMessageType::Call,
-73_184_125
)));
#[rustfmt::skip]
let expected: [u8; 11] = [
0x82, 0x21, 0x83,
0x99,
0x8D,
0xDD,
0x0F, 0x03, 0x66,
0x6F,
0x6F ,
];
assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_read_message_begin_negative_sequence_number_1() {
let (mut i_prot, _) = test_objects();
#[rustfmt::skip]
let source_bytes: [u8; 11] = [
0x82, 0x21, 0x83,
0x99,
0x8D,
0xDD,
0x0F, 0x03, 0x66,
0x6F,
0x6F ,
];
i_prot.transport.set_readable_bytes(&source_bytes);
let expected = TMessageIdentifier::new("foo", TMessageType::Call, -73_184_125);
let res = assert_success!(i_prot.read_message_begin());
assert_eq!(&expected, &res);
}
#[test]
fn must_write_message_begin_negative_sequence_number_2() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
"foo",
TMessageType::Call,
-1_073_741_823
)));
#[rustfmt::skip]
let expected: [u8; 11] = [
0x82, 0x21, 0x81,
0x80,
0x80,
0x80,
0x0C, 0x03, 0x66,
0x6F,
0x6F ,
];
assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_read_message_begin_negative_sequence_number_2() {
let (mut i_prot, _) = test_objects();
#[rustfmt::skip]
let source_bytes: [u8; 11] = [
0x82, 0x21, 0x81,
0x80,
0x80,
0x80,
0x0C, 0x03, 0x66,
0x6F,
0x6F, ];
i_prot.transport.set_readable_bytes(&source_bytes);
let expected = TMessageIdentifier::new("foo", TMessageType::Call, -1_073_741_823);
let res = assert_success!(i_prot.read_message_begin());
assert_eq!(&expected, &res);
}
#[test]
fn must_round_trip_upto_i64_maxvalue() {
for i in 0..64 {
let (mut i_prot, mut o_prot) = test_objects();
let val: i64 = ((1u64 << i) - 1) as i64;
o_prot
.write_field_begin(&TFieldIdentifier::new("val", TType::I64, 1))
.unwrap();
o_prot.write_i64(val).unwrap();
o_prot.write_field_end().unwrap();
o_prot.flush().unwrap();
copy_write_buffer_to_read_buffer!(o_prot);
i_prot.read_field_begin().unwrap();
assert_eq!(val, i_prot.read_i64().unwrap());
}
}
#[test]
fn must_round_trip_message_begin() {
let (mut i_prot, mut o_prot) = test_objects();
let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948);
assert_success!(o_prot.write_message_begin(&ident));
copy_write_buffer_to_read_buffer!(o_prot);
let res = assert_success!(i_prot.read_message_begin());
assert_eq!(&res, &ident);
}
#[test]
fn must_write_message_end() {
assert_no_write(|o| o.write_message_end());
}
#[test]
fn must_write_struct_with_delta_fields() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
#[rustfmt::skip]
let expected: [u8; 5] = [
0x03, 0x00, 0x44, 0x59, 0x00 ,
];
assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_round_trip_struct_with_delta_fields() {
let (mut i_prot, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
assert_success!(o_prot.write_field_begin(&field_ident_1));
assert_success!(o_prot.write_field_end());
let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
assert_success!(o_prot.write_field_begin(&field_ident_2));
assert_success!(o_prot.write_field_end());
let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
assert_success!(o_prot.write_field_begin(&field_ident_3));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
copy_write_buffer_to_read_buffer!(o_prot);
assert_success!(i_prot.read_struct_begin());
let read_ident_1 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_1,
TFieldIdentifier {
name: None,
..field_ident_1
}
);
assert_success!(i_prot.read_field_end());
let read_ident_2 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_2,
TFieldIdentifier {
name: None,
..field_ident_2
}
);
assert_success!(i_prot.read_field_end());
let read_ident_3 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_3,
TFieldIdentifier {
name: None,
..field_ident_3
}
);
assert_success!(i_prot.read_field_end());
let read_ident_4 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_4,
TFieldIdentifier {
name: None,
field_type: TType::Stop,
id: None,
}
);
assert_success!(i_prot.read_struct_end());
}
#[test]
fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
#[rustfmt::skip]
let expected: [u8; 4] = [
0x15, 0x1A, 0x48, 0x00 ,
];
assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
let (mut i_prot, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
assert_success!(o_prot.write_field_begin(&field_ident_1));
assert_success!(o_prot.write_field_end());
let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
assert_success!(o_prot.write_field_begin(&field_ident_2));
assert_success!(o_prot.write_field_end());
let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
assert_success!(o_prot.write_field_begin(&field_ident_3));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
copy_write_buffer_to_read_buffer!(o_prot);
assert_success!(i_prot.read_struct_begin());
let read_ident_1 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_1,
TFieldIdentifier {
name: None,
..field_ident_1
}
);
assert_success!(i_prot.read_field_end());
let read_ident_2 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_2,
TFieldIdentifier {
name: None,
..field_ident_2
}
);
assert_success!(i_prot.read_field_end());
let read_ident_3 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_3,
TFieldIdentifier {
name: None,
..field_ident_3
}
);
assert_success!(i_prot.read_field_end());
let read_ident_4 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_4,
TFieldIdentifier {
name: None,
field_type: TType::Stop,
id: None,
}
);
assert_success!(i_prot.read_struct_end());
}
#[test]
fn must_write_struct_with_long_fields() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
#[rustfmt::skip]
let expected: [u8; 8] = [
0x05, 0x00, 0x06, 0x20, 0x0A, 0xC6,
0x01, 0x00 ,
];
assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_round_trip_struct_with_long_fields() {
let (mut i_prot, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
assert_success!(o_prot.write_field_begin(&field_ident_1));
assert_success!(o_prot.write_field_end());
let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
assert_success!(o_prot.write_field_begin(&field_ident_2));
assert_success!(o_prot.write_field_end());
let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
assert_success!(o_prot.write_field_begin(&field_ident_3));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
copy_write_buffer_to_read_buffer!(o_prot);
assert_success!(i_prot.read_struct_begin());
let read_ident_1 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_1,
TFieldIdentifier {
name: None,
..field_ident_1
}
);
assert_success!(i_prot.read_field_end());
let read_ident_2 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_2,
TFieldIdentifier {
name: None,
..field_ident_2
}
);
assert_success!(i_prot.read_field_end());
let read_ident_3 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_3,
TFieldIdentifier {
name: None,
..field_ident_3
}
);
assert_success!(i_prot.read_field_end());
let read_ident_4 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_4,
TFieldIdentifier {
name: None,
field_type: TType::Stop,
id: None,
}
);
assert_success!(i_prot.read_struct_end());
}
#[test]
fn must_write_struct_with_mix_of_long_and_delta_fields() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
#[rustfmt::skip]
let expected: [u8; 10] = [
0x16, 0x85, 0x0A, 0xD0,
0x0F, 0x0A, 0xA2,
0x1F, 0x3A, 0x00 ,
];
assert_eq_written_bytes!(o_prot, expected);
}
#[allow(clippy::cognitive_complexity)]
#[test]
fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
let (mut i_prot, mut o_prot) = test_objects();
let struct_ident = TStructIdentifier::new("foo");
assert_success!(o_prot.write_struct_begin(&struct_ident));
let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
assert_success!(o_prot.write_field_begin(&field_ident_1));
assert_success!(o_prot.write_field_end());
let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
assert_success!(o_prot.write_field_begin(&field_ident_2));
assert_success!(o_prot.write_field_end());
let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
assert_success!(o_prot.write_field_begin(&field_ident_3));
assert_success!(o_prot.write_field_end());
let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
assert_success!(o_prot.write_field_begin(&field_ident_4));
assert_success!(o_prot.write_field_end());
let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
assert_success!(o_prot.write_field_begin(&field_ident_5));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
copy_write_buffer_to_read_buffer!(o_prot);
assert_success!(i_prot.read_struct_begin());
let read_ident_1 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_1,
TFieldIdentifier {
name: None,
..field_ident_1
}
);
assert_success!(i_prot.read_field_end());
let read_ident_2 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_2,
TFieldIdentifier {
name: None,
..field_ident_2
}
);
assert_success!(i_prot.read_field_end());
let read_ident_3 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_3,
TFieldIdentifier {
name: None,
..field_ident_3
}
);
assert_success!(i_prot.read_field_end());
let read_ident_4 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_4,
TFieldIdentifier {
name: None,
..field_ident_4
}
);
assert_success!(i_prot.read_field_end());
let read_ident_5 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_5,
TFieldIdentifier {
name: None,
..field_ident_5
}
);
assert_success!(i_prot.read_field_end());
let read_ident_6 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_6,
TFieldIdentifier {
name: None,
field_type: TType::Stop,
id: None,
}
);
assert_success!(i_prot.read_struct_end());
}
#[test]
fn must_write_nested_structs_0() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
#[rustfmt::skip]
let expected: [u8; 7] = [
0x16, 0x85, 0x73, 0x07, 0x30, 0x00, 0x00 ,
];
assert_eq_written_bytes!(o_prot, expected);
}
#[allow(clippy::cognitive_complexity)]
#[test]
fn must_round_trip_nested_structs_0() {
let (mut i_prot, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
assert_success!(o_prot.write_field_begin(&field_ident_1));
assert_success!(o_prot.write_field_end());
let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
assert_success!(o_prot.write_field_begin(&field_ident_2));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
assert_success!(o_prot.write_field_begin(&field_ident_3));
assert_success!(o_prot.write_field_end());
let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
assert_success!(o_prot.write_field_begin(&field_ident_4));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
copy_write_buffer_to_read_buffer!(o_prot);
assert_success!(i_prot.read_struct_begin());
let read_ident_1 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_1,
TFieldIdentifier {
name: None,
..field_ident_1
}
);
assert_success!(i_prot.read_field_end());
let read_ident_2 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_2,
TFieldIdentifier {
name: None,
..field_ident_2
}
);
assert_success!(i_prot.read_field_end());
assert_success!(i_prot.read_struct_begin());
let read_ident_3 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_3,
TFieldIdentifier {
name: None,
..field_ident_3
}
);
assert_success!(i_prot.read_field_end());
let read_ident_4 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_4,
TFieldIdentifier {
name: None,
..field_ident_4
}
);
assert_success!(i_prot.read_field_end());
let read_ident_6 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_6,
TFieldIdentifier {
name: None,
field_type: TType::Stop,
id: None,
}
);
assert_success!(i_prot.read_struct_end());
let read_ident_7 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_7,
TFieldIdentifier {
name: None,
field_type: TType::Stop,
id: None,
}
);
assert_success!(i_prot.read_struct_end());
}
#[test]
fn must_write_nested_structs_1() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
#[rustfmt::skip]
let expected: [u8; 7] = [
0x16, 0x85, 0x07, 0x30, 0x33, 0x00, 0x00 ,
];
assert_eq_written_bytes!(o_prot, expected);
}
#[allow(clippy::cognitive_complexity)]
#[test]
fn must_round_trip_nested_structs_1() {
let (mut i_prot, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
assert_success!(o_prot.write_field_begin(&field_ident_1));
assert_success!(o_prot.write_field_end());
let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
assert_success!(o_prot.write_field_begin(&field_ident_2));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
assert_success!(o_prot.write_field_begin(&field_ident_3));
assert_success!(o_prot.write_field_end());
let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
assert_success!(o_prot.write_field_begin(&field_ident_4));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
copy_write_buffer_to_read_buffer!(o_prot);
assert_success!(i_prot.read_struct_begin());
let read_ident_1 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_1,
TFieldIdentifier {
name: None,
..field_ident_1
}
);
assert_success!(i_prot.read_field_end());
let read_ident_2 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_2,
TFieldIdentifier {
name: None,
..field_ident_2
}
);
assert_success!(i_prot.read_field_end());
assert_success!(i_prot.read_struct_begin());
let read_ident_3 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_3,
TFieldIdentifier {
name: None,
..field_ident_3
}
);
assert_success!(i_prot.read_field_end());
let read_ident_4 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_4,
TFieldIdentifier {
name: None,
..field_ident_4
}
);
assert_success!(i_prot.read_field_end());
let read_ident_6 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_6,
TFieldIdentifier {
name: None,
field_type: TType::Stop,
id: None,
}
);
assert_success!(i_prot.read_struct_end());
let read_ident_7 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_7,
TFieldIdentifier {
name: None,
field_type: TType::Stop,
id: None,
}
);
assert_success!(i_prot.read_struct_end());
}
#[test]
fn must_write_nested_structs_2() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
#[rustfmt::skip]
let expected: [u8; 7] = [
0x16, 0x08, 0x2A, 0x77, 0x33, 0x00, 0x00 ,
];
assert_eq_written_bytes!(o_prot, expected);
}
#[allow(clippy::cognitive_complexity)]
#[test]
fn must_round_trip_nested_structs_2() {
let (mut i_prot, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
assert_success!(o_prot.write_field_begin(&field_ident_1));
assert_success!(o_prot.write_field_end());
let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
assert_success!(o_prot.write_field_begin(&field_ident_2));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
assert_success!(o_prot.write_field_begin(&field_ident_3));
assert_success!(o_prot.write_field_end());
let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
assert_success!(o_prot.write_field_begin(&field_ident_4));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
copy_write_buffer_to_read_buffer!(o_prot);
assert_success!(i_prot.read_struct_begin());
let read_ident_1 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_1,
TFieldIdentifier {
name: None,
..field_ident_1
}
);
assert_success!(i_prot.read_field_end());
let read_ident_2 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_2,
TFieldIdentifier {
name: None,
..field_ident_2
}
);
assert_success!(i_prot.read_field_end());
assert_success!(i_prot.read_struct_begin());
let read_ident_3 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_3,
TFieldIdentifier {
name: None,
..field_ident_3
}
);
assert_success!(i_prot.read_field_end());
let read_ident_4 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_4,
TFieldIdentifier {
name: None,
..field_ident_4
}
);
assert_success!(i_prot.read_field_end());
let read_ident_6 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_6,
TFieldIdentifier {
name: None,
field_type: TType::Stop,
id: None,
}
);
assert_success!(i_prot.read_struct_end());
let read_ident_7 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_7,
TFieldIdentifier {
name: None,
field_type: TType::Stop,
id: None,
}
);
assert_success!(i_prot.read_struct_end());
}
#[test]
fn must_write_nested_structs_3() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
#[rustfmt::skip]
let expected: [u8; 8] = [
0x16, 0x08, 0x2A, 0x07, 0x2A, 0x63, 0x00, 0x00 ,
];
assert_eq_written_bytes!(o_prot, expected);
}
#[allow(clippy::cognitive_complexity)]
#[test]
fn must_round_trip_nested_structs_3() {
let (mut i_prot, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
assert_success!(o_prot.write_field_begin(&field_ident_1));
assert_success!(o_prot.write_field_end());
let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
assert_success!(o_prot.write_field_begin(&field_ident_2));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
assert_success!(o_prot.write_field_begin(&field_ident_3));
assert_success!(o_prot.write_field_end());
let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
assert_success!(o_prot.write_field_begin(&field_ident_4));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
copy_write_buffer_to_read_buffer!(o_prot);
assert_success!(i_prot.read_struct_begin());
let read_ident_1 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_1,
TFieldIdentifier {
name: None,
..field_ident_1
}
);
assert_success!(i_prot.read_field_end());
let read_ident_2 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_2,
TFieldIdentifier {
name: None,
..field_ident_2
}
);
assert_success!(i_prot.read_field_end());
assert_success!(i_prot.read_struct_begin());
let read_ident_3 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_3,
TFieldIdentifier {
name: None,
..field_ident_3
}
);
assert_success!(i_prot.read_field_end());
let read_ident_4 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_4,
TFieldIdentifier {
name: None,
..field_ident_4
}
);
assert_success!(i_prot.read_field_end());
let read_ident_6 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_6,
TFieldIdentifier {
name: None,
field_type: TType::Stop,
id: None,
}
);
assert_success!(i_prot.read_struct_end());
let read_ident_7 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_7,
TFieldIdentifier {
name: None,
field_type: TType::Stop,
id: None,
}
);
assert_success!(i_prot.read_struct_end());
}
#[test]
fn must_write_bool_field() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
assert_success!(o_prot.write_bool(true));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
assert_success!(o_prot.write_bool(false));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
assert_success!(o_prot.write_bool(true));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
assert_success!(o_prot.write_bool(false));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
#[rustfmt::skip]
let expected: [u8; 7] = [
0x11, 0x82, 0x01, 0x34, 0x02, 0x5A, 0x00 ,
];
assert_eq_written_bytes!(o_prot, expected);
}
#[allow(clippy::cognitive_complexity)]
#[test]
fn must_round_trip_bool_field() {
let (mut i_prot, mut o_prot) = test_objects();
let struct_ident = TStructIdentifier::new("foo");
assert_success!(o_prot.write_struct_begin(&struct_ident));
let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
assert_success!(o_prot.write_field_begin(&field_ident_1));
assert_success!(o_prot.write_bool(true));
assert_success!(o_prot.write_field_end());
let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
assert_success!(o_prot.write_field_begin(&field_ident_2));
assert_success!(o_prot.write_bool(false));
assert_success!(o_prot.write_field_end());
let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
assert_success!(o_prot.write_field_begin(&field_ident_3));
assert_success!(o_prot.write_bool(true));
assert_success!(o_prot.write_field_end());
let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
assert_success!(o_prot.write_field_begin(&field_ident_4));
assert_success!(o_prot.write_bool(false));
assert_success!(o_prot.write_field_end());
assert_success!(o_prot.write_field_stop());
assert_success!(o_prot.write_struct_end());
copy_write_buffer_to_read_buffer!(o_prot);
assert_success!(i_prot.read_struct_begin());
let read_ident_1 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_1,
TFieldIdentifier {
name: None,
..field_ident_1
}
);
let read_value_1 = assert_success!(i_prot.read_bool());
assert_eq!(read_value_1, true);
assert_success!(i_prot.read_field_end());
let read_ident_2 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_2,
TFieldIdentifier {
name: None,
..field_ident_2
}
);
let read_value_2 = assert_success!(i_prot.read_bool());
assert_eq!(read_value_2, false);
assert_success!(i_prot.read_field_end());
let read_ident_3 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_3,
TFieldIdentifier {
name: None,
..field_ident_3
}
);
let read_value_3 = assert_success!(i_prot.read_bool());
assert_eq!(read_value_3, true);
assert_success!(i_prot.read_field_end());
let read_ident_4 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_4,
TFieldIdentifier {
name: None,
..field_ident_4
}
);
let read_value_4 = assert_success!(i_prot.read_bool());
assert_eq!(read_value_4, false);
assert_success!(i_prot.read_field_end());
let read_ident_5 = assert_success!(i_prot.read_field_begin());
assert_eq!(
read_ident_5,
TFieldIdentifier {
name: None,
field_type: TType::Stop,
id: None,
}
);
assert_success!(i_prot.read_struct_end());
}
#[test]
#[should_panic]
fn must_fail_if_write_field_end_without_writing_bool_value() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
o_prot.write_field_end().unwrap();
}
#[test]
#[should_panic]
fn must_fail_if_write_stop_field_without_writing_bool_value() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
o_prot.write_field_stop().unwrap();
}
#[test]
#[should_panic]
fn must_fail_if_write_struct_end_without_writing_bool_value() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
o_prot.write_struct_end().unwrap();
}
#[test]
#[should_panic]
fn must_fail_if_write_struct_end_without_any_fields() {
let (_, mut o_prot) = test_objects();
o_prot.write_struct_end().unwrap();
}
#[test]
fn must_write_field_end() {
assert_no_write(|o| o.write_field_end());
}
#[test]
fn must_write_small_sized_list_begin() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
let expected: [u8; 1] = [0x46 ];
assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_round_trip_small_sized_list_begin() {
let (mut i_prot, mut o_prot) = test_objects();
let ident = TListIdentifier::new(TType::I08, 10);
assert_success!(o_prot.write_list_begin(&ident));
copy_write_buffer_to_read_buffer!(o_prot);
let res = assert_success!(i_prot.read_list_begin());
assert_eq!(&res, &ident);
}
#[test]
fn must_write_large_sized_list_begin() {
let (_, mut o_prot) = test_objects();
let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
assert!(res.is_ok());
let expected: [u8; 3] = [
0xF9, 0x8F, 0x4E, ];
assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_round_trip_large_sized_list_begin() {
let (mut i_prot, mut o_prot) = test_objects();
let ident = TListIdentifier::new(TType::Set, 47381);
assert_success!(o_prot.write_list_begin(&ident));
copy_write_buffer_to_read_buffer!(o_prot);
let res = assert_success!(i_prot.read_list_begin());
assert_eq!(&res, &ident);
}
#[test]
fn must_write_list_end() {
assert_no_write(|o| o.write_list_end());
}
#[test]
fn must_write_small_sized_set_begin() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
let expected: [u8; 1] = [0x2C ];
assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_round_trip_small_sized_set_begin() {
let (mut i_prot, mut o_prot) = test_objects();
let ident = TSetIdentifier::new(TType::I16, 7);
assert_success!(o_prot.write_set_begin(&ident));
copy_write_buffer_to_read_buffer!(o_prot);
let res = assert_success!(i_prot.read_set_begin());
assert_eq!(&res, &ident);
}
#[test]
fn must_write_large_sized_set_begin() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
let expected: [u8; 4] = [
0xF7, 0xD3, 0xBA, 0x01, ];
assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_round_trip_large_sized_set_begin() {
let (mut i_prot, mut o_prot) = test_objects();
let ident = TSetIdentifier::new(TType::Map, 3_928_429);
assert_success!(o_prot.write_set_begin(&ident));
copy_write_buffer_to_read_buffer!(o_prot);
let res = assert_success!(i_prot.read_set_begin());
assert_eq!(&res, &ident);
}
#[test]
fn must_write_set_end() {
assert_no_write(|o| o.write_set_end());
}
#[test]
fn must_write_zero_sized_map_begin() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
let expected: [u8; 1] = [0x00]; assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_read_zero_sized_map_begin() {
let (mut i_prot, mut o_prot) = test_objects();
assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
copy_write_buffer_to_read_buffer!(o_prot);
let res = assert_success!(i_prot.read_map_begin());
assert_eq!(
&res,
&TMapIdentifier {
key_type: None,
value_type: None,
size: 0,
}
);
}
#[test]
fn must_write_map_begin() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
TType::Double,
TType::String,
238
)));
let expected: [u8; 3] = [
0xEE, 0x01, 0x78, ];
assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_round_trip_map_begin() {
let (mut i_prot, mut o_prot) = test_objects();
let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349);
assert_success!(o_prot.write_map_begin(&ident));
copy_write_buffer_to_read_buffer!(o_prot);
let res = assert_success!(i_prot.read_map_begin());
assert_eq!(&res, &ident);
}
#[test]
fn must_write_map_end() {
assert_no_write(|o| o.write_map_end());
}
#[test]
fn must_write_map_with_bool_key_and_value() {
let (_, mut o_prot) = test_objects();
assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
assert_success!(o_prot.write_bool(true));
assert_success!(o_prot.write_bool(false));
assert_success!(o_prot.write_map_end());
let expected: [u8; 4] = [
0x01, 0x11, 0x01, 0x02, ];
assert_eq_written_bytes!(o_prot, expected);
}
#[test]
fn must_round_trip_map_with_bool_value() {
let (mut i_prot, mut o_prot) = test_objects();
let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
assert_success!(o_prot.write_map_begin(&map_ident));
assert_success!(o_prot.write_bool(true));
assert_success!(o_prot.write_bool(false));
assert_success!(o_prot.write_bool(false));
assert_success!(o_prot.write_bool(true));
assert_success!(o_prot.write_map_end());
copy_write_buffer_to_read_buffer!(o_prot);
let rcvd_ident = assert_success!(i_prot.read_map_begin());
assert_eq!(&rcvd_ident, &map_ident);
let b = assert_success!(i_prot.read_bool());
assert_eq!(b, true);
let b = assert_success!(i_prot.read_bool());
assert_eq!(b, false);
let b = assert_success!(i_prot.read_bool());
assert_eq!(b, false);
let b = assert_success!(i_prot.read_bool());
assert_eq!(b, true);
assert_success!(i_prot.read_map_end());
}
#[test]
fn must_read_map_end() {
let (mut i_prot, _) = test_objects();
assert!(i_prot.read_map_end().is_ok()); }
fn test_objects() -> (
TCompactInputProtocol<ReadHalf<TBufferChannel>>,
TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
) {
let mem = TBufferChannel::with_capacity(80, 80);
let (r_mem, w_mem) = mem.split().unwrap();
let i_prot = TCompactInputProtocol::new(r_mem);
let o_prot = TCompactOutputProtocol::new(w_mem);
(i_prot, o_prot)
}
#[test]
fn must_read_write_double() {
let (mut i_prot, mut o_prot) = test_objects();
#[allow(clippy::approx_constant)]
let double = 3.141_592_653_589_793;
o_prot.write_double(double).unwrap();
copy_write_buffer_to_read_buffer!(o_prot);
let read_double = i_prot.read_double().unwrap();
assert!(read_double - double < std::f64::EPSILON);
}
#[test]
fn must_encode_double_as_other_langs() {
let (_, mut o_prot) = test_objects();
let expected = [24, 45, 68, 84, 251, 33, 9, 64];
#[allow(clippy::approx_constant)]
let double = 3.141_592_653_589_793;
o_prot.write_double(double).unwrap();
assert_eq_written_bytes!(o_prot, expected);
}
fn assert_no_write<F>(mut write_fn: F)
where
F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> crate::Result<()>,
{
let (_, mut o_prot) = test_objects();
assert!(write_fn(&mut o_prot).is_ok());
assert_eq!(o_prot.transport.write_bytes().len(), 0);
}
}