blob: 368735457be2eae2f8c7dae2a32623d7a29fa158 [file] [log] [blame]
Allen George8b96bfb2016-11-02 08:01:08 -04001// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
Marcin Pajkowskib34680f2019-12-02 10:29:16 +010018use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
Allen George8b96bfb2016-11-02 08:01:08 -040019use integer_encoding::{VarIntReader, VarIntWriter};
Danny Browningddec4312019-03-08 14:20:41 -070020use std::convert::{From, TryFrom};
Vadim Chekand3355af2018-01-05 23:12:47 -050021use std::io;
Allen George8b96bfb2016-11-02 08:01:08 -040022
Allen Georgeef7a1892018-12-16 18:01:37 -050023use super::{
24 TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier, TMapIdentifier,
25 TMessageIdentifier, TMessageType,
26};
Allen George8b96bfb2016-11-02 08:01:08 -040027use super::{TOutputProtocol, TOutputProtocolFactory, TSetIdentifier, TStructIdentifier, TType};
Allen Georgeb0d14132020-03-29 11:48:55 -040028use crate::transport::{TReadTransport, TWriteTransport};
Allen George8b96bfb2016-11-02 08:01:08 -040029
30const COMPACT_PROTOCOL_ID: u8 = 0x82;
31const COMPACT_VERSION: u8 = 0x01;
32const COMPACT_VERSION_MASK: u8 = 0x1F;
33
34/// Read messages encoded in the Thrift compact protocol.
35///
36/// # Examples
37///
38/// Create and use a `TCompactInputProtocol`.
39///
40/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -040041/// use thrift::protocol::{TCompactInputProtocol, TInputProtocol};
Allen George0e22c362017-01-30 07:15:00 -050042/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -040043///
Allen George0e22c362017-01-30 07:15:00 -050044/// let mut channel = TTcpChannel::new();
45/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040046///
Allen George0e22c362017-01-30 07:15:00 -050047/// let mut protocol = TCompactInputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -040048///
Allen George0e22c362017-01-30 07:15:00 -050049/// let recvd_bool = protocol.read_bool().unwrap();
50/// let recvd_string = protocol.read_string().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040051/// ```
Allen George0e22c362017-01-30 07:15:00 -050052#[derive(Debug)]
53pub struct TCompactInputProtocol<T>
54where
55 T: TReadTransport,
56{
Allen George8b96bfb2016-11-02 08:01:08 -040057 // Identifier of the last field deserialized for a struct.
58 last_read_field_id: i16,
59 // Stack of the last read field ids (a new entry is added each time a nested struct is read).
60 read_field_id_stack: Vec<i16>,
61 // Boolean value for a field.
62 // Saved because boolean fields and their value are encoded in a single byte,
63 // and reading the field only occurs after the field id is read.
64 pending_read_bool_value: Option<bool>,
65 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -050066 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -040067}
68
Allen George0e22c362017-01-30 07:15:00 -050069impl<T> TCompactInputProtocol<T>
70where
71 T: TReadTransport,
72{
Allen George8b96bfb2016-11-02 08:01:08 -040073 /// Create a `TCompactInputProtocol` that reads bytes from `transport`.
Allen George0e22c362017-01-30 07:15:00 -050074 pub fn new(transport: T) -> TCompactInputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -040075 TCompactInputProtocol {
76 last_read_field_id: 0,
77 read_field_id_stack: Vec::new(),
78 pending_read_bool_value: None,
Allen George7ddbcc02020-11-08 09:51:19 -050079 transport,
Allen George8b96bfb2016-11-02 08:01:08 -040080 }
81 }
82
Allen George8a1743d2020-12-05 01:19:27 -050083 /// Reads a varint for an `i32` without attempting to zigzag-decode it.
84 fn read_non_zigzag_varint(&mut self) -> crate::Result<i32> {
85 let mut num = 0i32;
86
87 let mut buf = [0u8; 1];
88 let mut shift_bits = 0u32;
89 let mut should_continue = true;
90
91 while should_continue {
92 self.transport.read_exact(&mut buf)?;
93 num |= ((buf[0] & 0x7F) as i32) << shift_bits;
94 shift_bits += 7;
95 should_continue = (buf[0] & 0x80) > 0;
96 }
97
98 Ok(num)
99 }
100
Allen Georgeb0d14132020-03-29 11:48:55 -0400101 fn read_list_set_begin(&mut self) -> crate::Result<(TType, i32)> {
Allen George8b96bfb2016-11-02 08:01:08 -0400102 let header = self.read_byte()?;
103 let element_type = collection_u8_to_type(header & 0x0F)?;
104
105 let element_count;
106 let possible_element_count = (header & 0xF0) >> 4;
107 if possible_element_count != 15 {
108 // high bits set high if count and type encoded separately
109 element_count = possible_element_count as i32;
110 } else {
Allen George0e22c362017-01-30 07:15:00 -0500111 element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400112 }
113
114 Ok((element_type, element_count))
115 }
116}
117
Allen George0e22c362017-01-30 07:15:00 -0500118impl<T> TInputProtocol for TCompactInputProtocol<T>
119where
120 T: TReadTransport,
121{
Allen Georgeb0d14132020-03-29 11:48:55 -0400122 fn read_message_begin(&mut self) -> crate::Result<TMessageIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400123 let compact_id = self.read_byte()?;
124 if compact_id != COMPACT_PROTOCOL_ID {
Allen Georgeb0d14132020-03-29 11:48:55 -0400125 Err(crate::Error::Protocol(crate::ProtocolError {
126 kind: crate::ProtocolErrorKind::BadVersion,
Allen Georgeef7a1892018-12-16 18:01:37 -0500127 message: format!("invalid compact protocol header {:?}", compact_id),
128 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400129 } else {
130 Ok(())
131 }?;
132
133 let type_and_byte = self.read_byte()?;
134 let received_version = type_and_byte & COMPACT_VERSION_MASK;
135 if received_version != COMPACT_VERSION {
Allen Georgeb0d14132020-03-29 11:48:55 -0400136 Err(crate::Error::Protocol(crate::ProtocolError {
137 kind: crate::ProtocolErrorKind::BadVersion,
Allen Georgeef7a1892018-12-16 18:01:37 -0500138 message: format!(
139 "cannot process compact protocol version {:?}",
140 received_version
Allen George0e22c362017-01-30 07:15:00 -0500141 ),
Allen Georgeef7a1892018-12-16 18:01:37 -0500142 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400143 } else {
144 Ok(())
145 }?;
146
147 // NOTE: unsigned right shift will pad with 0s
148 let message_type: TMessageType = TMessageType::try_from(type_and_byte >> 5)?;
Allen George8a1743d2020-12-05 01:19:27 -0500149 let sequence_number = self.read_non_zigzag_varint()?;
Allen George8b96bfb2016-11-02 08:01:08 -0400150 let service_call_name = self.read_string()?;
151
152 self.last_read_field_id = 0;
153
Allen Georgeef7a1892018-12-16 18:01:37 -0500154 Ok(TMessageIdentifier::new(
155 service_call_name,
156 message_type,
157 sequence_number,
158 ))
Allen George8b96bfb2016-11-02 08:01:08 -0400159 }
160
Allen Georgeb0d14132020-03-29 11:48:55 -0400161 fn read_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400162 Ok(())
163 }
164
Allen Georgeb0d14132020-03-29 11:48:55 -0400165 fn read_struct_begin(&mut self) -> crate::Result<Option<TStructIdentifier>> {
Allen George8b96bfb2016-11-02 08:01:08 -0400166 self.read_field_id_stack.push(self.last_read_field_id);
167 self.last_read_field_id = 0;
168 Ok(None)
169 }
170
Allen Georgeb0d14132020-03-29 11:48:55 -0400171 fn read_struct_end(&mut self) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500172 self.last_read_field_id = self
173 .read_field_id_stack
Allen George8b96bfb2016-11-02 08:01:08 -0400174 .pop()
175 .expect("should have previous field ids");
176 Ok(())
177 }
178
Allen Georgeb0d14132020-03-29 11:48:55 -0400179 fn read_field_begin(&mut self) -> crate::Result<TFieldIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400180 // we can read at least one byte, which is:
181 // - the type
182 // - the field delta and the type
183 let field_type = self.read_byte()?;
184 let field_delta = (field_type & 0xF0) >> 4;
185 let field_type = match field_type & 0x0F {
186 0x01 => {
187 self.pending_read_bool_value = Some(true);
188 Ok(TType::Bool)
189 }
190 0x02 => {
191 self.pending_read_bool_value = Some(false);
192 Ok(TType::Bool)
193 }
194 ttu8 => u8_to_type(ttu8),
195 }?;
196
197 match field_type {
Allen Georgeef7a1892018-12-16 18:01:37 -0500198 TType::Stop => Ok(
199 TFieldIdentifier::new::<Option<String>, String, Option<i16>>(
200 None,
201 TType::Stop,
202 None,
203 ),
204 ),
Allen George8b96bfb2016-11-02 08:01:08 -0400205 _ => {
206 if field_delta != 0 {
207 self.last_read_field_id += field_delta as i16;
208 } else {
209 self.last_read_field_id = self.read_i16()?;
210 };
211
Allen Georgeef7a1892018-12-16 18:01:37 -0500212 Ok(TFieldIdentifier {
213 name: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500214 field_type,
Allen Georgeef7a1892018-12-16 18:01:37 -0500215 id: Some(self.last_read_field_id),
216 })
Allen George8b96bfb2016-11-02 08:01:08 -0400217 }
218 }
219 }
220
Allen Georgeb0d14132020-03-29 11:48:55 -0400221 fn read_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400222 Ok(())
223 }
224
Allen Georgeb0d14132020-03-29 11:48:55 -0400225 fn read_bool(&mut self) -> crate::Result<bool> {
Allen George8b96bfb2016-11-02 08:01:08 -0400226 match self.pending_read_bool_value.take() {
227 Some(b) => Ok(b),
228 None => {
229 let b = self.read_byte()?;
230 match b {
231 0x01 => Ok(true),
232 0x02 => Ok(false),
Allen Georgeb0d14132020-03-29 11:48:55 -0400233 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
234 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500235 message: format!("cannot convert {} into bool", unkn),
236 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400237 }
238 }
239 }
240 }
241
Allen Georgeb0d14132020-03-29 11:48:55 -0400242 fn read_bytes(&mut self) -> crate::Result<Vec<u8>> {
Allen George0e22c362017-01-30 07:15:00 -0500243 let len = self.transport.read_varint::<u32>()?;
Allen George8b96bfb2016-11-02 08:01:08 -0400244 let mut buf = vec![0u8; len as usize];
Allen George0e22c362017-01-30 07:15:00 -0500245 self.transport
246 .read_exact(&mut buf)
247 .map_err(From::from)
248 .map(|_| buf)
Allen George8b96bfb2016-11-02 08:01:08 -0400249 }
250
Allen Georgeb0d14132020-03-29 11:48:55 -0400251 fn read_i8(&mut self) -> crate::Result<i8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400252 self.read_byte().map(|i| i as i8)
253 }
254
Allen Georgeb0d14132020-03-29 11:48:55 -0400255 fn read_i16(&mut self) -> crate::Result<i16> {
Allen George0e22c362017-01-30 07:15:00 -0500256 self.transport.read_varint::<i16>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400257 }
258
Allen Georgeb0d14132020-03-29 11:48:55 -0400259 fn read_i32(&mut self) -> crate::Result<i32> {
Allen George0e22c362017-01-30 07:15:00 -0500260 self.transport.read_varint::<i32>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400261 }
262
Allen Georgeb0d14132020-03-29 11:48:55 -0400263 fn read_i64(&mut self) -> crate::Result<i64> {
Allen George0e22c362017-01-30 07:15:00 -0500264 self.transport.read_varint::<i64>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400265 }
266
Allen Georgeb0d14132020-03-29 11:48:55 -0400267 fn read_double(&mut self) -> crate::Result<f64> {
Allen George8a1743d2020-12-05 01:19:27 -0500268 self.transport
269 .read_f64::<LittleEndian>()
270 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400271 }
272
Allen Georgeb0d14132020-03-29 11:48:55 -0400273 fn read_string(&mut self) -> crate::Result<String> {
Allen George8b96bfb2016-11-02 08:01:08 -0400274 let bytes = self.read_bytes()?;
275 String::from_utf8(bytes).map_err(From::from)
276 }
277
Allen Georgeb0d14132020-03-29 11:48:55 -0400278 fn read_list_begin(&mut self) -> crate::Result<TListIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400279 let (element_type, element_count) = self.read_list_set_begin()?;
280 Ok(TListIdentifier::new(element_type, element_count))
281 }
282
Allen Georgeb0d14132020-03-29 11:48:55 -0400283 fn read_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400284 Ok(())
285 }
286
Allen Georgeb0d14132020-03-29 11:48:55 -0400287 fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400288 let (element_type, element_count) = self.read_list_set_begin()?;
289 Ok(TSetIdentifier::new(element_type, element_count))
290 }
291
Allen Georgeb0d14132020-03-29 11:48:55 -0400292 fn read_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400293 Ok(())
294 }
295
Allen Georgeb0d14132020-03-29 11:48:55 -0400296 fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier> {
Allen George0e22c362017-01-30 07:15:00 -0500297 let element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400298 if element_count == 0 {
299 Ok(TMapIdentifier::new(None, None, 0))
300 } else {
301 let type_header = self.read_byte()?;
302 let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
303 let val_type = collection_u8_to_type(type_header & 0x0F)?;
304 Ok(TMapIdentifier::new(key_type, val_type, element_count))
305 }
306 }
307
Allen Georgeb0d14132020-03-29 11:48:55 -0400308 fn read_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400309 Ok(())
310 }
311
312 // utility
313 //
314
Allen Georgeb0d14132020-03-29 11:48:55 -0400315 fn read_byte(&mut self) -> crate::Result<u8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400316 let mut buf = [0u8; 1];
Allen George0e22c362017-01-30 07:15:00 -0500317 self.transport
318 .read_exact(&mut buf)
319 .map_err(From::from)
320 .map(|_| buf[0])
Allen George8b96bfb2016-11-02 08:01:08 -0400321 }
322}
323
Vadim Chekand3355af2018-01-05 23:12:47 -0500324impl<T> io::Seek for TCompactInputProtocol<T>
325where
326 T: io::Seek + TReadTransport,
327{
328 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
329 self.transport.seek(pos)
330 }
331}
332
Allen George8b96bfb2016-11-02 08:01:08 -0400333/// Factory for creating instances of `TCompactInputProtocol`.
334#[derive(Default)]
335pub struct TCompactInputProtocolFactory;
336
337impl TCompactInputProtocolFactory {
338 /// Create a `TCompactInputProtocolFactory`.
339 pub fn new() -> TCompactInputProtocolFactory {
340 TCompactInputProtocolFactory {}
341 }
342}
343
344impl TInputProtocolFactory for TCompactInputProtocolFactory {
Danny Browning77d96c12019-08-21 13:41:07 -0600345 fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500346 Box::new(TCompactInputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400347 }
348}
349
350/// Write messages using the Thrift compact protocol.
351///
352/// # Examples
353///
354/// Create and use a `TCompactOutputProtocol`.
355///
356/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -0400357/// use thrift::protocol::{TCompactOutputProtocol, TOutputProtocol};
Allen George0e22c362017-01-30 07:15:00 -0500358/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -0400359///
Allen George0e22c362017-01-30 07:15:00 -0500360/// let mut channel = TTcpChannel::new();
361/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400362///
Allen George0e22c362017-01-30 07:15:00 -0500363/// let mut protocol = TCompactOutputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -0400364///
Allen George0e22c362017-01-30 07:15:00 -0500365/// protocol.write_bool(true).unwrap();
366/// protocol.write_string("test_string").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400367/// ```
Allen George0e22c362017-01-30 07:15:00 -0500368#[derive(Debug)]
369pub struct TCompactOutputProtocol<T>
370where
371 T: TWriteTransport,
372{
Allen George8b96bfb2016-11-02 08:01:08 -0400373 // Identifier of the last field serialized for a struct.
374 last_write_field_id: i16,
Allen George0e22c362017-01-30 07:15:00 -0500375 // Stack of the last written field ids (new entry added each time a nested struct is written).
Allen George8b96bfb2016-11-02 08:01:08 -0400376 write_field_id_stack: Vec<i16>,
377 // Field identifier of the boolean field to be written.
378 // Saved because boolean fields and their value are encoded in a single byte
379 pending_write_bool_field_identifier: Option<TFieldIdentifier>,
380 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -0500381 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -0400382}
383
Allen George0e22c362017-01-30 07:15:00 -0500384impl<T> TCompactOutputProtocol<T>
385where
386 T: TWriteTransport,
387{
Allen George8b96bfb2016-11-02 08:01:08 -0400388 /// Create a `TCompactOutputProtocol` that writes bytes to `transport`.
Allen George0e22c362017-01-30 07:15:00 -0500389 pub fn new(transport: T) -> TCompactOutputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -0400390 TCompactOutputProtocol {
391 last_write_field_id: 0,
392 write_field_id_stack: Vec::new(),
393 pending_write_bool_field_identifier: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500394 transport,
Allen George8b96bfb2016-11-02 08:01:08 -0400395 }
396 }
397
Allen George8a1743d2020-12-05 01:19:27 -0500398 /// Writes a varint for an `i32` without attempting to zigzag-encode it first.
399 fn write_non_zigzag_varint(&mut self, i: i32) -> crate::Result<()> {
400 let mut output = Vec::with_capacity(5);
401 let mut i = i as u32; // avoids sign extension on bitshift
402
403 loop {
404 if (i & !0x7F) == 0 {
405 output.push(i as u8);
406 break;
407 } else {
408 let varint_byte = ((i as u8) & 0x7F) | 0x80;
409 output.push(varint_byte);
410 i >>= 7;
411 }
412 }
413
414 self.transport
415 .write_all(output.as_slice())
416 .map_err(From::from)
417 }
418
Allen George8b96bfb2016-11-02 08:01:08 -0400419 // FIXME: field_type as unconstrained u8 is bad
Allen Georgeb0d14132020-03-29 11:48:55 -0400420 fn write_field_header(&mut self, field_type: u8, field_id: i16) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400421 let field_delta = field_id - self.last_write_field_id;
422 if field_delta > 0 && field_delta < 15 {
423 self.write_byte(((field_delta as u8) << 4) | field_type)?;
424 } else {
425 self.write_byte(field_type)?;
426 self.write_i16(field_id)?;
427 }
428 self.last_write_field_id = field_id;
429 Ok(())
430 }
431
Allen George8a1743d2020-12-05 01:19:27 -0500432 fn write_list_set_begin(
433 &mut self,
434 element_type: TType,
435 element_count: i32,
436 ) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400437 let elem_identifier = collection_type_to_u8(element_type);
438 if element_count <= 14 {
439 let header = (element_count as u8) << 4 | elem_identifier;
440 self.write_byte(header)
441 } else {
442 let header = 0xF0 | elem_identifier;
443 self.write_byte(header)?;
Allen George8a1743d2020-12-05 01:19:27 -0500444 // size is strictly positive as per the spec, so:
445 // 1. we first cast to u32
446 // 2. write as varint
447 // which means that integer_encoding will **not** zigzag it first
Allen George8b96bfb2016-11-02 08:01:08 -0400448 self.transport
Allen George8b96bfb2016-11-02 08:01:08 -0400449 .write_varint(element_count as u32)
450 .map_err(From::from)
451 .map(|_| ())
452 }
453 }
454
455 fn assert_no_pending_bool_write(&self) {
456 if let Some(ref f) = self.pending_write_bool_field_identifier {
457 panic!("pending bool field {:?} not written", f)
458 }
459 }
460}
461
Allen George0e22c362017-01-30 07:15:00 -0500462impl<T> TOutputProtocol for TCompactOutputProtocol<T>
463where
464 T: TWriteTransport,
465{
Allen Georgeb0d14132020-03-29 11:48:55 -0400466 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400467 self.write_byte(COMPACT_PROTOCOL_ID)?;
468 self.write_byte((u8::from(identifier.message_type) << 5) | COMPACT_VERSION)?;
Allen George8a1743d2020-12-05 01:19:27 -0500469 self.write_non_zigzag_varint(identifier.sequence_number)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400470 self.write_string(&identifier.name)?;
471 Ok(())
472 }
473
Allen Georgeb0d14132020-03-29 11:48:55 -0400474 fn write_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400475 self.assert_no_pending_bool_write();
476 Ok(())
477 }
478
Allen Georgeb0d14132020-03-29 11:48:55 -0400479 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400480 self.write_field_id_stack.push(self.last_write_field_id);
481 self.last_write_field_id = 0;
482 Ok(())
483 }
484
Allen Georgeb0d14132020-03-29 11:48:55 -0400485 fn write_struct_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400486 self.assert_no_pending_bool_write();
Allen Georgeef7a1892018-12-16 18:01:37 -0500487 self.last_write_field_id = self
488 .write_field_id_stack
Allen George0e22c362017-01-30 07:15:00 -0500489 .pop()
490 .expect("should have previous field ids");
Allen George8b96bfb2016-11-02 08:01:08 -0400491 Ok(())
492 }
493
Allen Georgeb0d14132020-03-29 11:48:55 -0400494 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400495 match identifier.field_type {
496 TType::Bool => {
497 if self.pending_write_bool_field_identifier.is_some() {
Allen George0e22c362017-01-30 07:15:00 -0500498 panic!(
499 "should not have a pending bool while writing another bool with id: \
Allen Georgeef7a1892018-12-16 18:01:37 -0500500 {:?}",
Allen George0e22c362017-01-30 07:15:00 -0500501 identifier
502 )
Allen George8b96bfb2016-11-02 08:01:08 -0400503 }
504 self.pending_write_bool_field_identifier = Some(identifier.clone());
505 Ok(())
506 }
507 _ => {
508 let field_type = type_to_u8(identifier.field_type);
Allen Georgeef7a1892018-12-16 18:01:37 -0500509 let field_id = identifier.id.expect("non-stop field should have field id");
Allen George8b96bfb2016-11-02 08:01:08 -0400510 self.write_field_header(field_type, field_id)
511 }
512 }
513 }
514
Allen Georgeb0d14132020-03-29 11:48:55 -0400515 fn write_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400516 self.assert_no_pending_bool_write();
517 Ok(())
518 }
519
Allen Georgeb0d14132020-03-29 11:48:55 -0400520 fn write_field_stop(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400521 self.assert_no_pending_bool_write();
522 self.write_byte(type_to_u8(TType::Stop))
523 }
524
Allen Georgeb0d14132020-03-29 11:48:55 -0400525 fn write_bool(&mut self, b: bool) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400526 match self.pending_write_bool_field_identifier.take() {
527 Some(pending) => {
528 let field_id = pending.id.expect("bool field should have a field id");
529 let field_type_as_u8 = if b { 0x01 } else { 0x02 };
530 self.write_field_header(field_type_as_u8, field_id)
531 }
532 None => {
533 if b {
534 self.write_byte(0x01)
535 } else {
536 self.write_byte(0x02)
537 }
538 }
539 }
540 }
541
Allen Georgeb0d14132020-03-29 11:48:55 -0400542 fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> {
Allen George8a1743d2020-12-05 01:19:27 -0500543 // size is strictly positive as per the spec, so:
544 // 1. we first cast to u32
545 // 2. write as varint
546 // which means that integer_encoding will **not** zigzag it first
Allen George0e22c362017-01-30 07:15:00 -0500547 self.transport.write_varint(b.len() as u32)?;
548 self.transport.write_all(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400549 }
550
Allen Georgeb0d14132020-03-29 11:48:55 -0400551 fn write_i8(&mut self, i: i8) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400552 self.write_byte(i as u8)
553 }
554
Allen Georgeb0d14132020-03-29 11:48:55 -0400555 fn write_i16(&mut self, i: i16) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500556 self.transport
Allen George8a1743d2020-12-05 01:19:27 -0500557 .write_varint(i as i32)
Allen George0e22c362017-01-30 07:15:00 -0500558 .map_err(From::from)
559 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400560 }
561
Allen Georgeb0d14132020-03-29 11:48:55 -0400562 fn write_i32(&mut self, i: i32) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500563 self.transport
564 .write_varint(i)
565 .map_err(From::from)
566 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400567 }
568
Allen Georgeb0d14132020-03-29 11:48:55 -0400569 fn write_i64(&mut self, i: i64) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500570 self.transport
571 .write_varint(i)
572 .map_err(From::from)
573 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400574 }
575
Allen Georgeb0d14132020-03-29 11:48:55 -0400576 fn write_double(&mut self, d: f64) -> crate::Result<()> {
Allen George8a1743d2020-12-05 01:19:27 -0500577 self.transport
578 .write_f64::<LittleEndian>(d)
579 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400580 }
581
Allen Georgeb0d14132020-03-29 11:48:55 -0400582 fn write_string(&mut self, s: &str) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400583 self.write_bytes(s.as_bytes())
584 }
585
Allen Georgeb0d14132020-03-29 11:48:55 -0400586 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400587 self.write_list_set_begin(identifier.element_type, identifier.size)
588 }
589
Allen Georgeb0d14132020-03-29 11:48:55 -0400590 fn write_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400591 Ok(())
592 }
593
Allen Georgeb0d14132020-03-29 11:48:55 -0400594 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400595 self.write_list_set_begin(identifier.element_type, identifier.size)
596 }
597
Allen Georgeb0d14132020-03-29 11:48:55 -0400598 fn write_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400599 Ok(())
600 }
601
Allen Georgeb0d14132020-03-29 11:48:55 -0400602 fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400603 if identifier.size == 0 {
604 self.write_byte(0)
605 } else {
Allen George8a1743d2020-12-05 01:19:27 -0500606 // size is strictly positive as per the spec, so:
607 // 1. we first cast to u32
608 // 2. write as varint
609 // which means that integer_encoding will **not** zigzag it first
Allen George0e22c362017-01-30 07:15:00 -0500610 self.transport.write_varint(identifier.size as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400611
Allen George0e22c362017-01-30 07:15:00 -0500612 let key_type = identifier
613 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400614 .expect("map identifier to write should contain key type");
615 let key_type_byte = collection_type_to_u8(key_type) << 4;
616
Allen George0e22c362017-01-30 07:15:00 -0500617 let val_type = identifier
618 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400619 .expect("map identifier to write should contain value type");
620 let val_type_byte = collection_type_to_u8(val_type);
621
622 let map_type_header = key_type_byte | val_type_byte;
623 self.write_byte(map_type_header)
624 }
625 }
626
Allen Georgeb0d14132020-03-29 11:48:55 -0400627 fn write_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400628 Ok(())
629 }
630
Allen Georgeb0d14132020-03-29 11:48:55 -0400631 fn flush(&mut self) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500632 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400633 }
634
635 // utility
636 //
637
Allen Georgeb0d14132020-03-29 11:48:55 -0400638 fn write_byte(&mut self, b: u8) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500639 self.transport.write(&[b]).map_err(From::from).map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400640 }
641}
642
643/// Factory for creating instances of `TCompactOutputProtocol`.
644#[derive(Default)]
645pub struct TCompactOutputProtocolFactory;
646
647impl TCompactOutputProtocolFactory {
648 /// Create a `TCompactOutputProtocolFactory`.
649 pub fn new() -> TCompactOutputProtocolFactory {
650 TCompactOutputProtocolFactory {}
651 }
652}
653
654impl TOutputProtocolFactory for TCompactOutputProtocolFactory {
Allen George8a1743d2020-12-05 01:19:27 -0500655 fn create(
656 &self,
657 transport: Box<dyn TWriteTransport + Send>,
658 ) -> Box<dyn TOutputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500659 Box::new(TCompactOutputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400660 }
661}
662
663fn collection_type_to_u8(field_type: TType) -> u8 {
664 match field_type {
665 TType::Bool => 0x01,
666 f => type_to_u8(f),
667 }
668}
669
670fn type_to_u8(field_type: TType) -> u8 {
671 match field_type {
672 TType::Stop => 0x00,
673 TType::I08 => 0x03, // equivalent to TType::Byte
674 TType::I16 => 0x04,
675 TType::I32 => 0x05,
676 TType::I64 => 0x06,
677 TType::Double => 0x07,
678 TType::String => 0x08,
679 TType::List => 0x09,
680 TType::Set => 0x0A,
681 TType::Map => 0x0B,
682 TType::Struct => 0x0C,
Allen Georgeef7a1892018-12-16 18:01:37 -0500683 _ => panic!(format!(
684 "should not have attempted to convert {} to u8",
685 field_type
686 )),
Allen George8b96bfb2016-11-02 08:01:08 -0400687 }
688}
689
Allen Georgeb0d14132020-03-29 11:48:55 -0400690fn collection_u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400691 match b {
692 0x01 => Ok(TType::Bool),
693 o => u8_to_type(o),
694 }
695}
696
Allen Georgeb0d14132020-03-29 11:48:55 -0400697fn u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400698 match b {
699 0x00 => Ok(TType::Stop),
700 0x03 => Ok(TType::I08), // equivalent to TType::Byte
701 0x04 => Ok(TType::I16),
702 0x05 => Ok(TType::I32),
703 0x06 => Ok(TType::I64),
704 0x07 => Ok(TType::Double),
705 0x08 => Ok(TType::String),
706 0x09 => Ok(TType::List),
707 0x0A => Ok(TType::Set),
708 0x0B => Ok(TType::Map),
709 0x0C => Ok(TType::Struct),
Allen Georgeb0d14132020-03-29 11:48:55 -0400710 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
711 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500712 message: format!("cannot convert {} into TType", unkn),
713 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400714 }
715}
716
717#[cfg(test)]
718mod tests {
719
Allen George8a1743d2020-12-05 01:19:27 -0500720 use std::i32;
721
Allen Georgeb0d14132020-03-29 11:48:55 -0400722 use crate::protocol::{
Allen Georgeef7a1892018-12-16 18:01:37 -0500723 TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
724 TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
725 };
Allen Georgeb0d14132020-03-29 11:48:55 -0400726 use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400727
728 use super::*;
729
730 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500731 fn must_write_message_begin_largest_maximum_positive_sequence_number() {
732 let (_, mut o_prot) = test_objects();
733
734 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
735 "bar",
736 TMessageType::Reply,
737 i32::MAX
738 )));
739
740 #[rustfmt::skip]
741 let expected: [u8; 11] = [
742 0x82, /* protocol ID */
743 0x41, /* message type | protocol version */
744 0xFF,
745 0xFF,
746 0xFF,
747 0xFF,
748 0x07, /* non-zig-zag varint sequence number */
749 0x03, /* message-name length */
750 0x62,
751 0x61,
752 0x72 /* "bar" */,
753 ];
754
755 assert_eq_written_bytes!(o_prot, expected);
756 }
757
758 #[test]
759 fn must_read_message_begin_largest_maximum_positive_sequence_number() {
760 let (mut i_prot, _) = test_objects();
761
762 #[rustfmt::skip]
763 let source_bytes: [u8; 11] = [
764 0x82, /* protocol ID */
765 0x41, /* message type | protocol version */
766 0xFF,
767 0xFF,
768 0xFF,
769 0xFF,
770 0x07, /* non-zig-zag varint sequence number */
771 0x03, /* message-name length */
772 0x62,
773 0x61,
774 0x72 /* "bar" */,
775 ];
776
777 i_prot.transport.set_readable_bytes(&source_bytes);
778
779 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MAX);
780 let res = assert_success!(i_prot.read_message_begin());
781
782 assert_eq!(&expected, &res);
783 }
784
785 #[test]
786 fn must_write_message_begin_positive_sequence_number_0() {
Allen George0e22c362017-01-30 07:15:00 -0500787 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400788
Allen Georgeef7a1892018-12-16 18:01:37 -0500789 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
790 "foo",
791 TMessageType::Call,
792 431
793 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400794
Allen George7ddbcc02020-11-08 09:51:19 -0500795 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500796 let expected: [u8; 8] = [
797 0x82, /* protocol ID */
798 0x21, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500799 0xAF,
800 0x03, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500801 0x03, /* message-name length */
802 0x66,
803 0x6F,
804 0x6F /* "foo" */,
805 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400806
Allen George0e22c362017-01-30 07:15:00 -0500807 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400808 }
809
810 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500811 fn must_read_message_begin_positive_sequence_number_0() {
812 let (mut i_prot, _) = test_objects();
813
814 #[rustfmt::skip]
815 let source_bytes: [u8; 8] = [
816 0x82, /* protocol ID */
817 0x21, /* message type | protocol version */
818 0xAF,
819 0x03, /* non-zig-zag varint sequence number */
820 0x03, /* message-name length */
821 0x66,
822 0x6F,
823 0x6F /* "foo" */,
824 ];
825
826 i_prot.transport.set_readable_bytes(&source_bytes);
827
828 let expected = TMessageIdentifier::new("foo", TMessageType::Call, 431);
829 let res = assert_success!(i_prot.read_message_begin());
830
831 assert_eq!(&expected, &res);
832 }
833
834 #[test]
835 fn must_write_message_begin_positive_sequence_number_1() {
Allen George0e22c362017-01-30 07:15:00 -0500836 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400837
Allen Georgeef7a1892018-12-16 18:01:37 -0500838 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
839 "bar",
840 TMessageType::Reply,
Allen George7ddbcc02020-11-08 09:51:19 -0500841 991_828
Allen Georgeef7a1892018-12-16 18:01:37 -0500842 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400843
Allen George7ddbcc02020-11-08 09:51:19 -0500844 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500845 let expected: [u8; 9] = [
846 0x82, /* protocol ID */
847 0x41, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500848 0xD4,
849 0xC4,
850 0x3C, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500851 0x03, /* message-name length */
852 0x62,
853 0x61,
854 0x72 /* "bar" */,
855 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400856
Allen George0e22c362017-01-30 07:15:00 -0500857 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400858 }
859
860 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500861 fn must_read_message_begin_positive_sequence_number_1() {
862 let (mut i_prot, _) = test_objects();
863
864 #[rustfmt::skip]
865 let source_bytes: [u8; 9] = [
866 0x82, /* protocol ID */
867 0x41, /* message type | protocol version */
868 0xD4,
869 0xC4,
870 0x3C, /* non-zig-zag varint sequence number */
871 0x03, /* message-name length */
872 0x62,
873 0x61,
874 0x72 /* "bar" */,
875 ];
876
877 i_prot.transport.set_readable_bytes(&source_bytes);
878
879 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 991_828);
880 let res = assert_success!(i_prot.read_message_begin());
881
882 assert_eq!(&expected, &res);
883 }
884
885 #[test]
886 fn must_write_message_begin_zero_sequence_number() {
887 let (_, mut o_prot) = test_objects();
888
889 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
890 "bar",
891 TMessageType::Reply,
892 0
893 )));
894
895 #[rustfmt::skip]
896 let expected: [u8; 7] = [
897 0x82, /* protocol ID */
898 0x41, /* message type | protocol version */
899 0x00, /* non-zig-zag varint sequence number */
900 0x03, /* message-name length */
901 0x62,
902 0x61,
903 0x72 /* "bar" */,
904 ];
905
906 assert_eq_written_bytes!(o_prot, expected);
907 }
908
909 #[test]
910 fn must_read_message_begin_zero_sequence_number() {
911 let (mut i_prot, _) = test_objects();
912
913 #[rustfmt::skip]
914 let source_bytes: [u8; 7] = [
915 0x82, /* protocol ID */
916 0x41, /* message type | protocol version */
917 0x00, /* non-zig-zag varint sequence number */
918 0x03, /* message-name length */
919 0x62,
920 0x61,
921 0x72 /* "bar" */,
922 ];
923
924 i_prot.transport.set_readable_bytes(&source_bytes);
925
926 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 0);
927 let res = assert_success!(i_prot.read_message_begin());
928
929 assert_eq!(&expected, &res);
930 }
931
932 #[test]
933 fn must_write_message_begin_largest_minimum_negative_sequence_number() {
934 let (_, mut o_prot) = test_objects();
935
936 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
937 "bar",
938 TMessageType::Reply,
939 i32::MIN
940 )));
941
942 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
943 #[rustfmt::skip]
944 let expected: [u8; 11] = [
945 0x82, /* protocol ID */
946 0x41, /* message type | protocol version */
947 0x80,
948 0x80,
949 0x80,
950 0x80,
951 0x08, /* non-zig-zag varint sequence number */
952 0x03, /* message-name length */
953 0x62,
954 0x61,
955 0x72 /* "bar" */,
956 ];
957
958 assert_eq_written_bytes!(o_prot, expected);
959 }
960
961 #[test]
962 fn must_read_message_begin_largest_minimum_negative_sequence_number() {
963 let (mut i_prot, _) = test_objects();
964
965 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
966 #[rustfmt::skip]
967 let source_bytes: [u8; 11] = [
968 0x82, /* protocol ID */
969 0x41, /* message type | protocol version */
970 0x80,
971 0x80,
972 0x80,
973 0x80,
974 0x08, /* non-zig-zag varint sequence number */
975 0x03, /* message-name length */
976 0x62,
977 0x61,
978 0x72 /* "bar" */,
979 ];
980
981 i_prot.transport.set_readable_bytes(&source_bytes);
982
983 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MIN);
984 let res = assert_success!(i_prot.read_message_begin());
985
986 assert_eq!(&expected, &res);
987 }
988
989 #[test]
990 fn must_write_message_begin_negative_sequence_number_0() {
991 let (_, mut o_prot) = test_objects();
992
993 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
994 "foo",
995 TMessageType::Call,
996 -431
997 )));
998
999 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
1000 #[rustfmt::skip]
1001 let expected: [u8; 11] = [
1002 0x82, /* protocol ID */
1003 0x21, /* message type | protocol version */
1004 0xD1,
1005 0xFC,
1006 0xFF,
1007 0xFF,
1008 0x0F, /* non-zig-zag varint sequence number */
1009 0x03, /* message-name length */
1010 0x66,
1011 0x6F,
1012 0x6F /* "foo" */,
1013 ];
1014
1015 assert_eq_written_bytes!(o_prot, expected);
1016 }
1017
1018 #[test]
1019 fn must_read_message_begin_negative_sequence_number_0() {
1020 let (mut i_prot, _) = test_objects();
1021
1022 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
1023 #[rustfmt::skip]
1024 let source_bytes: [u8; 11] = [
1025 0x82, /* protocol ID */
1026 0x21, /* message type | protocol version */
1027 0xD1,
1028 0xFC,
1029 0xFF,
1030 0xFF,
1031 0x0F, /* non-zig-zag varint sequence number */
1032 0x03, /* message-name length */
1033 0x66,
1034 0x6F,
1035 0x6F /* "foo" */,
1036 ];
1037
1038 i_prot.transport.set_readable_bytes(&source_bytes);
1039
1040 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -431);
1041 let res = assert_success!(i_prot.read_message_begin());
1042
1043 assert_eq!(&expected, &res);
1044 }
1045
1046 #[test]
1047 fn must_write_message_begin_negative_sequence_number_1() {
1048 let (_, mut o_prot) = test_objects();
1049
1050 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1051 "foo",
1052 TMessageType::Call,
1053 -73_184_125
1054 )));
1055
1056 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1057 #[rustfmt::skip]
1058 let expected: [u8; 11] = [
1059 0x82, /* protocol ID */
1060 0x21, /* message type | protocol version */
1061 0x83,
1062 0x99,
1063 0x8D,
1064 0xDD,
1065 0x0F, /* non-zig-zag varint sequence number */
1066 0x03, /* message-name length */
1067 0x66,
1068 0x6F,
1069 0x6F /* "foo" */,
1070 ];
1071
1072 assert_eq_written_bytes!(o_prot, expected);
1073 }
1074
1075 #[test]
1076 fn must_read_message_begin_negative_sequence_number_1() {
1077 let (mut i_prot, _) = test_objects();
1078
1079 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1080 #[rustfmt::skip]
1081 let source_bytes: [u8; 11] = [
1082 0x82, /* protocol ID */
1083 0x21, /* message type | protocol version */
1084 0x83,
1085 0x99,
1086 0x8D,
1087 0xDD,
1088 0x0F, /* non-zig-zag varint sequence number */
1089 0x03, /* message-name length */
1090 0x66,
1091 0x6F,
1092 0x6F /* "foo" */,
1093 ];
1094
1095 i_prot.transport.set_readable_bytes(&source_bytes);
1096
1097 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -73_184_125);
1098 let res = assert_success!(i_prot.read_message_begin());
1099
1100 assert_eq!(&expected, &res);
1101 }
1102
1103 #[test]
1104 fn must_write_message_begin_negative_sequence_number_2() {
1105 let (_, mut o_prot) = test_objects();
1106
1107 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1108 "foo",
1109 TMessageType::Call,
1110 -1_073_741_823
1111 )));
1112
1113 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
1114 #[rustfmt::skip]
1115 let expected: [u8; 11] = [
1116 0x82, /* protocol ID */
1117 0x21, /* message type | protocol version */
1118 0x81,
1119 0x80,
1120 0x80,
1121 0x80,
1122 0x0C, /* non-zig-zag varint sequence number */
1123 0x03, /* message-name length */
1124 0x66,
1125 0x6F,
1126 0x6F /* "foo" */,
1127 ];
1128
1129 assert_eq_written_bytes!(o_prot, expected);
1130 }
1131
1132 #[test]
1133 fn must_read_message_begin_negative_sequence_number_2() {
1134 let (mut i_prot, _) = test_objects();
1135
1136 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
1137 let source_bytes: [u8; 11] = [
1138 0x82, /* protocol ID */
1139 0x21, /* message type | protocol version */
1140 0x81,
1141 0x80,
1142 0x80,
1143 0x80,
1144 0x0C, /* non-zig-zag varint sequence number */
1145 0x03, /* message-name length */
1146 0x66,
1147 0x6F,
1148 0x6F /* "foo" */,
1149 ];
1150
1151 i_prot.transport.set_readable_bytes(&source_bytes);
1152
1153 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -1_073_741_823);
1154 let res = assert_success!(i_prot.read_message_begin());
1155
1156 assert_eq!(&expected, &res);
1157 }
1158
1159 #[test]
Nik Claytone7917602020-03-05 11:51:15 +01001160 fn must_round_trip_upto_i64_maxvalue() {
1161 // See https://issues.apache.org/jira/browse/THRIFT-5131
1162 for i in 0..64 {
1163 let (mut i_prot, mut o_prot) = test_objects();
1164 let val: i64 = ((1u64 << i) - 1) as i64;
1165
1166 o_prot
Allen George8a1743d2020-12-05 01:19:27 -05001167 .write_field_begin(&TFieldIdentifier::new("val", TType::I64, 1))
Nik Claytone7917602020-03-05 11:51:15 +01001168 .unwrap();
1169 o_prot.write_i64(val).unwrap();
1170 o_prot.write_field_end().unwrap();
1171 o_prot.flush().unwrap();
1172
1173 copy_write_buffer_to_read_buffer!(o_prot);
1174
1175 i_prot.read_field_begin().unwrap();
1176 assert_eq!(val, i_prot.read_i64().unwrap());
1177 }
1178 }
1179
1180 #[test]
Allen George8b96bfb2016-11-02 08:01:08 -04001181 fn must_round_trip_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -05001182 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001183
Allen George7ddbcc02020-11-08 09:51:19 -05001184 let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948);
Allen George8b96bfb2016-11-02 08:01:08 -04001185
1186 assert_success!(o_prot.write_message_begin(&ident));
1187
Allen George0e22c362017-01-30 07:15:00 -05001188 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001189
1190 let res = assert_success!(i_prot.read_message_begin());
1191 assert_eq!(&res, &ident);
1192 }
1193
1194 #[test]
1195 fn must_write_message_end() {
1196 assert_no_write(|o| o.write_message_end());
1197 }
1198
1199 // NOTE: structs and fields are tested together
1200 //
1201
1202 #[test]
1203 fn must_write_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001204 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001205
1206 // no bytes should be written however
1207 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1208
1209 // write three fields with tiny field ids
1210 // since they're small the field ids will be encoded as deltas
1211
1212 // since this is the first field (and it's zero) it gets the full varint write
1213 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
1214 assert_success!(o_prot.write_field_end());
1215
1216 // since this delta > 0 and < 15 it can be encoded as a delta
1217 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
1218 assert_success!(o_prot.write_field_end());
1219
1220 // since this delta > 0 and < 15 it can be encoded as a delta
1221 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
1222 assert_success!(o_prot.write_field_end());
1223
1224 // now, finish the struct off
1225 assert_success!(o_prot.write_field_stop());
1226 assert_success!(o_prot.write_struct_end());
1227
Allen George7ddbcc02020-11-08 09:51:19 -05001228 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001229 let expected: [u8; 5] = [
1230 0x03, /* field type */
1231 0x00, /* first field id */
1232 0x44, /* field delta (4) | field type */
1233 0x59, /* field delta (5) | field type */
1234 0x00 /* field stop */,
1235 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001236
Allen George0e22c362017-01-30 07:15:00 -05001237 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001238 }
1239
1240 #[test]
1241 fn must_round_trip_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001242 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001243
1244 // no bytes should be written however
1245 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1246
1247 // write three fields with tiny field ids
1248 // since they're small the field ids will be encoded as deltas
1249
1250 // since this is the first field (and it's zero) it gets the full varint write
1251 let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
1252 assert_success!(o_prot.write_field_begin(&field_ident_1));
1253 assert_success!(o_prot.write_field_end());
1254
1255 // since this delta > 0 and < 15 it can be encoded as a delta
1256 let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
1257 assert_success!(o_prot.write_field_begin(&field_ident_2));
1258 assert_success!(o_prot.write_field_end());
1259
1260 // since this delta > 0 and < 15 it can be encoded as a delta
1261 let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
1262 assert_success!(o_prot.write_field_begin(&field_ident_3));
1263 assert_success!(o_prot.write_field_end());
1264
1265 // now, finish the struct off
1266 assert_success!(o_prot.write_field_stop());
1267 assert_success!(o_prot.write_struct_end());
1268
Allen George0e22c362017-01-30 07:15:00 -05001269 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001270
1271 // read the struct back
1272 assert_success!(i_prot.read_struct_begin());
1273
1274 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001275 assert_eq!(
1276 read_ident_1,
1277 TFieldIdentifier {
1278 name: None,
1279 ..field_ident_1
1280 }
1281 );
Allen George8b96bfb2016-11-02 08:01:08 -04001282 assert_success!(i_prot.read_field_end());
1283
1284 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001285 assert_eq!(
1286 read_ident_2,
1287 TFieldIdentifier {
1288 name: None,
1289 ..field_ident_2
1290 }
1291 );
Allen George8b96bfb2016-11-02 08:01:08 -04001292 assert_success!(i_prot.read_field_end());
1293
1294 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001295 assert_eq!(
1296 read_ident_3,
1297 TFieldIdentifier {
1298 name: None,
1299 ..field_ident_3
1300 }
1301 );
Allen George8b96bfb2016-11-02 08:01:08 -04001302 assert_success!(i_prot.read_field_end());
1303
1304 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001305 assert_eq!(
1306 read_ident_4,
1307 TFieldIdentifier {
1308 name: None,
1309 field_type: TType::Stop,
1310 id: None,
1311 }
1312 );
Allen George8b96bfb2016-11-02 08:01:08 -04001313
1314 assert_success!(i_prot.read_struct_end());
1315 }
1316
1317 #[test]
1318 fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001319 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001320
1321 // no bytes should be written however
1322 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1323
1324 // write three fields with tiny field ids
1325 // since they're small the field ids will be encoded as deltas
1326
1327 // gets a delta write
1328 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
1329 assert_success!(o_prot.write_field_end());
1330
1331 // since this delta > 0 and < 15 it can be encoded as a delta
1332 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
1333 assert_success!(o_prot.write_field_end());
1334
1335 // since this delta > 0 and < 15 it can be encoded as a delta
1336 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
1337 assert_success!(o_prot.write_field_end());
1338
1339 // now, finish the struct off
1340 assert_success!(o_prot.write_field_stop());
1341 assert_success!(o_prot.write_struct_end());
1342
Allen George7ddbcc02020-11-08 09:51:19 -05001343 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001344 let expected: [u8; 4] = [
1345 0x15, /* field delta (1) | field type */
1346 0x1A, /* field delta (1) | field type */
1347 0x48, /* field delta (4) | field type */
1348 0x00 /* field stop */,
1349 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001350
Allen George0e22c362017-01-30 07:15:00 -05001351 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001352 }
1353
1354 #[test]
1355 fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001356 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001357
1358 // no bytes should be written however
1359 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1360
1361 // write three fields with tiny field ids
1362 // since they're small the field ids will be encoded as deltas
1363
1364 // gets a delta write
1365 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
1366 assert_success!(o_prot.write_field_begin(&field_ident_1));
1367 assert_success!(o_prot.write_field_end());
1368
1369 // since this delta > 0 and < 15 it can be encoded as a delta
1370 let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
1371 assert_success!(o_prot.write_field_begin(&field_ident_2));
1372 assert_success!(o_prot.write_field_end());
1373
1374 // since this delta > 0 and < 15 it can be encoded as a delta
1375 let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
1376 assert_success!(o_prot.write_field_begin(&field_ident_3));
1377 assert_success!(o_prot.write_field_end());
1378
1379 // now, finish the struct off
1380 assert_success!(o_prot.write_field_stop());
1381 assert_success!(o_prot.write_struct_end());
1382
Allen George0e22c362017-01-30 07:15:00 -05001383 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001384
1385 // read the struct back
1386 assert_success!(i_prot.read_struct_begin());
1387
1388 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001389 assert_eq!(
1390 read_ident_1,
1391 TFieldIdentifier {
1392 name: None,
1393 ..field_ident_1
1394 }
1395 );
Allen George8b96bfb2016-11-02 08:01:08 -04001396 assert_success!(i_prot.read_field_end());
1397
1398 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001399 assert_eq!(
1400 read_ident_2,
1401 TFieldIdentifier {
1402 name: None,
1403 ..field_ident_2
1404 }
1405 );
Allen George8b96bfb2016-11-02 08:01:08 -04001406 assert_success!(i_prot.read_field_end());
1407
1408 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001409 assert_eq!(
1410 read_ident_3,
1411 TFieldIdentifier {
1412 name: None,
1413 ..field_ident_3
1414 }
1415 );
Allen George8b96bfb2016-11-02 08:01:08 -04001416 assert_success!(i_prot.read_field_end());
1417
1418 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001419 assert_eq!(
1420 read_ident_4,
1421 TFieldIdentifier {
1422 name: None,
1423 field_type: TType::Stop,
1424 id: None,
1425 }
1426 );
Allen George8b96bfb2016-11-02 08:01:08 -04001427
1428 assert_success!(i_prot.read_struct_end());
1429 }
1430
1431 #[test]
1432 fn must_write_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001433 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001434
1435 // no bytes should be written however
1436 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1437
1438 // write three fields with field ids that cannot be encoded as deltas
1439
1440 // since this is the first field (and it's zero) it gets the full varint write
1441 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
1442 assert_success!(o_prot.write_field_end());
1443
1444 // since this delta is > 15 it is encoded as a zig-zag varint
1445 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
1446 assert_success!(o_prot.write_field_end());
1447
1448 // since this delta is > 15 it is encoded as a zig-zag varint
1449 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
1450 assert_success!(o_prot.write_field_end());
1451
1452 // now, finish the struct off
1453 assert_success!(o_prot.write_field_stop());
1454 assert_success!(o_prot.write_struct_end());
1455
Allen George7ddbcc02020-11-08 09:51:19 -05001456 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001457 let expected: [u8; 8] = [
1458 0x05, /* field type */
1459 0x00, /* first field id */
1460 0x06, /* field type */
1461 0x20, /* zig-zag varint field id */
1462 0x0A, /* field type */
1463 0xC6,
1464 0x01, /* zig-zag varint field id */
1465 0x00 /* field stop */,
1466 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001467
Allen George0e22c362017-01-30 07:15:00 -05001468 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001469 }
1470
1471 #[test]
1472 fn must_round_trip_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001473 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001474
1475 // no bytes should be written however
1476 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1477
1478 // write three fields with field ids that cannot be encoded as deltas
1479
1480 // since this is the first field (and it's zero) it gets the full varint write
1481 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
1482 assert_success!(o_prot.write_field_begin(&field_ident_1));
1483 assert_success!(o_prot.write_field_end());
1484
1485 // since this delta is > 15 it is encoded as a zig-zag varint
1486 let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
1487 assert_success!(o_prot.write_field_begin(&field_ident_2));
1488 assert_success!(o_prot.write_field_end());
1489
1490 // since this delta is > 15 it is encoded as a zig-zag varint
1491 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
1492 assert_success!(o_prot.write_field_begin(&field_ident_3));
1493 assert_success!(o_prot.write_field_end());
1494
1495 // now, finish the struct off
1496 assert_success!(o_prot.write_field_stop());
1497 assert_success!(o_prot.write_struct_end());
1498
Allen George0e22c362017-01-30 07:15:00 -05001499 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001500
1501 // read the struct back
1502 assert_success!(i_prot.read_struct_begin());
1503
1504 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001505 assert_eq!(
1506 read_ident_1,
1507 TFieldIdentifier {
1508 name: None,
1509 ..field_ident_1
1510 }
1511 );
Allen George8b96bfb2016-11-02 08:01:08 -04001512 assert_success!(i_prot.read_field_end());
1513
1514 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001515 assert_eq!(
1516 read_ident_2,
1517 TFieldIdentifier {
1518 name: None,
1519 ..field_ident_2
1520 }
1521 );
Allen George8b96bfb2016-11-02 08:01:08 -04001522 assert_success!(i_prot.read_field_end());
1523
1524 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001525 assert_eq!(
1526 read_ident_3,
1527 TFieldIdentifier {
1528 name: None,
1529 ..field_ident_3
1530 }
1531 );
Allen George8b96bfb2016-11-02 08:01:08 -04001532 assert_success!(i_prot.read_field_end());
1533
1534 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001535 assert_eq!(
1536 read_ident_4,
1537 TFieldIdentifier {
1538 name: None,
1539 field_type: TType::Stop,
1540 id: None,
1541 }
1542 );
Allen George8b96bfb2016-11-02 08:01:08 -04001543
1544 assert_success!(i_prot.read_struct_end());
1545 }
1546
1547 #[test]
1548 fn must_write_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001549 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001550
1551 // no bytes should be written however
1552 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1553
1554 // write three fields with field ids that cannot be encoded as deltas
1555
1556 // since the delta is > 0 and < 15 it gets a delta write
1557 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1558 assert_success!(o_prot.write_field_end());
1559
1560 // since this delta > 0 and < 15 it gets a delta write
1561 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1562 assert_success!(o_prot.write_field_end());
1563
1564 // since this delta is > 15 it is encoded as a zig-zag varint
1565 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
1566 assert_success!(o_prot.write_field_end());
1567
1568 // since this delta is > 15 it is encoded as a zig-zag varint
1569 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
1570 assert_success!(o_prot.write_field_end());
1571
1572 // since this is only 3 up from the previous it is recorded as a delta
1573 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
1574 assert_success!(o_prot.write_field_end());
1575
1576 // now, finish the struct off
1577 assert_success!(o_prot.write_field_stop());
1578 assert_success!(o_prot.write_struct_end());
1579
Allen George7ddbcc02020-11-08 09:51:19 -05001580 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001581 let expected: [u8; 10] = [
1582 0x16, /* field delta (1) | field type */
1583 0x85, /* field delta (8) | field type */
1584 0x0A, /* field type */
1585 0xD0,
1586 0x0F, /* zig-zag varint field id */
1587 0x0A, /* field type */
1588 0xA2,
1589 0x1F, /* zig-zag varint field id */
1590 0x3A, /* field delta (3) | field type */
1591 0x00 /* field stop */,
1592 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001593
Allen George0e22c362017-01-30 07:15:00 -05001594 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001595 }
1596
Allen George7ddbcc02020-11-08 09:51:19 -05001597 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001598 #[test]
1599 fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001600 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001601
1602 // no bytes should be written however
1603 let struct_ident = TStructIdentifier::new("foo");
1604 assert_success!(o_prot.write_struct_begin(&struct_ident));
1605
1606 // write three fields with field ids that cannot be encoded as deltas
1607
1608 // since the delta is > 0 and < 15 it gets a delta write
1609 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1610 assert_success!(o_prot.write_field_begin(&field_ident_1));
1611 assert_success!(o_prot.write_field_end());
1612
1613 // since this delta > 0 and < 15 it gets a delta write
1614 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1615 assert_success!(o_prot.write_field_begin(&field_ident_2));
1616 assert_success!(o_prot.write_field_end());
1617
1618 // since this delta is > 15 it is encoded as a zig-zag varint
1619 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
1620 assert_success!(o_prot.write_field_begin(&field_ident_3));
1621 assert_success!(o_prot.write_field_end());
1622
1623 // since this delta is > 15 it is encoded as a zig-zag varint
1624 let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
1625 assert_success!(o_prot.write_field_begin(&field_ident_4));
1626 assert_success!(o_prot.write_field_end());
1627
1628 // since this is only 3 up from the previous it is recorded as a delta
1629 let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
1630 assert_success!(o_prot.write_field_begin(&field_ident_5));
1631 assert_success!(o_prot.write_field_end());
1632
1633 // now, finish the struct off
1634 assert_success!(o_prot.write_field_stop());
1635 assert_success!(o_prot.write_struct_end());
1636
Allen George0e22c362017-01-30 07:15:00 -05001637 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001638
1639 // read the struct back
1640 assert_success!(i_prot.read_struct_begin());
1641
1642 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001643 assert_eq!(
1644 read_ident_1,
1645 TFieldIdentifier {
1646 name: None,
1647 ..field_ident_1
1648 }
1649 );
Allen George8b96bfb2016-11-02 08:01:08 -04001650 assert_success!(i_prot.read_field_end());
1651
1652 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001653 assert_eq!(
1654 read_ident_2,
1655 TFieldIdentifier {
1656 name: None,
1657 ..field_ident_2
1658 }
1659 );
Allen George8b96bfb2016-11-02 08:01:08 -04001660 assert_success!(i_prot.read_field_end());
1661
1662 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001663 assert_eq!(
1664 read_ident_3,
1665 TFieldIdentifier {
1666 name: None,
1667 ..field_ident_3
1668 }
1669 );
Allen George8b96bfb2016-11-02 08:01:08 -04001670 assert_success!(i_prot.read_field_end());
1671
1672 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001673 assert_eq!(
1674 read_ident_4,
1675 TFieldIdentifier {
1676 name: None,
1677 ..field_ident_4
1678 }
1679 );
Allen George8b96bfb2016-11-02 08:01:08 -04001680 assert_success!(i_prot.read_field_end());
1681
1682 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001683 assert_eq!(
1684 read_ident_5,
1685 TFieldIdentifier {
1686 name: None,
1687 ..field_ident_5
1688 }
1689 );
Allen George8b96bfb2016-11-02 08:01:08 -04001690 assert_success!(i_prot.read_field_end());
1691
1692 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001693 assert_eq!(
1694 read_ident_6,
1695 TFieldIdentifier {
1696 name: None,
1697 field_type: TType::Stop,
1698 id: None,
1699 }
1700 );
Allen George8b96bfb2016-11-02 08:01:08 -04001701
1702 assert_success!(i_prot.read_struct_end());
1703 }
1704
1705 #[test]
1706 fn must_write_nested_structs_0() {
1707 // last field of the containing struct is a delta
1708 // first field of the the contained struct is a delta
1709
Allen George0e22c362017-01-30 07:15:00 -05001710 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001711
1712 // start containing struct
1713 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1714
1715 // containing struct
1716 // since the delta is > 0 and < 15 it gets a delta write
1717 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1718 assert_success!(o_prot.write_field_end());
1719
1720 // containing struct
1721 // since this delta > 0 and < 15 it gets a delta write
1722 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1723 assert_success!(o_prot.write_field_end());
1724
1725 // start contained struct
1726 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1727
1728 // contained struct
1729 // since the delta is > 0 and < 15 it gets a delta write
1730 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
1731 assert_success!(o_prot.write_field_end());
1732
1733 // contained struct
1734 // since this delta > 15 it gets a full write
1735 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1736 assert_success!(o_prot.write_field_end());
1737
1738 // end contained struct
1739 assert_success!(o_prot.write_field_stop());
1740 assert_success!(o_prot.write_struct_end());
1741
1742 // end containing struct
1743 assert_success!(o_prot.write_field_stop());
1744 assert_success!(o_prot.write_struct_end());
1745
Allen George7ddbcc02020-11-08 09:51:19 -05001746 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001747 let expected: [u8; 7] = [
1748 0x16, /* field delta (1) | field type */
1749 0x85, /* field delta (8) | field type */
1750 0x73, /* field delta (7) | field type */
1751 0x07, /* field type */
1752 0x30, /* zig-zag varint field id */
1753 0x00, /* field stop - contained */
1754 0x00 /* field stop - containing */,
1755 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001756
Allen George0e22c362017-01-30 07:15:00 -05001757 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001758 }
1759
Allen George7ddbcc02020-11-08 09:51:19 -05001760 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001761 #[test]
1762 fn must_round_trip_nested_structs_0() {
1763 // last field of the containing struct is a delta
1764 // first field of the the contained struct is a delta
1765
Allen George0e22c362017-01-30 07:15:00 -05001766 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001767
1768 // start containing struct
1769 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1770
1771 // containing struct
1772 // since the delta is > 0 and < 15 it gets a delta write
1773 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1774 assert_success!(o_prot.write_field_begin(&field_ident_1));
1775 assert_success!(o_prot.write_field_end());
1776
1777 // containing struct
1778 // since this delta > 0 and < 15 it gets a delta write
1779 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1780 assert_success!(o_prot.write_field_begin(&field_ident_2));
1781 assert_success!(o_prot.write_field_end());
1782
1783 // start contained struct
1784 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1785
1786 // contained struct
1787 // since the delta is > 0 and < 15 it gets a delta write
1788 let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
1789 assert_success!(o_prot.write_field_begin(&field_ident_3));
1790 assert_success!(o_prot.write_field_end());
1791
1792 // contained struct
1793 // since this delta > 15 it gets a full write
1794 let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
1795 assert_success!(o_prot.write_field_begin(&field_ident_4));
1796 assert_success!(o_prot.write_field_end());
1797
1798 // end contained struct
1799 assert_success!(o_prot.write_field_stop());
1800 assert_success!(o_prot.write_struct_end());
1801
1802 // end containing struct
1803 assert_success!(o_prot.write_field_stop());
1804 assert_success!(o_prot.write_struct_end());
1805
Allen George0e22c362017-01-30 07:15:00 -05001806 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001807
1808 // read containing struct back
1809 assert_success!(i_prot.read_struct_begin());
1810
1811 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001812 assert_eq!(
1813 read_ident_1,
1814 TFieldIdentifier {
1815 name: None,
1816 ..field_ident_1
1817 }
1818 );
Allen George8b96bfb2016-11-02 08:01:08 -04001819 assert_success!(i_prot.read_field_end());
1820
1821 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001822 assert_eq!(
1823 read_ident_2,
1824 TFieldIdentifier {
1825 name: None,
1826 ..field_ident_2
1827 }
1828 );
Allen George8b96bfb2016-11-02 08:01:08 -04001829 assert_success!(i_prot.read_field_end());
1830
1831 // read contained struct back
1832 assert_success!(i_prot.read_struct_begin());
1833
1834 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001835 assert_eq!(
1836 read_ident_3,
1837 TFieldIdentifier {
1838 name: None,
1839 ..field_ident_3
1840 }
1841 );
Allen George8b96bfb2016-11-02 08:01:08 -04001842 assert_success!(i_prot.read_field_end());
1843
1844 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001845 assert_eq!(
1846 read_ident_4,
1847 TFieldIdentifier {
1848 name: None,
1849 ..field_ident_4
1850 }
1851 );
Allen George8b96bfb2016-11-02 08:01:08 -04001852 assert_success!(i_prot.read_field_end());
1853
1854 // end contained struct
1855 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001856 assert_eq!(
1857 read_ident_6,
1858 TFieldIdentifier {
1859 name: None,
1860 field_type: TType::Stop,
1861 id: None,
1862 }
1863 );
Allen George8b96bfb2016-11-02 08:01:08 -04001864 assert_success!(i_prot.read_struct_end());
1865
1866 // end containing struct
1867 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001868 assert_eq!(
1869 read_ident_7,
1870 TFieldIdentifier {
1871 name: None,
1872 field_type: TType::Stop,
1873 id: None,
1874 }
1875 );
Allen George8b96bfb2016-11-02 08:01:08 -04001876 assert_success!(i_prot.read_struct_end());
1877 }
1878
1879 #[test]
1880 fn must_write_nested_structs_1() {
1881 // last field of the containing struct is a delta
1882 // first field of the the contained struct is a full write
1883
Allen George0e22c362017-01-30 07:15:00 -05001884 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001885
1886 // start containing struct
1887 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1888
1889 // containing struct
1890 // since the delta is > 0 and < 15 it gets a delta write
1891 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1892 assert_success!(o_prot.write_field_end());
1893
1894 // containing struct
1895 // since this delta > 0 and < 15 it gets a delta write
1896 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1897 assert_success!(o_prot.write_field_end());
1898
1899 // start contained struct
1900 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1901
1902 // contained struct
1903 // since this delta > 15 it gets a full write
1904 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1905 assert_success!(o_prot.write_field_end());
1906
1907 // contained struct
1908 // since the delta is > 0 and < 15 it gets a delta write
1909 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1910 assert_success!(o_prot.write_field_end());
1911
1912 // end contained struct
1913 assert_success!(o_prot.write_field_stop());
1914 assert_success!(o_prot.write_struct_end());
1915
1916 // end containing struct
1917 assert_success!(o_prot.write_field_stop());
1918 assert_success!(o_prot.write_struct_end());
1919
Allen George7ddbcc02020-11-08 09:51:19 -05001920 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001921 let expected: [u8; 7] = [
1922 0x16, /* field delta (1) | field type */
1923 0x85, /* field delta (8) | field type */
1924 0x07, /* field type */
1925 0x30, /* zig-zag varint field id */
1926 0x33, /* field delta (3) | field type */
1927 0x00, /* field stop - contained */
1928 0x00 /* field stop - containing */,
1929 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001930
Allen George0e22c362017-01-30 07:15:00 -05001931 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001932 }
1933
Allen George7ddbcc02020-11-08 09:51:19 -05001934 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001935 #[test]
1936 fn must_round_trip_nested_structs_1() {
1937 // last field of the containing struct is a delta
1938 // first field of the the contained struct is a full write
1939
Allen George0e22c362017-01-30 07:15:00 -05001940 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001941
1942 // start containing struct
1943 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1944
1945 // containing struct
1946 // since the delta is > 0 and < 15 it gets a delta write
1947 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1948 assert_success!(o_prot.write_field_begin(&field_ident_1));
1949 assert_success!(o_prot.write_field_end());
1950
1951 // containing struct
1952 // since this delta > 0 and < 15 it gets a delta write
1953 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1954 assert_success!(o_prot.write_field_begin(&field_ident_2));
1955 assert_success!(o_prot.write_field_end());
1956
1957 // start contained struct
1958 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1959
1960 // contained struct
1961 // since this delta > 15 it gets a full write
1962 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
1963 assert_success!(o_prot.write_field_begin(&field_ident_3));
1964 assert_success!(o_prot.write_field_end());
1965
1966 // contained struct
1967 // since the delta is > 0 and < 15 it gets a delta write
1968 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
1969 assert_success!(o_prot.write_field_begin(&field_ident_4));
1970 assert_success!(o_prot.write_field_end());
1971
1972 // end contained struct
1973 assert_success!(o_prot.write_field_stop());
1974 assert_success!(o_prot.write_struct_end());
1975
1976 // end containing struct
1977 assert_success!(o_prot.write_field_stop());
1978 assert_success!(o_prot.write_struct_end());
1979
Allen George0e22c362017-01-30 07:15:00 -05001980 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001981
1982 // read containing struct back
1983 assert_success!(i_prot.read_struct_begin());
1984
1985 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001986 assert_eq!(
1987 read_ident_1,
1988 TFieldIdentifier {
1989 name: None,
1990 ..field_ident_1
1991 }
1992 );
Allen George8b96bfb2016-11-02 08:01:08 -04001993 assert_success!(i_prot.read_field_end());
1994
1995 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001996 assert_eq!(
1997 read_ident_2,
1998 TFieldIdentifier {
1999 name: None,
2000 ..field_ident_2
2001 }
2002 );
Allen George8b96bfb2016-11-02 08:01:08 -04002003 assert_success!(i_prot.read_field_end());
2004
2005 // read contained struct back
2006 assert_success!(i_prot.read_struct_begin());
2007
2008 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002009 assert_eq!(
2010 read_ident_3,
2011 TFieldIdentifier {
2012 name: None,
2013 ..field_ident_3
2014 }
2015 );
Allen George8b96bfb2016-11-02 08:01:08 -04002016 assert_success!(i_prot.read_field_end());
2017
2018 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002019 assert_eq!(
2020 read_ident_4,
2021 TFieldIdentifier {
2022 name: None,
2023 ..field_ident_4
2024 }
2025 );
Allen George8b96bfb2016-11-02 08:01:08 -04002026 assert_success!(i_prot.read_field_end());
2027
2028 // end contained struct
2029 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002030 assert_eq!(
2031 read_ident_6,
2032 TFieldIdentifier {
2033 name: None,
2034 field_type: TType::Stop,
2035 id: None,
2036 }
2037 );
Allen George8b96bfb2016-11-02 08:01:08 -04002038 assert_success!(i_prot.read_struct_end());
2039
2040 // end containing struct
2041 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002042 assert_eq!(
2043 read_ident_7,
2044 TFieldIdentifier {
2045 name: None,
2046 field_type: TType::Stop,
2047 id: None,
2048 }
2049 );
Allen George8b96bfb2016-11-02 08:01:08 -04002050 assert_success!(i_prot.read_struct_end());
2051 }
2052
2053 #[test]
2054 fn must_write_nested_structs_2() {
2055 // last field of the containing struct is a full write
2056 // first field of the the contained struct is a delta write
2057
Allen George0e22c362017-01-30 07:15:00 -05002058 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002059
2060 // start containing struct
2061 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2062
2063 // containing struct
2064 // since the delta is > 0 and < 15 it gets a delta write
2065 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2066 assert_success!(o_prot.write_field_end());
2067
2068 // containing struct
2069 // since this delta > 15 it gets a full write
2070 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2071 assert_success!(o_prot.write_field_end());
2072
2073 // start contained struct
2074 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2075
2076 // contained struct
2077 // since this delta > 0 and < 15 it gets a delta write
2078 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
2079 assert_success!(o_prot.write_field_end());
2080
2081 // contained struct
2082 // since the delta is > 0 and < 15 it gets a delta write
2083 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
2084 assert_success!(o_prot.write_field_end());
2085
2086 // end contained struct
2087 assert_success!(o_prot.write_field_stop());
2088 assert_success!(o_prot.write_struct_end());
2089
2090 // end containing struct
2091 assert_success!(o_prot.write_field_stop());
2092 assert_success!(o_prot.write_struct_end());
2093
Allen George7ddbcc02020-11-08 09:51:19 -05002094 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002095 let expected: [u8; 7] = [
2096 0x16, /* field delta (1) | field type */
2097 0x08, /* field type */
2098 0x2A, /* zig-zag varint field id */
2099 0x77, /* field delta(7) | field type */
2100 0x33, /* field delta (3) | field type */
2101 0x00, /* field stop - contained */
2102 0x00 /* field stop - containing */,
2103 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002104
Allen George0e22c362017-01-30 07:15:00 -05002105 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002106 }
2107
Allen George7ddbcc02020-11-08 09:51:19 -05002108 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002109 #[test]
2110 fn must_round_trip_nested_structs_2() {
Allen George0e22c362017-01-30 07:15:00 -05002111 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002112
2113 // start containing struct
2114 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2115
2116 // containing struct
2117 // since the delta is > 0 and < 15 it gets a delta write
2118 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2119 assert_success!(o_prot.write_field_begin(&field_ident_1));
2120 assert_success!(o_prot.write_field_end());
2121
2122 // containing struct
2123 // since this delta > 15 it gets a full write
2124 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2125 assert_success!(o_prot.write_field_begin(&field_ident_2));
2126 assert_success!(o_prot.write_field_end());
2127
2128 // start contained struct
2129 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2130
2131 // contained struct
2132 // since this delta > 0 and < 15 it gets a delta write
2133 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
2134 assert_success!(o_prot.write_field_begin(&field_ident_3));
2135 assert_success!(o_prot.write_field_end());
2136
2137 // contained struct
2138 // since the delta is > 0 and < 15 it gets a delta write
2139 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
2140 assert_success!(o_prot.write_field_begin(&field_ident_4));
2141 assert_success!(o_prot.write_field_end());
2142
2143 // end contained struct
2144 assert_success!(o_prot.write_field_stop());
2145 assert_success!(o_prot.write_struct_end());
2146
2147 // end containing struct
2148 assert_success!(o_prot.write_field_stop());
2149 assert_success!(o_prot.write_struct_end());
2150
Allen George0e22c362017-01-30 07:15:00 -05002151 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002152
2153 // read containing struct back
2154 assert_success!(i_prot.read_struct_begin());
2155
2156 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002157 assert_eq!(
2158 read_ident_1,
2159 TFieldIdentifier {
2160 name: None,
2161 ..field_ident_1
2162 }
2163 );
Allen George8b96bfb2016-11-02 08:01:08 -04002164 assert_success!(i_prot.read_field_end());
2165
2166 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002167 assert_eq!(
2168 read_ident_2,
2169 TFieldIdentifier {
2170 name: None,
2171 ..field_ident_2
2172 }
2173 );
Allen George8b96bfb2016-11-02 08:01:08 -04002174 assert_success!(i_prot.read_field_end());
2175
2176 // read contained struct back
2177 assert_success!(i_prot.read_struct_begin());
2178
2179 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002180 assert_eq!(
2181 read_ident_3,
2182 TFieldIdentifier {
2183 name: None,
2184 ..field_ident_3
2185 }
2186 );
Allen George8b96bfb2016-11-02 08:01:08 -04002187 assert_success!(i_prot.read_field_end());
2188
2189 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002190 assert_eq!(
2191 read_ident_4,
2192 TFieldIdentifier {
2193 name: None,
2194 ..field_ident_4
2195 }
2196 );
Allen George8b96bfb2016-11-02 08:01:08 -04002197 assert_success!(i_prot.read_field_end());
2198
2199 // end contained struct
2200 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002201 assert_eq!(
2202 read_ident_6,
2203 TFieldIdentifier {
2204 name: None,
2205 field_type: TType::Stop,
2206 id: None,
2207 }
2208 );
Allen George8b96bfb2016-11-02 08:01:08 -04002209 assert_success!(i_prot.read_struct_end());
2210
2211 // end containing struct
2212 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002213 assert_eq!(
2214 read_ident_7,
2215 TFieldIdentifier {
2216 name: None,
2217 field_type: TType::Stop,
2218 id: None,
2219 }
2220 );
Allen George8b96bfb2016-11-02 08:01:08 -04002221 assert_success!(i_prot.read_struct_end());
2222 }
2223
2224 #[test]
2225 fn must_write_nested_structs_3() {
2226 // last field of the containing struct is a full write
2227 // first field of the the contained struct is a full write
2228
Allen George0e22c362017-01-30 07:15:00 -05002229 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002230
2231 // start containing struct
2232 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2233
2234 // containing struct
2235 // since the delta is > 0 and < 15 it gets a delta write
2236 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2237 assert_success!(o_prot.write_field_end());
2238
2239 // containing struct
2240 // since this delta > 15 it gets a full write
2241 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2242 assert_success!(o_prot.write_field_end());
2243
2244 // start contained struct
2245 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2246
2247 // contained struct
2248 // since this delta > 15 it gets a full write
2249 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
2250 assert_success!(o_prot.write_field_end());
2251
2252 // contained struct
2253 // since the delta is > 0 and < 15 it gets a delta write
2254 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
2255 assert_success!(o_prot.write_field_end());
2256
2257 // end contained struct
2258 assert_success!(o_prot.write_field_stop());
2259 assert_success!(o_prot.write_struct_end());
2260
2261 // end containing struct
2262 assert_success!(o_prot.write_field_stop());
2263 assert_success!(o_prot.write_struct_end());
2264
Allen George7ddbcc02020-11-08 09:51:19 -05002265 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002266 let expected: [u8; 8] = [
2267 0x16, /* field delta (1) | field type */
2268 0x08, /* field type */
2269 0x2A, /* zig-zag varint field id */
2270 0x07, /* field type */
2271 0x2A, /* zig-zag varint field id */
2272 0x63, /* field delta (6) | field type */
2273 0x00, /* field stop - contained */
2274 0x00 /* field stop - containing */,
2275 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002276
Allen George0e22c362017-01-30 07:15:00 -05002277 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002278 }
2279
Allen George7ddbcc02020-11-08 09:51:19 -05002280 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002281 #[test]
2282 fn must_round_trip_nested_structs_3() {
2283 // last field of the containing struct is a full write
2284 // first field of the the contained struct is a full write
2285
Allen George0e22c362017-01-30 07:15:00 -05002286 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002287
2288 // start containing struct
2289 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2290
2291 // containing struct
2292 // since the delta is > 0 and < 15 it gets a delta write
2293 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2294 assert_success!(o_prot.write_field_begin(&field_ident_1));
2295 assert_success!(o_prot.write_field_end());
2296
2297 // containing struct
2298 // since this delta > 15 it gets a full write
2299 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2300 assert_success!(o_prot.write_field_begin(&field_ident_2));
2301 assert_success!(o_prot.write_field_end());
2302
2303 // start contained struct
2304 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2305
2306 // contained struct
2307 // since this delta > 15 it gets a full write
2308 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
2309 assert_success!(o_prot.write_field_begin(&field_ident_3));
2310 assert_success!(o_prot.write_field_end());
2311
2312 // contained struct
2313 // since the delta is > 0 and < 15 it gets a delta write
2314 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2315 assert_success!(o_prot.write_field_begin(&field_ident_4));
2316 assert_success!(o_prot.write_field_end());
2317
2318 // end contained struct
2319 assert_success!(o_prot.write_field_stop());
2320 assert_success!(o_prot.write_struct_end());
2321
2322 // end containing struct
2323 assert_success!(o_prot.write_field_stop());
2324 assert_success!(o_prot.write_struct_end());
2325
Allen George0e22c362017-01-30 07:15:00 -05002326 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002327
2328 // read containing struct back
2329 assert_success!(i_prot.read_struct_begin());
2330
2331 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002332 assert_eq!(
2333 read_ident_1,
2334 TFieldIdentifier {
2335 name: None,
2336 ..field_ident_1
2337 }
2338 );
Allen George8b96bfb2016-11-02 08:01:08 -04002339 assert_success!(i_prot.read_field_end());
2340
2341 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002342 assert_eq!(
2343 read_ident_2,
2344 TFieldIdentifier {
2345 name: None,
2346 ..field_ident_2
2347 }
2348 );
Allen George8b96bfb2016-11-02 08:01:08 -04002349 assert_success!(i_prot.read_field_end());
2350
2351 // read contained struct back
2352 assert_success!(i_prot.read_struct_begin());
2353
2354 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002355 assert_eq!(
2356 read_ident_3,
2357 TFieldIdentifier {
2358 name: None,
2359 ..field_ident_3
2360 }
2361 );
Allen George8b96bfb2016-11-02 08:01:08 -04002362 assert_success!(i_prot.read_field_end());
2363
2364 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002365 assert_eq!(
2366 read_ident_4,
2367 TFieldIdentifier {
2368 name: None,
2369 ..field_ident_4
2370 }
2371 );
Allen George8b96bfb2016-11-02 08:01:08 -04002372 assert_success!(i_prot.read_field_end());
2373
2374 // end contained struct
2375 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002376 assert_eq!(
2377 read_ident_6,
2378 TFieldIdentifier {
2379 name: None,
2380 field_type: TType::Stop,
2381 id: None,
2382 }
2383 );
Allen George8b96bfb2016-11-02 08:01:08 -04002384 assert_success!(i_prot.read_struct_end());
2385
2386 // end containing struct
2387 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002388 assert_eq!(
2389 read_ident_7,
2390 TFieldIdentifier {
2391 name: None,
2392 field_type: TType::Stop,
2393 id: None,
2394 }
2395 );
Allen George8b96bfb2016-11-02 08:01:08 -04002396 assert_success!(i_prot.read_struct_end());
2397 }
2398
2399 #[test]
2400 fn must_write_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002401 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002402
2403 // no bytes should be written however
2404 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2405
2406 // write three fields with field ids that cannot be encoded as deltas
2407
2408 // since the delta is > 0 and < 16 it gets a delta write
2409 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2410 assert_success!(o_prot.write_bool(true));
2411 assert_success!(o_prot.write_field_end());
2412
2413 // since this delta > 0 and < 15 it gets a delta write
2414 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
2415 assert_success!(o_prot.write_bool(false));
2416 assert_success!(o_prot.write_field_end());
2417
2418 // since this delta > 15 it gets a full write
2419 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
2420 assert_success!(o_prot.write_bool(true));
2421 assert_success!(o_prot.write_field_end());
2422
2423 // since this delta > 15 it gets a full write
2424 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
2425 assert_success!(o_prot.write_bool(false));
2426 assert_success!(o_prot.write_field_end());
2427
2428 // now, finish the struct off
2429 assert_success!(o_prot.write_field_stop());
2430 assert_success!(o_prot.write_struct_end());
2431
Allen George7ddbcc02020-11-08 09:51:19 -05002432 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002433 let expected: [u8; 7] = [
2434 0x11, /* field delta (1) | true */
2435 0x82, /* field delta (8) | false */
2436 0x01, /* true */
2437 0x34, /* field id */
2438 0x02, /* false */
2439 0x5A, /* field id */
2440 0x00 /* stop field */,
2441 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002442
Allen George0e22c362017-01-30 07:15:00 -05002443 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002444 }
2445
Allen George7ddbcc02020-11-08 09:51:19 -05002446 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002447 #[test]
2448 fn must_round_trip_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002449 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002450
2451 // no bytes should be written however
2452 let struct_ident = TStructIdentifier::new("foo");
2453 assert_success!(o_prot.write_struct_begin(&struct_ident));
2454
2455 // write two fields
2456
2457 // since the delta is > 0 and < 16 it gets a delta write
2458 let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
2459 assert_success!(o_prot.write_field_begin(&field_ident_1));
2460 assert_success!(o_prot.write_bool(true));
2461 assert_success!(o_prot.write_field_end());
2462
2463 // since this delta > 0 and < 15 it gets a delta write
2464 let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
2465 assert_success!(o_prot.write_field_begin(&field_ident_2));
2466 assert_success!(o_prot.write_bool(false));
2467 assert_success!(o_prot.write_field_end());
2468
2469 // since this delta > 15 it gets a full write
2470 let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
2471 assert_success!(o_prot.write_field_begin(&field_ident_3));
2472 assert_success!(o_prot.write_bool(true));
2473 assert_success!(o_prot.write_field_end());
2474
2475 // since this delta > 15 it gets a full write
2476 let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
2477 assert_success!(o_prot.write_field_begin(&field_ident_4));
2478 assert_success!(o_prot.write_bool(false));
2479 assert_success!(o_prot.write_field_end());
2480
2481 // now, finish the struct off
2482 assert_success!(o_prot.write_field_stop());
2483 assert_success!(o_prot.write_struct_end());
2484
Allen George0e22c362017-01-30 07:15:00 -05002485 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002486
2487 // read the struct back
2488 assert_success!(i_prot.read_struct_begin());
2489
2490 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002491 assert_eq!(
2492 read_ident_1,
2493 TFieldIdentifier {
2494 name: None,
2495 ..field_ident_1
2496 }
2497 );
Allen George8b96bfb2016-11-02 08:01:08 -04002498 let read_value_1 = assert_success!(i_prot.read_bool());
2499 assert_eq!(read_value_1, true);
2500 assert_success!(i_prot.read_field_end());
2501
2502 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002503 assert_eq!(
2504 read_ident_2,
2505 TFieldIdentifier {
2506 name: None,
2507 ..field_ident_2
2508 }
2509 );
Allen George8b96bfb2016-11-02 08:01:08 -04002510 let read_value_2 = assert_success!(i_prot.read_bool());
2511 assert_eq!(read_value_2, false);
2512 assert_success!(i_prot.read_field_end());
2513
2514 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002515 assert_eq!(
2516 read_ident_3,
2517 TFieldIdentifier {
2518 name: None,
2519 ..field_ident_3
2520 }
2521 );
Allen George8b96bfb2016-11-02 08:01:08 -04002522 let read_value_3 = assert_success!(i_prot.read_bool());
2523 assert_eq!(read_value_3, true);
2524 assert_success!(i_prot.read_field_end());
2525
2526 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002527 assert_eq!(
2528 read_ident_4,
2529 TFieldIdentifier {
2530 name: None,
2531 ..field_ident_4
2532 }
2533 );
Allen George8b96bfb2016-11-02 08:01:08 -04002534 let read_value_4 = assert_success!(i_prot.read_bool());
2535 assert_eq!(read_value_4, false);
2536 assert_success!(i_prot.read_field_end());
2537
2538 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002539 assert_eq!(
2540 read_ident_5,
2541 TFieldIdentifier {
2542 name: None,
2543 field_type: TType::Stop,
2544 id: None,
2545 }
2546 );
Allen George8b96bfb2016-11-02 08:01:08 -04002547
2548 assert_success!(i_prot.read_struct_end());
2549 }
2550
2551 #[test]
2552 #[should_panic]
2553 fn must_fail_if_write_field_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002554 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002555 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2556 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2557 o_prot.write_field_end().unwrap();
2558 }
2559
2560 #[test]
2561 #[should_panic]
2562 fn must_fail_if_write_stop_field_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002563 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002564 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2565 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2566 o_prot.write_field_stop().unwrap();
2567 }
2568
2569 #[test]
2570 #[should_panic]
2571 fn must_fail_if_write_struct_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002572 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002573 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2574 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2575 o_prot.write_struct_end().unwrap();
2576 }
2577
2578 #[test]
2579 #[should_panic]
2580 fn must_fail_if_write_struct_end_without_any_fields() {
Allen George0e22c362017-01-30 07:15:00 -05002581 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002582 o_prot.write_struct_end().unwrap();
2583 }
2584
2585 #[test]
2586 fn must_write_field_end() {
2587 assert_no_write(|o| o.write_field_end());
2588 }
2589
2590 #[test]
2591 fn must_write_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002592 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002593
2594 assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
2595
2596 let expected: [u8; 1] = [0x46 /* size | elem_type */];
2597
Allen George0e22c362017-01-30 07:15:00 -05002598 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002599 }
2600
2601 #[test]
2602 fn must_round_trip_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002603 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002604
2605 let ident = TListIdentifier::new(TType::I08, 10);
2606
2607 assert_success!(o_prot.write_list_begin(&ident));
2608
Allen George0e22c362017-01-30 07:15:00 -05002609 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002610
2611 let res = assert_success!(i_prot.read_list_begin());
2612 assert_eq!(&res, &ident);
2613 }
2614
2615 #[test]
2616 fn must_write_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002617 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002618
2619 let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
2620 assert!(res.is_ok());
2621
Allen George0e22c362017-01-30 07:15:00 -05002622 let expected: [u8; 3] = [
2623 0xF9, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002624 0x8F, 0x4E, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002625 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002626
Allen George0e22c362017-01-30 07:15:00 -05002627 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002628 }
2629
2630 #[test]
2631 fn must_round_trip_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002632 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002633
2634 let ident = TListIdentifier::new(TType::Set, 47381);
2635
2636 assert_success!(o_prot.write_list_begin(&ident));
2637
Allen George0e22c362017-01-30 07:15:00 -05002638 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002639
2640 let res = assert_success!(i_prot.read_list_begin());
2641 assert_eq!(&res, &ident);
2642 }
2643
2644 #[test]
2645 fn must_write_list_end() {
2646 assert_no_write(|o| o.write_list_end());
2647 }
2648
2649 #[test]
2650 fn must_write_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002651 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002652
2653 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
2654
2655 let expected: [u8; 1] = [0x2C /* size | elem_type */];
2656
Allen George0e22c362017-01-30 07:15:00 -05002657 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002658 }
2659
2660 #[test]
2661 fn must_round_trip_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002662 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002663
2664 let ident = TSetIdentifier::new(TType::I16, 7);
2665
2666 assert_success!(o_prot.write_set_begin(&ident));
2667
Allen George0e22c362017-01-30 07:15:00 -05002668 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002669
2670 let res = assert_success!(i_prot.read_set_begin());
2671 assert_eq!(&res, &ident);
2672 }
2673
2674 #[test]
2675 fn must_write_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002676 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002677
2678 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
2679
Allen George0e22c362017-01-30 07:15:00 -05002680 let expected: [u8; 4] = [
2681 0xF7, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002682 0xD3, 0xBA, 0x01, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002683 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002684
Allen George0e22c362017-01-30 07:15:00 -05002685 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002686 }
2687
2688 #[test]
2689 fn must_round_trip_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002690 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002691
Allen George7ddbcc02020-11-08 09:51:19 -05002692 let ident = TSetIdentifier::new(TType::Map, 3_928_429);
Allen George8b96bfb2016-11-02 08:01:08 -04002693
2694 assert_success!(o_prot.write_set_begin(&ident));
2695
Allen George0e22c362017-01-30 07:15:00 -05002696 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002697
2698 let res = assert_success!(i_prot.read_set_begin());
2699 assert_eq!(&res, &ident);
2700 }
2701
2702 #[test]
2703 fn must_write_set_end() {
2704 assert_no_write(|o| o.write_set_end());
2705 }
2706
2707 #[test]
2708 fn must_write_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002709 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002710
2711 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
2712
2713 let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything
2714
Allen George0e22c362017-01-30 07:15:00 -05002715 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002716 }
2717
2718 #[test]
2719 fn must_read_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002720 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002721
2722 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
2723
Allen George0e22c362017-01-30 07:15:00 -05002724 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002725
2726 let res = assert_success!(i_prot.read_map_begin());
Allen George0e22c362017-01-30 07:15:00 -05002727 assert_eq!(
2728 &res,
2729 &TMapIdentifier {
Allen Georgeef7a1892018-12-16 18:01:37 -05002730 key_type: None,
2731 value_type: None,
2732 size: 0,
2733 }
Allen George0e22c362017-01-30 07:15:00 -05002734 );
Allen George8b96bfb2016-11-02 08:01:08 -04002735 }
2736
2737 #[test]
2738 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002739 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002740
Allen Georgeef7a1892018-12-16 18:01:37 -05002741 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
2742 TType::Double,
2743 TType::String,
2744 238
2745 )));
Allen George8b96bfb2016-11-02 08:01:08 -04002746
Allen George0e22c362017-01-30 07:15:00 -05002747 let expected: [u8; 3] = [
Allen Georgeef7a1892018-12-16 18:01:37 -05002748 0xEE, 0x01, /* size as varint */
2749 0x78, /* key type | val type */
Allen George0e22c362017-01-30 07:15:00 -05002750 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002751
Allen George0e22c362017-01-30 07:15:00 -05002752 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002753 }
2754
2755 #[test]
2756 fn must_round_trip_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002757 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002758
Allen George7ddbcc02020-11-08 09:51:19 -05002759 let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349);
Allen George8b96bfb2016-11-02 08:01:08 -04002760
2761 assert_success!(o_prot.write_map_begin(&ident));
2762
Allen George0e22c362017-01-30 07:15:00 -05002763 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002764
2765 let res = assert_success!(i_prot.read_map_begin());
2766 assert_eq!(&res, &ident);
2767 }
2768
2769 #[test]
2770 fn must_write_map_end() {
2771 assert_no_write(|o| o.write_map_end());
2772 }
2773
2774 #[test]
2775 fn must_write_map_with_bool_key_and_value() {
Allen George0e22c362017-01-30 07:15:00 -05002776 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002777
2778 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
2779 assert_success!(o_prot.write_bool(true));
2780 assert_success!(o_prot.write_bool(false));
2781 assert_success!(o_prot.write_map_end());
2782
Allen George0e22c362017-01-30 07:15:00 -05002783 let expected: [u8; 4] = [
2784 0x01, /* size as varint */
2785 0x11, /* key type | val type */
2786 0x01, /* key: true */
Allen Georgeef7a1892018-12-16 18:01:37 -05002787 0x02, /* val: false */
Allen George0e22c362017-01-30 07:15:00 -05002788 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002789
Allen George0e22c362017-01-30 07:15:00 -05002790 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002791 }
2792
2793 #[test]
2794 fn must_round_trip_map_with_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002795 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002796
2797 let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
2798 assert_success!(o_prot.write_map_begin(&map_ident));
2799 assert_success!(o_prot.write_bool(true));
2800 assert_success!(o_prot.write_bool(false));
2801 assert_success!(o_prot.write_bool(false));
2802 assert_success!(o_prot.write_bool(true));
2803 assert_success!(o_prot.write_map_end());
2804
Allen George0e22c362017-01-30 07:15:00 -05002805 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002806
2807 // map header
2808 let rcvd_ident = assert_success!(i_prot.read_map_begin());
2809 assert_eq!(&rcvd_ident, &map_ident);
2810 // key 1
2811 let b = assert_success!(i_prot.read_bool());
2812 assert_eq!(b, true);
2813 // val 1
2814 let b = assert_success!(i_prot.read_bool());
2815 assert_eq!(b, false);
2816 // key 2
2817 let b = assert_success!(i_prot.read_bool());
2818 assert_eq!(b, false);
2819 // val 2
2820 let b = assert_success!(i_prot.read_bool());
2821 assert_eq!(b, true);
2822 // map end
2823 assert_success!(i_prot.read_map_end());
2824 }
2825
2826 #[test]
2827 fn must_read_map_end() {
Allen George0e22c362017-01-30 07:15:00 -05002828 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002829 assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
2830 }
2831
Allen Georgeef7a1892018-12-16 18:01:37 -05002832 fn test_objects() -> (
2833 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2834 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2835 ) {
Allen George0e22c362017-01-30 07:15:00 -05002836 let mem = TBufferChannel::with_capacity(80, 80);
Allen George8b96bfb2016-11-02 08:01:08 -04002837
Allen George0e22c362017-01-30 07:15:00 -05002838 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -04002839
Allen George0e22c362017-01-30 07:15:00 -05002840 let i_prot = TCompactInputProtocol::new(r_mem);
2841 let o_prot = TCompactOutputProtocol::new(w_mem);
Allen George8b96bfb2016-11-02 08:01:08 -04002842
Allen George0e22c362017-01-30 07:15:00 -05002843 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -04002844 }
2845
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002846 #[test]
2847 fn must_read_write_double() {
2848 let (mut i_prot, mut o_prot) = test_objects();
2849
Allen George7ddbcc02020-11-08 09:51:19 -05002850 #[allow(clippy::approx_constant)]
2851 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002852 o_prot.write_double(double).unwrap();
2853 copy_write_buffer_to_read_buffer!(o_prot);
2854
Allen George7ddbcc02020-11-08 09:51:19 -05002855 let read_double = i_prot.read_double().unwrap();
2856 assert!(read_double - double < std::f64::EPSILON);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002857 }
2858
2859 #[test]
2860 fn must_encode_double_as_other_langs() {
2861 let (_, mut o_prot) = test_objects();
2862 let expected = [24, 45, 68, 84, 251, 33, 9, 64];
2863
Allen George7ddbcc02020-11-08 09:51:19 -05002864 #[allow(clippy::approx_constant)]
2865 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002866 o_prot.write_double(double).unwrap();
2867
2868 assert_eq_written_bytes!(o_prot, expected);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002869 }
2870
Allen George0e22c362017-01-30 07:15:00 -05002871 fn assert_no_write<F>(mut write_fn: F)
2872 where
Allen Georgeb0d14132020-03-29 11:48:55 -04002873 F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> crate::Result<()>,
Allen George0e22c362017-01-30 07:15:00 -05002874 {
2875 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002876 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -05002877 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -04002878 }
2879}