blob: 7e1a7510e0c6da6c9c03904a9b975f7c71221a51 [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};
Hasnain Lakhani42d0b712025-07-17 19:57:05 -070029use crate::{ProtocolError, ProtocolErrorKind, TConfiguration};
Allen George8b96bfb2016-11-02 08:01:08 -040030
31const COMPACT_PROTOCOL_ID: u8 = 0x82;
32const COMPACT_VERSION: u8 = 0x01;
33const COMPACT_VERSION_MASK: u8 = 0x1F;
34
35/// Read messages encoded in the Thrift compact protocol.
36///
37/// # Examples
38///
39/// Create and use a `TCompactInputProtocol`.
40///
41/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -040042/// use thrift::protocol::{TCompactInputProtocol, TInputProtocol};
Allen George0e22c362017-01-30 07:15:00 -050043/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -040044///
Allen George0e22c362017-01-30 07:15:00 -050045/// let mut channel = TTcpChannel::new();
46/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040047///
Allen George0e22c362017-01-30 07:15:00 -050048/// let mut protocol = TCompactInputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -040049///
Allen George0e22c362017-01-30 07:15:00 -050050/// let recvd_bool = protocol.read_bool().unwrap();
51/// let recvd_string = protocol.read_string().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040052/// ```
Allen George0e22c362017-01-30 07:15:00 -050053#[derive(Debug)]
54pub struct TCompactInputProtocol<T>
55where
56 T: TReadTransport,
57{
Allen George8b96bfb2016-11-02 08:01:08 -040058 // Identifier of the last field deserialized for a struct.
59 last_read_field_id: i16,
60 // Stack of the last read field ids (a new entry is added each time a nested struct is read).
61 read_field_id_stack: Vec<i16>,
62 // Boolean value for a field.
63 // Saved because boolean fields and their value are encoded in a single byte,
64 // and reading the field only occurs after the field id is read.
65 pending_read_bool_value: Option<bool>,
66 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -050067 transport: T,
Hasnain Lakhani42d0b712025-07-17 19:57:05 -070068 // Configuration
69 config: TConfiguration,
70 // Current recursion depth
71 recursion_depth: usize,
Allen George8b96bfb2016-11-02 08:01:08 -040072}
73
Allen George0e22c362017-01-30 07:15:00 -050074impl<T> TCompactInputProtocol<T>
75where
76 T: TReadTransport,
77{
Allen George8b96bfb2016-11-02 08:01:08 -040078 /// Create a `TCompactInputProtocol` that reads bytes from `transport`.
Allen George0e22c362017-01-30 07:15:00 -050079 pub fn new(transport: T) -> TCompactInputProtocol<T> {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -070080 Self::with_config(transport, TConfiguration::default())
81 }
82
83 /// Create a `TCompactInputProtocol` with custom configuration.
84 pub fn with_config(transport: T, config: TConfiguration) -> TCompactInputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -040085 TCompactInputProtocol {
86 last_read_field_id: 0,
87 read_field_id_stack: Vec::new(),
88 pending_read_bool_value: None,
Allen George7ddbcc02020-11-08 09:51:19 -050089 transport,
Hasnain Lakhani42d0b712025-07-17 19:57:05 -070090 config,
91 recursion_depth: 0,
Allen George8b96bfb2016-11-02 08:01:08 -040092 }
93 }
94
Allen Georgeb0d14132020-03-29 11:48:55 -040095 fn read_list_set_begin(&mut self) -> crate::Result<(TType, i32)> {
Allen George8b96bfb2016-11-02 08:01:08 -040096 let header = self.read_byte()?;
97 let element_type = collection_u8_to_type(header & 0x0F)?;
98
Allen George8b96bfb2016-11-02 08:01:08 -040099 let possible_element_count = (header & 0xF0) >> 4;
Tdxdxoz85d82bf2022-07-17 14:14:12 +0200100 let element_count = if possible_element_count != 15 {
Allen George8b96bfb2016-11-02 08:01:08 -0400101 // high bits set high if count and type encoded separately
Tdxdxoz85d82bf2022-07-17 14:14:12 +0200102 possible_element_count as i32
Allen George8b96bfb2016-11-02 08:01:08 -0400103 } else {
Tdxdxoz85d82bf2022-07-17 14:14:12 +0200104 self.transport.read_varint::<u32>()? as i32
105 };
Allen George8b96bfb2016-11-02 08:01:08 -0400106
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700107 let min_element_size = self.min_serialized_size(element_type);
108 super::check_container_size(&self.config, element_count, min_element_size)?;
109
Allen George8b96bfb2016-11-02 08:01:08 -0400110 Ok((element_type, element_count))
111 }
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700112
113 fn check_recursion_depth(&self) -> crate::Result<()> {
114 if let Some(limit) = self.config.max_recursion_depth() {
115 if self.recursion_depth >= limit {
116 return Err(crate::Error::Protocol(ProtocolError::new(
117 ProtocolErrorKind::DepthLimit,
118 format!("Maximum recursion depth {} exceeded", limit),
119 )));
120 }
121 }
122 Ok(())
123 }
Allen George8b96bfb2016-11-02 08:01:08 -0400124}
125
Allen George0e22c362017-01-30 07:15:00 -0500126impl<T> TInputProtocol for TCompactInputProtocol<T>
127where
128 T: TReadTransport,
129{
Allen Georgeb0d14132020-03-29 11:48:55 -0400130 fn read_message_begin(&mut self) -> crate::Result<TMessageIdentifier> {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700131 // TODO: Once specialization is stable, call the message size tracking here
Allen George8b96bfb2016-11-02 08:01:08 -0400132 let compact_id = self.read_byte()?;
133 if compact_id != COMPACT_PROTOCOL_ID {
Allen Georgeb0d14132020-03-29 11:48:55 -0400134 Err(crate::Error::Protocol(crate::ProtocolError {
135 kind: crate::ProtocolErrorKind::BadVersion,
Allen Georgeef7a1892018-12-16 18:01:37 -0500136 message: format!("invalid compact protocol header {:?}", compact_id),
137 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400138 } else {
139 Ok(())
140 }?;
141
142 let type_and_byte = self.read_byte()?;
143 let received_version = type_and_byte & COMPACT_VERSION_MASK;
144 if received_version != COMPACT_VERSION {
Allen Georgeb0d14132020-03-29 11:48:55 -0400145 Err(crate::Error::Protocol(crate::ProtocolError {
146 kind: crate::ProtocolErrorKind::BadVersion,
Allen Georgeef7a1892018-12-16 18:01:37 -0500147 message: format!(
148 "cannot process compact protocol version {:?}",
149 received_version
Allen George0e22c362017-01-30 07:15:00 -0500150 ),
Allen Georgeef7a1892018-12-16 18:01:37 -0500151 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400152 } else {
153 Ok(())
154 }?;
155
156 // NOTE: unsigned right shift will pad with 0s
157 let message_type: TMessageType = TMessageType::try_from(type_and_byte >> 5)?;
Allen George48905102021-02-20 08:47:01 -0500158 // writing side wrote signed sequence number as u32 to avoid zigzag encoding
159 let sequence_number = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400160 let service_call_name = self.read_string()?;
161
162 self.last_read_field_id = 0;
163
Allen Georgeef7a1892018-12-16 18:01:37 -0500164 Ok(TMessageIdentifier::new(
165 service_call_name,
166 message_type,
167 sequence_number,
168 ))
Allen George8b96bfb2016-11-02 08:01:08 -0400169 }
170
Allen Georgeb0d14132020-03-29 11:48:55 -0400171 fn read_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400172 Ok(())
173 }
174
Allen Georgeb0d14132020-03-29 11:48:55 -0400175 fn read_struct_begin(&mut self) -> crate::Result<Option<TStructIdentifier>> {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700176 self.check_recursion_depth()?;
177 self.recursion_depth += 1;
Allen George8b96bfb2016-11-02 08:01:08 -0400178 self.read_field_id_stack.push(self.last_read_field_id);
179 self.last_read_field_id = 0;
180 Ok(None)
181 }
182
Allen Georgeb0d14132020-03-29 11:48:55 -0400183 fn read_struct_end(&mut self) -> crate::Result<()> {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700184 self.recursion_depth -= 1;
Allen Georgeef7a1892018-12-16 18:01:37 -0500185 self.last_read_field_id = self
186 .read_field_id_stack
Allen George8b96bfb2016-11-02 08:01:08 -0400187 .pop()
188 .expect("should have previous field ids");
189 Ok(())
190 }
191
Allen Georgeb0d14132020-03-29 11:48:55 -0400192 fn read_field_begin(&mut self) -> crate::Result<TFieldIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400193 // we can read at least one byte, which is:
194 // - the type
195 // - the field delta and the type
196 let field_type = self.read_byte()?;
197 let field_delta = (field_type & 0xF0) >> 4;
198 let field_type = match field_type & 0x0F {
199 0x01 => {
200 self.pending_read_bool_value = Some(true);
201 Ok(TType::Bool)
202 }
203 0x02 => {
204 self.pending_read_bool_value = Some(false);
205 Ok(TType::Bool)
206 }
207 ttu8 => u8_to_type(ttu8),
208 }?;
209
210 match field_type {
Allen Georgeef7a1892018-12-16 18:01:37 -0500211 TType::Stop => Ok(
212 TFieldIdentifier::new::<Option<String>, String, Option<i16>>(
213 None,
214 TType::Stop,
215 None,
216 ),
217 ),
Allen George8b96bfb2016-11-02 08:01:08 -0400218 _ => {
219 if field_delta != 0 {
220 self.last_read_field_id += field_delta as i16;
221 } else {
222 self.last_read_field_id = self.read_i16()?;
223 };
224
Allen Georgeef7a1892018-12-16 18:01:37 -0500225 Ok(TFieldIdentifier {
226 name: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500227 field_type,
Allen Georgeef7a1892018-12-16 18:01:37 -0500228 id: Some(self.last_read_field_id),
229 })
Allen George8b96bfb2016-11-02 08:01:08 -0400230 }
231 }
232 }
233
Allen Georgeb0d14132020-03-29 11:48:55 -0400234 fn read_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400235 Ok(())
236 }
237
Allen Georgeb0d14132020-03-29 11:48:55 -0400238 fn read_bool(&mut self) -> crate::Result<bool> {
Allen George8b96bfb2016-11-02 08:01:08 -0400239 match self.pending_read_bool_value.take() {
240 Some(b) => Ok(b),
241 None => {
242 let b = self.read_byte()?;
243 match b {
Jörn Horstmann717bd792025-02-02 23:10:27 +0100244 // Previous versions of the thrift compact protocol specification said to use 0
245 // and 1 inside collections, but that differed from existing implementations.
246 // The specification was updated in https://github.com/apache/thrift/commit/2c29c5665bc442e703480bb0ee60fe925ffe02e8.
247 0x00 => Ok(false),
Allen George8b96bfb2016-11-02 08:01:08 -0400248 0x01 => Ok(true),
249 0x02 => Ok(false),
Allen Georgeb0d14132020-03-29 11:48:55 -0400250 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
251 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500252 message: format!("cannot convert {} into bool", unkn),
253 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400254 }
255 }
256 }
257 }
258
Allen Georgeb0d14132020-03-29 11:48:55 -0400259 fn read_bytes(&mut self) -> crate::Result<Vec<u8>> {
Allen George0e22c362017-01-30 07:15:00 -0500260 let len = self.transport.read_varint::<u32>()?;
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700261
262 if let Some(max_size) = self.config.max_string_size() {
263 if len as usize > max_size {
264 return Err(crate::Error::Protocol(ProtocolError::new(
265 ProtocolErrorKind::SizeLimit,
266 format!(
267 "Byte array size {} exceeds maximum allowed size of {}",
268 len, max_size
269 ),
270 )));
271 }
272 }
273
Allen George8b96bfb2016-11-02 08:01:08 -0400274 let mut buf = vec![0u8; len as usize];
Allen George0e22c362017-01-30 07:15:00 -0500275 self.transport
276 .read_exact(&mut buf)
277 .map_err(From::from)
278 .map(|_| buf)
Allen George8b96bfb2016-11-02 08:01:08 -0400279 }
280
Allen Georgeb0d14132020-03-29 11:48:55 -0400281 fn read_i8(&mut self) -> crate::Result<i8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400282 self.read_byte().map(|i| i as i8)
283 }
284
Allen Georgeb0d14132020-03-29 11:48:55 -0400285 fn read_i16(&mut self) -> crate::Result<i16> {
Allen George0e22c362017-01-30 07:15:00 -0500286 self.transport.read_varint::<i16>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400287 }
288
Allen Georgeb0d14132020-03-29 11:48:55 -0400289 fn read_i32(&mut self) -> crate::Result<i32> {
Allen George0e22c362017-01-30 07:15:00 -0500290 self.transport.read_varint::<i32>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400291 }
292
Allen Georgeb0d14132020-03-29 11:48:55 -0400293 fn read_i64(&mut self) -> crate::Result<i64> {
Allen George0e22c362017-01-30 07:15:00 -0500294 self.transport.read_varint::<i64>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400295 }
296
Allen Georgeb0d14132020-03-29 11:48:55 -0400297 fn read_double(&mut self) -> crate::Result<f64> {
Allen George8a1743d2020-12-05 01:19:27 -0500298 self.transport
299 .read_f64::<LittleEndian>()
300 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400301 }
302
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800303 fn read_uuid(&mut self) -> crate::Result<uuid::Uuid> {
304 uuid::Uuid::from_slice(&self.read_bytes()?).map_err(From::from)
305 }
306
Allen Georgeb0d14132020-03-29 11:48:55 -0400307 fn read_string(&mut self) -> crate::Result<String> {
Allen George8b96bfb2016-11-02 08:01:08 -0400308 let bytes = self.read_bytes()?;
309 String::from_utf8(bytes).map_err(From::from)
310 }
311
Allen Georgeb0d14132020-03-29 11:48:55 -0400312 fn read_list_begin(&mut self) -> crate::Result<TListIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400313 let (element_type, element_count) = self.read_list_set_begin()?;
314 Ok(TListIdentifier::new(element_type, element_count))
315 }
316
Allen Georgeb0d14132020-03-29 11:48:55 -0400317 fn read_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400318 Ok(())
319 }
320
Allen Georgeb0d14132020-03-29 11:48:55 -0400321 fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400322 let (element_type, element_count) = self.read_list_set_begin()?;
323 Ok(TSetIdentifier::new(element_type, element_count))
324 }
325
Allen Georgeb0d14132020-03-29 11:48:55 -0400326 fn read_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400327 Ok(())
328 }
329
Allen Georgeb0d14132020-03-29 11:48:55 -0400330 fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier> {
Allen George0e22c362017-01-30 07:15:00 -0500331 let element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400332 if element_count == 0 {
333 Ok(TMapIdentifier::new(None, None, 0))
334 } else {
335 let type_header = self.read_byte()?;
336 let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
337 let val_type = collection_u8_to_type(type_header & 0x0F)?;
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700338
339 let key_min_size = self.min_serialized_size(key_type);
340 let value_min_size = self.min_serialized_size(val_type);
341 let element_size = key_min_size + value_min_size;
342 super::check_container_size(&self.config, element_count, element_size)?;
343
Allen George8b96bfb2016-11-02 08:01:08 -0400344 Ok(TMapIdentifier::new(key_type, val_type, element_count))
345 }
346 }
347
Allen Georgeb0d14132020-03-29 11:48:55 -0400348 fn read_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400349 Ok(())
350 }
351
352 // utility
353 //
354
Allen Georgeb0d14132020-03-29 11:48:55 -0400355 fn read_byte(&mut self) -> crate::Result<u8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400356 let mut buf = [0u8; 1];
Allen George0e22c362017-01-30 07:15:00 -0500357 self.transport
358 .read_exact(&mut buf)
359 .map_err(From::from)
360 .map(|_| buf[0])
Allen George8b96bfb2016-11-02 08:01:08 -0400361 }
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700362
363 fn min_serialized_size(&self, field_type: TType) -> usize {
364 compact_protocol_min_serialized_size(field_type)
365 }
366}
367
368pub(crate) fn compact_protocol_min_serialized_size(field_type: TType) -> usize {
369 match field_type {
370 TType::Stop => 1, // 1 byte
371 TType::Void => 1, // 1 byte
372 TType::Bool => 1, // 1 byte
373 TType::I08 => 1, // 1 byte
374 TType::Double => 8, // 8 bytes (not varint encoded)
375 TType::I16 => 1, // 1 byte minimum (varint)
376 TType::I32 => 1, // 1 byte minimum (varint)
377 TType::I64 => 1, // 1 byte minimum (varint)
378 TType::String => 1, // 1 byte minimum for length (varint)
379 TType::Struct => 1, // 1 byte minimum (stop field)
380 TType::Map => 1, // 1 byte minimum
381 TType::Set => 1, // 1 byte minimum
382 TType::List => 1, // 1 byte minimum
383 TType::Uuid => 16, // 16 bytes
384 TType::Utf7 => 1, // 1 byte
385 }
Allen George8b96bfb2016-11-02 08:01:08 -0400386}
387
Vadim Chekand3355af2018-01-05 23:12:47 -0500388impl<T> io::Seek for TCompactInputProtocol<T>
389where
390 T: io::Seek + TReadTransport,
391{
392 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
393 self.transport.seek(pos)
394 }
395}
396
Allen George8b96bfb2016-11-02 08:01:08 -0400397/// Factory for creating instances of `TCompactInputProtocol`.
398#[derive(Default)]
399pub struct TCompactInputProtocolFactory;
400
401impl TCompactInputProtocolFactory {
402 /// Create a `TCompactInputProtocolFactory`.
403 pub fn new() -> TCompactInputProtocolFactory {
404 TCompactInputProtocolFactory {}
405 }
406}
407
408impl TInputProtocolFactory for TCompactInputProtocolFactory {
Danny Browning77d96c12019-08-21 13:41:07 -0600409 fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500410 Box::new(TCompactInputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400411 }
412}
413
414/// Write messages using the Thrift compact protocol.
415///
416/// # Examples
417///
418/// Create and use a `TCompactOutputProtocol`.
419///
420/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -0400421/// use thrift::protocol::{TCompactOutputProtocol, TOutputProtocol};
Allen George0e22c362017-01-30 07:15:00 -0500422/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -0400423///
Allen George0e22c362017-01-30 07:15:00 -0500424/// let mut channel = TTcpChannel::new();
425/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400426///
Allen George0e22c362017-01-30 07:15:00 -0500427/// let mut protocol = TCompactOutputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -0400428///
Allen George0e22c362017-01-30 07:15:00 -0500429/// protocol.write_bool(true).unwrap();
430/// protocol.write_string("test_string").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400431/// ```
Allen George0e22c362017-01-30 07:15:00 -0500432#[derive(Debug)]
433pub struct TCompactOutputProtocol<T>
434where
435 T: TWriteTransport,
436{
Allen George8b96bfb2016-11-02 08:01:08 -0400437 // Identifier of the last field serialized for a struct.
438 last_write_field_id: i16,
Allen George0e22c362017-01-30 07:15:00 -0500439 // Stack of the last written field ids (new entry added each time a nested struct is written).
Allen George8b96bfb2016-11-02 08:01:08 -0400440 write_field_id_stack: Vec<i16>,
441 // Field identifier of the boolean field to be written.
442 // Saved because boolean fields and their value are encoded in a single byte
443 pending_write_bool_field_identifier: Option<TFieldIdentifier>,
444 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -0500445 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -0400446}
447
Allen George0e22c362017-01-30 07:15:00 -0500448impl<T> TCompactOutputProtocol<T>
449where
450 T: TWriteTransport,
451{
Allen George8b96bfb2016-11-02 08:01:08 -0400452 /// Create a `TCompactOutputProtocol` that writes bytes to `transport`.
Allen George0e22c362017-01-30 07:15:00 -0500453 pub fn new(transport: T) -> TCompactOutputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -0400454 TCompactOutputProtocol {
455 last_write_field_id: 0,
456 write_field_id_stack: Vec::new(),
457 pending_write_bool_field_identifier: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500458 transport,
Allen George8b96bfb2016-11-02 08:01:08 -0400459 }
460 }
461
462 // FIXME: field_type as unconstrained u8 is bad
Allen Georgeb0d14132020-03-29 11:48:55 -0400463 fn write_field_header(&mut self, field_type: u8, field_id: i16) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400464 let field_delta = field_id - self.last_write_field_id;
465 if field_delta > 0 && field_delta < 15 {
466 self.write_byte(((field_delta as u8) << 4) | field_type)?;
467 } else {
468 self.write_byte(field_type)?;
469 self.write_i16(field_id)?;
470 }
471 self.last_write_field_id = field_id;
472 Ok(())
473 }
474
Allen George8a1743d2020-12-05 01:19:27 -0500475 fn write_list_set_begin(
476 &mut self,
477 element_type: TType,
478 element_count: i32,
479 ) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400480 let elem_identifier = collection_type_to_u8(element_type);
481 if element_count <= 14 {
482 let header = (element_count as u8) << 4 | elem_identifier;
483 self.write_byte(header)
484 } else {
485 let header = 0xF0 | elem_identifier;
486 self.write_byte(header)?;
Allen George48905102021-02-20 08:47:01 -0500487 // element count is strictly positive as per the spec, so
488 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George8b96bfb2016-11-02 08:01:08 -0400489 self.transport
Allen George8b96bfb2016-11-02 08:01:08 -0400490 .write_varint(element_count as u32)
491 .map_err(From::from)
492 .map(|_| ())
493 }
494 }
495
496 fn assert_no_pending_bool_write(&self) {
497 if let Some(ref f) = self.pending_write_bool_field_identifier {
498 panic!("pending bool field {:?} not written", f)
499 }
500 }
501}
502
Allen George0e22c362017-01-30 07:15:00 -0500503impl<T> TOutputProtocol for TCompactOutputProtocol<T>
504where
505 T: TWriteTransport,
506{
Allen Georgeb0d14132020-03-29 11:48:55 -0400507 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400508 self.write_byte(COMPACT_PROTOCOL_ID)?;
509 self.write_byte((u8::from(identifier.message_type) << 5) | COMPACT_VERSION)?;
Allen George48905102021-02-20 08:47:01 -0500510 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George55c3e4c2021-03-01 23:19:52 -0500511 self.transport
512 .write_varint(identifier.sequence_number as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400513 self.write_string(&identifier.name)?;
514 Ok(())
515 }
516
Allen Georgeb0d14132020-03-29 11:48:55 -0400517 fn write_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400518 self.assert_no_pending_bool_write();
519 Ok(())
520 }
521
Allen Georgeb0d14132020-03-29 11:48:55 -0400522 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400523 self.write_field_id_stack.push(self.last_write_field_id);
524 self.last_write_field_id = 0;
525 Ok(())
526 }
527
Allen Georgeb0d14132020-03-29 11:48:55 -0400528 fn write_struct_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400529 self.assert_no_pending_bool_write();
Allen Georgeef7a1892018-12-16 18:01:37 -0500530 self.last_write_field_id = self
531 .write_field_id_stack
Allen George0e22c362017-01-30 07:15:00 -0500532 .pop()
533 .expect("should have previous field ids");
Allen George8b96bfb2016-11-02 08:01:08 -0400534 Ok(())
535 }
536
Allen Georgeb0d14132020-03-29 11:48:55 -0400537 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400538 match identifier.field_type {
539 TType::Bool => {
540 if self.pending_write_bool_field_identifier.is_some() {
Allen George0e22c362017-01-30 07:15:00 -0500541 panic!(
542 "should not have a pending bool while writing another bool with id: \
Allen Georgeef7a1892018-12-16 18:01:37 -0500543 {:?}",
Allen George0e22c362017-01-30 07:15:00 -0500544 identifier
545 )
Allen George8b96bfb2016-11-02 08:01:08 -0400546 }
547 self.pending_write_bool_field_identifier = Some(identifier.clone());
548 Ok(())
549 }
550 _ => {
551 let field_type = type_to_u8(identifier.field_type);
Allen Georgeef7a1892018-12-16 18:01:37 -0500552 let field_id = identifier.id.expect("non-stop field should have field id");
Allen George8b96bfb2016-11-02 08:01:08 -0400553 self.write_field_header(field_type, field_id)
554 }
555 }
556 }
557
Allen Georgeb0d14132020-03-29 11:48:55 -0400558 fn write_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400559 self.assert_no_pending_bool_write();
560 Ok(())
561 }
562
Allen Georgeb0d14132020-03-29 11:48:55 -0400563 fn write_field_stop(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400564 self.assert_no_pending_bool_write();
565 self.write_byte(type_to_u8(TType::Stop))
566 }
567
Allen Georgeb0d14132020-03-29 11:48:55 -0400568 fn write_bool(&mut self, b: bool) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400569 match self.pending_write_bool_field_identifier.take() {
570 Some(pending) => {
571 let field_id = pending.id.expect("bool field should have a field id");
572 let field_type_as_u8 = if b { 0x01 } else { 0x02 };
573 self.write_field_header(field_type_as_u8, field_id)
574 }
575 None => {
576 if b {
577 self.write_byte(0x01)
578 } else {
579 self.write_byte(0x02)
580 }
581 }
582 }
583 }
584
Allen Georgeb0d14132020-03-29 11:48:55 -0400585 fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> {
Allen George48905102021-02-20 08:47:01 -0500586 // length is strictly positive as per the spec, so
587 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500588 self.transport.write_varint(b.len() as u32)?;
589 self.transport.write_all(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400590 }
591
Allen Georgeb0d14132020-03-29 11:48:55 -0400592 fn write_i8(&mut self, i: i8) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400593 self.write_byte(i as u8)
594 }
595
Allen Georgeb0d14132020-03-29 11:48:55 -0400596 fn write_i16(&mut self, i: i16) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500597 self.transport
Allen George48905102021-02-20 08:47:01 -0500598 .write_varint(i)
Allen George0e22c362017-01-30 07:15:00 -0500599 .map_err(From::from)
600 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400601 }
602
Allen Georgeb0d14132020-03-29 11:48:55 -0400603 fn write_i32(&mut self, i: i32) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500604 self.transport
605 .write_varint(i)
606 .map_err(From::from)
607 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400608 }
609
Allen Georgeb0d14132020-03-29 11:48:55 -0400610 fn write_i64(&mut self, i: i64) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500611 self.transport
612 .write_varint(i)
613 .map_err(From::from)
614 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400615 }
616
Allen Georgeb0d14132020-03-29 11:48:55 -0400617 fn write_double(&mut self, d: f64) -> crate::Result<()> {
Allen George8a1743d2020-12-05 01:19:27 -0500618 self.transport
619 .write_f64::<LittleEndian>(d)
620 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400621 }
622
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800623 fn write_uuid(&mut self, uuid: &uuid::Uuid) -> crate::Result<()> {
624 self.write_bytes(uuid.as_bytes())
625 }
626
Allen Georgeb0d14132020-03-29 11:48:55 -0400627 fn write_string(&mut self, s: &str) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400628 self.write_bytes(s.as_bytes())
629 }
630
Allen Georgeb0d14132020-03-29 11:48:55 -0400631 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400632 self.write_list_set_begin(identifier.element_type, identifier.size)
633 }
634
Allen Georgeb0d14132020-03-29 11:48:55 -0400635 fn write_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400636 Ok(())
637 }
638
Allen Georgeb0d14132020-03-29 11:48:55 -0400639 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400640 self.write_list_set_begin(identifier.element_type, identifier.size)
641 }
642
Allen Georgeb0d14132020-03-29 11:48:55 -0400643 fn write_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400644 Ok(())
645 }
646
Allen Georgeb0d14132020-03-29 11:48:55 -0400647 fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400648 if identifier.size == 0 {
649 self.write_byte(0)
650 } else {
Allen George48905102021-02-20 08:47:01 -0500651 // element count is strictly positive as per the spec, so
652 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500653 self.transport.write_varint(identifier.size as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400654
Allen George0e22c362017-01-30 07:15:00 -0500655 let key_type = identifier
656 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400657 .expect("map identifier to write should contain key type");
658 let key_type_byte = collection_type_to_u8(key_type) << 4;
659
Allen George0e22c362017-01-30 07:15:00 -0500660 let val_type = identifier
661 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400662 .expect("map identifier to write should contain value type");
663 let val_type_byte = collection_type_to_u8(val_type);
664
665 let map_type_header = key_type_byte | val_type_byte;
666 self.write_byte(map_type_header)
667 }
668 }
669
Allen Georgeb0d14132020-03-29 11:48:55 -0400670 fn write_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400671 Ok(())
672 }
673
Allen Georgeb0d14132020-03-29 11:48:55 -0400674 fn flush(&mut self) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500675 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400676 }
677
678 // utility
679 //
680
Allen Georgeb0d14132020-03-29 11:48:55 -0400681 fn write_byte(&mut self, b: u8) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500682 self.transport.write(&[b]).map_err(From::from).map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400683 }
684}
685
686/// Factory for creating instances of `TCompactOutputProtocol`.
687#[derive(Default)]
688pub struct TCompactOutputProtocolFactory;
689
690impl TCompactOutputProtocolFactory {
691 /// Create a `TCompactOutputProtocolFactory`.
692 pub fn new() -> TCompactOutputProtocolFactory {
693 TCompactOutputProtocolFactory {}
694 }
695}
696
697impl TOutputProtocolFactory for TCompactOutputProtocolFactory {
Allen George8a1743d2020-12-05 01:19:27 -0500698 fn create(
699 &self,
700 transport: Box<dyn TWriteTransport + Send>,
701 ) -> Box<dyn TOutputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500702 Box::new(TCompactOutputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400703 }
704}
705
706fn collection_type_to_u8(field_type: TType) -> u8 {
707 match field_type {
708 TType::Bool => 0x01,
709 f => type_to_u8(f),
710 }
711}
712
713fn type_to_u8(field_type: TType) -> u8 {
714 match field_type {
715 TType::Stop => 0x00,
716 TType::I08 => 0x03, // equivalent to TType::Byte
717 TType::I16 => 0x04,
718 TType::I32 => 0x05,
719 TType::I64 => 0x06,
720 TType::Double => 0x07,
721 TType::String => 0x08,
722 TType::List => 0x09,
723 TType::Set => 0x0A,
724 TType::Map => 0x0B,
725 TType::Struct => 0x0C,
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800726 TType::Uuid => 0x0D,
Allen George2b691ee2021-10-14 22:25:07 -0400727 _ => panic!("should not have attempted to convert {} to u8", field_type),
Allen George8b96bfb2016-11-02 08:01:08 -0400728 }
729}
730
Allen Georgeb0d14132020-03-29 11:48:55 -0400731fn collection_u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400732 match b {
Jörn Horstmann717bd792025-02-02 23:10:27 +0100733 // For historical and compatibility reasons, a reader should be capable to deal with both cases.
734 // The only valid value in the original spec was 2, but due to a widespread implementation bug
735 // the defacto standard across large parts of the library became 1 instead.
736 // As a result, both values are now allowed.
737 0x01 | 0x02 => Ok(TType::Bool),
Allen George8b96bfb2016-11-02 08:01:08 -0400738 o => u8_to_type(o),
739 }
740}
741
Allen Georgeb0d14132020-03-29 11:48:55 -0400742fn u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400743 match b {
744 0x00 => Ok(TType::Stop),
745 0x03 => Ok(TType::I08), // equivalent to TType::Byte
746 0x04 => Ok(TType::I16),
747 0x05 => Ok(TType::I32),
748 0x06 => Ok(TType::I64),
749 0x07 => Ok(TType::Double),
750 0x08 => Ok(TType::String),
751 0x09 => Ok(TType::List),
752 0x0A => Ok(TType::Set),
753 0x0B => Ok(TType::Map),
754 0x0C => Ok(TType::Struct),
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800755 0x0D => Ok(TType::Uuid),
Allen Georgeb0d14132020-03-29 11:48:55 -0400756 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
757 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500758 message: format!("cannot convert {} into TType", unkn),
759 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400760 }
761}
762
763#[cfg(test)]
764mod tests {
765
Allen Georgeb0d14132020-03-29 11:48:55 -0400766 use crate::protocol::{
Allen Georgeef7a1892018-12-16 18:01:37 -0500767 TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
768 TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
769 };
Allen Georgeb0d14132020-03-29 11:48:55 -0400770 use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400771
772 use super::*;
773
774 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500775 fn must_write_message_begin_largest_maximum_positive_sequence_number() {
776 let (_, mut o_prot) = test_objects();
777
778 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
779 "bar",
780 TMessageType::Reply,
781 i32::MAX
782 )));
783
784 #[rustfmt::skip]
785 let expected: [u8; 11] = [
786 0x82, /* protocol ID */
787 0x41, /* message type | protocol version */
788 0xFF,
789 0xFF,
790 0xFF,
791 0xFF,
792 0x07, /* non-zig-zag varint sequence number */
793 0x03, /* message-name length */
794 0x62,
795 0x61,
796 0x72 /* "bar" */,
797 ];
798
799 assert_eq_written_bytes!(o_prot, expected);
800 }
801
802 #[test]
803 fn must_read_message_begin_largest_maximum_positive_sequence_number() {
804 let (mut i_prot, _) = test_objects();
805
806 #[rustfmt::skip]
807 let source_bytes: [u8; 11] = [
808 0x82, /* protocol ID */
809 0x41, /* message type | protocol version */
810 0xFF,
811 0xFF,
812 0xFF,
813 0xFF,
814 0x07, /* non-zig-zag varint sequence number */
815 0x03, /* message-name length */
816 0x62,
817 0x61,
818 0x72 /* "bar" */,
819 ];
820
821 i_prot.transport.set_readable_bytes(&source_bytes);
822
823 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MAX);
824 let res = assert_success!(i_prot.read_message_begin());
825
826 assert_eq!(&expected, &res);
827 }
828
829 #[test]
830 fn must_write_message_begin_positive_sequence_number_0() {
Allen George0e22c362017-01-30 07:15:00 -0500831 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400832
Allen Georgeef7a1892018-12-16 18:01:37 -0500833 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
834 "foo",
835 TMessageType::Call,
836 431
837 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400838
Allen George7ddbcc02020-11-08 09:51:19 -0500839 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500840 let expected: [u8; 8] = [
841 0x82, /* protocol ID */
842 0x21, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500843 0xAF,
844 0x03, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500845 0x03, /* message-name length */
846 0x66,
847 0x6F,
848 0x6F /* "foo" */,
849 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400850
Allen George0e22c362017-01-30 07:15:00 -0500851 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400852 }
853
854 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500855 fn must_read_message_begin_positive_sequence_number_0() {
856 let (mut i_prot, _) = test_objects();
857
858 #[rustfmt::skip]
859 let source_bytes: [u8; 8] = [
860 0x82, /* protocol ID */
861 0x21, /* message type | protocol version */
862 0xAF,
863 0x03, /* non-zig-zag varint sequence number */
864 0x03, /* message-name length */
865 0x66,
866 0x6F,
867 0x6F /* "foo" */,
868 ];
869
870 i_prot.transport.set_readable_bytes(&source_bytes);
871
872 let expected = TMessageIdentifier::new("foo", TMessageType::Call, 431);
873 let res = assert_success!(i_prot.read_message_begin());
874
875 assert_eq!(&expected, &res);
876 }
877
878 #[test]
879 fn must_write_message_begin_positive_sequence_number_1() {
Allen George0e22c362017-01-30 07:15:00 -0500880 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400881
Allen Georgeef7a1892018-12-16 18:01:37 -0500882 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
883 "bar",
884 TMessageType::Reply,
Allen George7ddbcc02020-11-08 09:51:19 -0500885 991_828
Allen Georgeef7a1892018-12-16 18:01:37 -0500886 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400887
Allen George7ddbcc02020-11-08 09:51:19 -0500888 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500889 let expected: [u8; 9] = [
890 0x82, /* protocol ID */
891 0x41, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500892 0xD4,
893 0xC4,
894 0x3C, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500895 0x03, /* message-name length */
896 0x62,
897 0x61,
898 0x72 /* "bar" */,
899 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400900
Allen George0e22c362017-01-30 07:15:00 -0500901 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400902 }
903
904 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500905 fn must_read_message_begin_positive_sequence_number_1() {
906 let (mut i_prot, _) = test_objects();
907
908 #[rustfmt::skip]
909 let source_bytes: [u8; 9] = [
910 0x82, /* protocol ID */
911 0x41, /* message type | protocol version */
912 0xD4,
913 0xC4,
914 0x3C, /* non-zig-zag varint sequence number */
915 0x03, /* message-name length */
916 0x62,
917 0x61,
918 0x72 /* "bar" */,
919 ];
920
921 i_prot.transport.set_readable_bytes(&source_bytes);
922
923 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 991_828);
924 let res = assert_success!(i_prot.read_message_begin());
925
926 assert_eq!(&expected, &res);
927 }
928
929 #[test]
930 fn must_write_message_begin_zero_sequence_number() {
931 let (_, mut o_prot) = test_objects();
932
933 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
934 "bar",
935 TMessageType::Reply,
936 0
937 )));
938
939 #[rustfmt::skip]
940 let expected: [u8; 7] = [
941 0x82, /* protocol ID */
942 0x41, /* message type | protocol version */
943 0x00, /* non-zig-zag varint sequence number */
944 0x03, /* message-name length */
945 0x62,
946 0x61,
947 0x72 /* "bar" */,
948 ];
949
950 assert_eq_written_bytes!(o_prot, expected);
951 }
952
953 #[test]
954 fn must_read_message_begin_zero_sequence_number() {
955 let (mut i_prot, _) = test_objects();
956
957 #[rustfmt::skip]
958 let source_bytes: [u8; 7] = [
959 0x82, /* protocol ID */
960 0x41, /* message type | protocol version */
961 0x00, /* non-zig-zag varint sequence number */
962 0x03, /* message-name length */
963 0x62,
964 0x61,
965 0x72 /* "bar" */,
966 ];
967
968 i_prot.transport.set_readable_bytes(&source_bytes);
969
970 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 0);
971 let res = assert_success!(i_prot.read_message_begin());
972
973 assert_eq!(&expected, &res);
974 }
975
976 #[test]
977 fn must_write_message_begin_largest_minimum_negative_sequence_number() {
978 let (_, mut o_prot) = test_objects();
979
980 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
981 "bar",
982 TMessageType::Reply,
983 i32::MIN
984 )));
985
986 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
987 #[rustfmt::skip]
988 let expected: [u8; 11] = [
989 0x82, /* protocol ID */
990 0x41, /* message type | protocol version */
991 0x80,
992 0x80,
993 0x80,
994 0x80,
995 0x08, /* non-zig-zag varint sequence number */
996 0x03, /* message-name length */
997 0x62,
998 0x61,
999 0x72 /* "bar" */,
1000 ];
1001
1002 assert_eq_written_bytes!(o_prot, expected);
1003 }
1004
1005 #[test]
1006 fn must_read_message_begin_largest_minimum_negative_sequence_number() {
1007 let (mut i_prot, _) = test_objects();
1008
1009 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
1010 #[rustfmt::skip]
1011 let source_bytes: [u8; 11] = [
1012 0x82, /* protocol ID */
1013 0x41, /* message type | protocol version */
1014 0x80,
1015 0x80,
1016 0x80,
1017 0x80,
1018 0x08, /* non-zig-zag varint sequence number */
1019 0x03, /* message-name length */
1020 0x62,
1021 0x61,
1022 0x72 /* "bar" */,
1023 ];
1024
1025 i_prot.transport.set_readable_bytes(&source_bytes);
1026
1027 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MIN);
1028 let res = assert_success!(i_prot.read_message_begin());
1029
1030 assert_eq!(&expected, &res);
1031 }
1032
1033 #[test]
1034 fn must_write_message_begin_negative_sequence_number_0() {
1035 let (_, mut o_prot) = test_objects();
1036
1037 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1038 "foo",
1039 TMessageType::Call,
1040 -431
1041 )));
1042
1043 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
1044 #[rustfmt::skip]
1045 let expected: [u8; 11] = [
1046 0x82, /* protocol ID */
1047 0x21, /* message type | protocol version */
1048 0xD1,
1049 0xFC,
1050 0xFF,
1051 0xFF,
1052 0x0F, /* non-zig-zag varint sequence number */
1053 0x03, /* message-name length */
1054 0x66,
1055 0x6F,
1056 0x6F /* "foo" */,
1057 ];
1058
1059 assert_eq_written_bytes!(o_prot, expected);
1060 }
1061
1062 #[test]
1063 fn must_read_message_begin_negative_sequence_number_0() {
1064 let (mut i_prot, _) = test_objects();
1065
1066 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
1067 #[rustfmt::skip]
1068 let source_bytes: [u8; 11] = [
1069 0x82, /* protocol ID */
1070 0x21, /* message type | protocol version */
1071 0xD1,
1072 0xFC,
1073 0xFF,
1074 0xFF,
1075 0x0F, /* non-zig-zag varint sequence number */
1076 0x03, /* message-name length */
1077 0x66,
1078 0x6F,
1079 0x6F /* "foo" */,
1080 ];
1081
1082 i_prot.transport.set_readable_bytes(&source_bytes);
1083
1084 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -431);
1085 let res = assert_success!(i_prot.read_message_begin());
1086
1087 assert_eq!(&expected, &res);
1088 }
1089
1090 #[test]
1091 fn must_write_message_begin_negative_sequence_number_1() {
1092 let (_, mut o_prot) = test_objects();
1093
1094 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1095 "foo",
1096 TMessageType::Call,
1097 -73_184_125
1098 )));
1099
1100 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1101 #[rustfmt::skip]
1102 let expected: [u8; 11] = [
1103 0x82, /* protocol ID */
1104 0x21, /* message type | protocol version */
1105 0x83,
1106 0x99,
1107 0x8D,
1108 0xDD,
1109 0x0F, /* non-zig-zag varint sequence number */
1110 0x03, /* message-name length */
1111 0x66,
1112 0x6F,
1113 0x6F /* "foo" */,
1114 ];
1115
1116 assert_eq_written_bytes!(o_prot, expected);
1117 }
1118
1119 #[test]
1120 fn must_read_message_begin_negative_sequence_number_1() {
1121 let (mut i_prot, _) = test_objects();
1122
1123 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1124 #[rustfmt::skip]
1125 let source_bytes: [u8; 11] = [
1126 0x82, /* protocol ID */
1127 0x21, /* message type | protocol version */
1128 0x83,
1129 0x99,
1130 0x8D,
1131 0xDD,
1132 0x0F, /* non-zig-zag varint sequence number */
1133 0x03, /* message-name length */
1134 0x66,
1135 0x6F,
1136 0x6F /* "foo" */,
1137 ];
1138
1139 i_prot.transport.set_readable_bytes(&source_bytes);
1140
1141 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -73_184_125);
1142 let res = assert_success!(i_prot.read_message_begin());
1143
1144 assert_eq!(&expected, &res);
1145 }
1146
1147 #[test]
1148 fn must_write_message_begin_negative_sequence_number_2() {
1149 let (_, mut o_prot) = test_objects();
1150
1151 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1152 "foo",
1153 TMessageType::Call,
1154 -1_073_741_823
1155 )));
1156
1157 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
1158 #[rustfmt::skip]
1159 let expected: [u8; 11] = [
1160 0x82, /* protocol ID */
1161 0x21, /* message type | protocol version */
1162 0x81,
1163 0x80,
1164 0x80,
1165 0x80,
1166 0x0C, /* non-zig-zag varint sequence number */
1167 0x03, /* message-name length */
1168 0x66,
1169 0x6F,
1170 0x6F /* "foo" */,
1171 ];
1172
1173 assert_eq_written_bytes!(o_prot, expected);
1174 }
1175
1176 #[test]
1177 fn must_read_message_begin_negative_sequence_number_2() {
1178 let (mut i_prot, _) = test_objects();
1179
1180 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
Allen George55c3e4c2021-03-01 23:19:52 -05001181 #[rustfmt::skip]
Allen George8a1743d2020-12-05 01:19:27 -05001182 let source_bytes: [u8; 11] = [
1183 0x82, /* protocol ID */
1184 0x21, /* message type | protocol version */
1185 0x81,
1186 0x80,
1187 0x80,
1188 0x80,
1189 0x0C, /* non-zig-zag varint sequence number */
1190 0x03, /* message-name length */
1191 0x66,
1192 0x6F,
Allen George55c3e4c2021-03-01 23:19:52 -05001193 0x6F, /* "foo" */
Allen George8a1743d2020-12-05 01:19:27 -05001194 ];
1195
1196 i_prot.transport.set_readable_bytes(&source_bytes);
1197
1198 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -1_073_741_823);
1199 let res = assert_success!(i_prot.read_message_begin());
1200
1201 assert_eq!(&expected, &res);
1202 }
1203
1204 #[test]
Nik Claytone7917602020-03-05 11:51:15 +01001205 fn must_round_trip_upto_i64_maxvalue() {
1206 // See https://issues.apache.org/jira/browse/THRIFT-5131
1207 for i in 0..64 {
1208 let (mut i_prot, mut o_prot) = test_objects();
1209 let val: i64 = ((1u64 << i) - 1) as i64;
1210
1211 o_prot
Allen George8a1743d2020-12-05 01:19:27 -05001212 .write_field_begin(&TFieldIdentifier::new("val", TType::I64, 1))
Nik Claytone7917602020-03-05 11:51:15 +01001213 .unwrap();
1214 o_prot.write_i64(val).unwrap();
1215 o_prot.write_field_end().unwrap();
1216 o_prot.flush().unwrap();
1217
1218 copy_write_buffer_to_read_buffer!(o_prot);
1219
1220 i_prot.read_field_begin().unwrap();
1221 assert_eq!(val, i_prot.read_i64().unwrap());
1222 }
1223 }
1224
1225 #[test]
Allen George8b96bfb2016-11-02 08:01:08 -04001226 fn must_round_trip_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -05001227 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001228
Allen George7ddbcc02020-11-08 09:51:19 -05001229 let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948);
Allen George8b96bfb2016-11-02 08:01:08 -04001230
1231 assert_success!(o_prot.write_message_begin(&ident));
1232
Allen George0e22c362017-01-30 07:15:00 -05001233 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001234
1235 let res = assert_success!(i_prot.read_message_begin());
1236 assert_eq!(&res, &ident);
1237 }
1238
1239 #[test]
1240 fn must_write_message_end() {
1241 assert_no_write(|o| o.write_message_end());
1242 }
1243
1244 // NOTE: structs and fields are tested together
1245 //
1246
1247 #[test]
1248 fn must_write_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001249 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001250
1251 // no bytes should be written however
1252 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1253
1254 // write three fields with tiny field ids
1255 // since they're small the field ids will be encoded as deltas
1256
1257 // since this is the first field (and it's zero) it gets the full varint write
1258 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
1259 assert_success!(o_prot.write_field_end());
1260
1261 // since this delta > 0 and < 15 it can be encoded as a delta
1262 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
1263 assert_success!(o_prot.write_field_end());
1264
1265 // since this delta > 0 and < 15 it can be encoded as a delta
1266 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
1267 assert_success!(o_prot.write_field_end());
1268
1269 // now, finish the struct off
1270 assert_success!(o_prot.write_field_stop());
1271 assert_success!(o_prot.write_struct_end());
1272
Allen George7ddbcc02020-11-08 09:51:19 -05001273 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001274 let expected: [u8; 5] = [
1275 0x03, /* field type */
1276 0x00, /* first field id */
1277 0x44, /* field delta (4) | field type */
1278 0x59, /* field delta (5) | field type */
1279 0x00 /* field stop */,
1280 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001281
Allen George0e22c362017-01-30 07:15:00 -05001282 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001283 }
1284
1285 #[test]
1286 fn must_round_trip_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001287 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001288
1289 // no bytes should be written however
1290 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1291
1292 // write three fields with tiny field ids
1293 // since they're small the field ids will be encoded as deltas
1294
1295 // since this is the first field (and it's zero) it gets the full varint write
1296 let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
1297 assert_success!(o_prot.write_field_begin(&field_ident_1));
1298 assert_success!(o_prot.write_field_end());
1299
1300 // since this delta > 0 and < 15 it can be encoded as a delta
1301 let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
1302 assert_success!(o_prot.write_field_begin(&field_ident_2));
1303 assert_success!(o_prot.write_field_end());
1304
1305 // since this delta > 0 and < 15 it can be encoded as a delta
1306 let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
1307 assert_success!(o_prot.write_field_begin(&field_ident_3));
1308 assert_success!(o_prot.write_field_end());
1309
1310 // now, finish the struct off
1311 assert_success!(o_prot.write_field_stop());
1312 assert_success!(o_prot.write_struct_end());
1313
Allen George0e22c362017-01-30 07:15:00 -05001314 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001315
1316 // read the struct back
1317 assert_success!(i_prot.read_struct_begin());
1318
1319 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001320 assert_eq!(
1321 read_ident_1,
1322 TFieldIdentifier {
1323 name: None,
1324 ..field_ident_1
1325 }
1326 );
Allen George8b96bfb2016-11-02 08:01:08 -04001327 assert_success!(i_prot.read_field_end());
1328
1329 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001330 assert_eq!(
1331 read_ident_2,
1332 TFieldIdentifier {
1333 name: None,
1334 ..field_ident_2
1335 }
1336 );
Allen George8b96bfb2016-11-02 08:01:08 -04001337 assert_success!(i_prot.read_field_end());
1338
1339 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001340 assert_eq!(
1341 read_ident_3,
1342 TFieldIdentifier {
1343 name: None,
1344 ..field_ident_3
1345 }
1346 );
Allen George8b96bfb2016-11-02 08:01:08 -04001347 assert_success!(i_prot.read_field_end());
1348
1349 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001350 assert_eq!(
1351 read_ident_4,
1352 TFieldIdentifier {
1353 name: None,
1354 field_type: TType::Stop,
1355 id: None,
1356 }
1357 );
Allen George8b96bfb2016-11-02 08:01:08 -04001358
1359 assert_success!(i_prot.read_struct_end());
1360 }
1361
1362 #[test]
1363 fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001364 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001365
1366 // no bytes should be written however
1367 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1368
1369 // write three fields with tiny field ids
1370 // since they're small the field ids will be encoded as deltas
1371
1372 // gets a delta write
1373 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
1374 assert_success!(o_prot.write_field_end());
1375
1376 // since this delta > 0 and < 15 it can be encoded as a delta
1377 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
1378 assert_success!(o_prot.write_field_end());
1379
1380 // since this delta > 0 and < 15 it can be encoded as a delta
1381 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
1382 assert_success!(o_prot.write_field_end());
1383
1384 // now, finish the struct off
1385 assert_success!(o_prot.write_field_stop());
1386 assert_success!(o_prot.write_struct_end());
1387
Allen George7ddbcc02020-11-08 09:51:19 -05001388 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001389 let expected: [u8; 4] = [
1390 0x15, /* field delta (1) | field type */
1391 0x1A, /* field delta (1) | field type */
1392 0x48, /* field delta (4) | field type */
1393 0x00 /* field stop */,
1394 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001395
Allen George0e22c362017-01-30 07:15:00 -05001396 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001397 }
1398
1399 #[test]
1400 fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001401 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001402
1403 // no bytes should be written however
1404 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1405
1406 // write three fields with tiny field ids
1407 // since they're small the field ids will be encoded as deltas
1408
1409 // gets a delta write
1410 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
1411 assert_success!(o_prot.write_field_begin(&field_ident_1));
1412 assert_success!(o_prot.write_field_end());
1413
1414 // since this delta > 0 and < 15 it can be encoded as a delta
1415 let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
1416 assert_success!(o_prot.write_field_begin(&field_ident_2));
1417 assert_success!(o_prot.write_field_end());
1418
1419 // since this delta > 0 and < 15 it can be encoded as a delta
1420 let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
1421 assert_success!(o_prot.write_field_begin(&field_ident_3));
1422 assert_success!(o_prot.write_field_end());
1423
1424 // now, finish the struct off
1425 assert_success!(o_prot.write_field_stop());
1426 assert_success!(o_prot.write_struct_end());
1427
Allen George0e22c362017-01-30 07:15:00 -05001428 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001429
1430 // read the struct back
1431 assert_success!(i_prot.read_struct_begin());
1432
1433 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001434 assert_eq!(
1435 read_ident_1,
1436 TFieldIdentifier {
1437 name: None,
1438 ..field_ident_1
1439 }
1440 );
Allen George8b96bfb2016-11-02 08:01:08 -04001441 assert_success!(i_prot.read_field_end());
1442
1443 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001444 assert_eq!(
1445 read_ident_2,
1446 TFieldIdentifier {
1447 name: None,
1448 ..field_ident_2
1449 }
1450 );
Allen George8b96bfb2016-11-02 08:01:08 -04001451 assert_success!(i_prot.read_field_end());
1452
1453 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001454 assert_eq!(
1455 read_ident_3,
1456 TFieldIdentifier {
1457 name: None,
1458 ..field_ident_3
1459 }
1460 );
Allen George8b96bfb2016-11-02 08:01:08 -04001461 assert_success!(i_prot.read_field_end());
1462
1463 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001464 assert_eq!(
1465 read_ident_4,
1466 TFieldIdentifier {
1467 name: None,
1468 field_type: TType::Stop,
1469 id: None,
1470 }
1471 );
Allen George8b96bfb2016-11-02 08:01:08 -04001472
1473 assert_success!(i_prot.read_struct_end());
1474 }
1475
1476 #[test]
1477 fn must_write_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001478 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001479
1480 // no bytes should be written however
1481 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1482
1483 // write three fields with field ids that cannot be encoded as deltas
1484
1485 // since this is the first field (and it's zero) it gets the full varint write
1486 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
1487 assert_success!(o_prot.write_field_end());
1488
1489 // since this delta is > 15 it is encoded as a zig-zag varint
1490 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
1491 assert_success!(o_prot.write_field_end());
1492
1493 // since this delta is > 15 it is encoded as a zig-zag varint
1494 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
1495 assert_success!(o_prot.write_field_end());
1496
1497 // now, finish the struct off
1498 assert_success!(o_prot.write_field_stop());
1499 assert_success!(o_prot.write_struct_end());
1500
Allen George7ddbcc02020-11-08 09:51:19 -05001501 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001502 let expected: [u8; 8] = [
1503 0x05, /* field type */
1504 0x00, /* first field id */
1505 0x06, /* field type */
1506 0x20, /* zig-zag varint field id */
1507 0x0A, /* field type */
1508 0xC6,
1509 0x01, /* zig-zag varint field id */
1510 0x00 /* field stop */,
1511 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001512
Allen George0e22c362017-01-30 07:15:00 -05001513 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001514 }
1515
1516 #[test]
1517 fn must_round_trip_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001518 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001519
1520 // no bytes should be written however
1521 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1522
1523 // write three fields with field ids that cannot be encoded as deltas
1524
1525 // since this is the first field (and it's zero) it gets the full varint write
1526 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
1527 assert_success!(o_prot.write_field_begin(&field_ident_1));
1528 assert_success!(o_prot.write_field_end());
1529
1530 // since this delta is > 15 it is encoded as a zig-zag varint
1531 let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
1532 assert_success!(o_prot.write_field_begin(&field_ident_2));
1533 assert_success!(o_prot.write_field_end());
1534
1535 // since this delta is > 15 it is encoded as a zig-zag varint
1536 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
1537 assert_success!(o_prot.write_field_begin(&field_ident_3));
1538 assert_success!(o_prot.write_field_end());
1539
1540 // now, finish the struct off
1541 assert_success!(o_prot.write_field_stop());
1542 assert_success!(o_prot.write_struct_end());
1543
Allen George0e22c362017-01-30 07:15:00 -05001544 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001545
1546 // read the struct back
1547 assert_success!(i_prot.read_struct_begin());
1548
1549 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001550 assert_eq!(
1551 read_ident_1,
1552 TFieldIdentifier {
1553 name: None,
1554 ..field_ident_1
1555 }
1556 );
Allen George8b96bfb2016-11-02 08:01:08 -04001557 assert_success!(i_prot.read_field_end());
1558
1559 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001560 assert_eq!(
1561 read_ident_2,
1562 TFieldIdentifier {
1563 name: None,
1564 ..field_ident_2
1565 }
1566 );
Allen George8b96bfb2016-11-02 08:01:08 -04001567 assert_success!(i_prot.read_field_end());
1568
1569 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001570 assert_eq!(
1571 read_ident_3,
1572 TFieldIdentifier {
1573 name: None,
1574 ..field_ident_3
1575 }
1576 );
Allen George8b96bfb2016-11-02 08:01:08 -04001577 assert_success!(i_prot.read_field_end());
1578
1579 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001580 assert_eq!(
1581 read_ident_4,
1582 TFieldIdentifier {
1583 name: None,
1584 field_type: TType::Stop,
1585 id: None,
1586 }
1587 );
Allen George8b96bfb2016-11-02 08:01:08 -04001588
1589 assert_success!(i_prot.read_struct_end());
1590 }
1591
1592 #[test]
1593 fn must_write_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001594 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001595
1596 // no bytes should be written however
1597 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1598
1599 // write three fields with field ids that cannot be encoded as deltas
1600
1601 // since the delta is > 0 and < 15 it gets a delta write
1602 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1603 assert_success!(o_prot.write_field_end());
1604
1605 // since this delta > 0 and < 15 it gets a delta write
1606 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1607 assert_success!(o_prot.write_field_end());
1608
1609 // since this delta is > 15 it is encoded as a zig-zag varint
1610 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
1611 assert_success!(o_prot.write_field_end());
1612
1613 // since this delta is > 15 it is encoded as a zig-zag varint
1614 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
1615 assert_success!(o_prot.write_field_end());
1616
1617 // since this is only 3 up from the previous it is recorded as a delta
1618 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
1619 assert_success!(o_prot.write_field_end());
1620
1621 // now, finish the struct off
1622 assert_success!(o_prot.write_field_stop());
1623 assert_success!(o_prot.write_struct_end());
1624
Allen George7ddbcc02020-11-08 09:51:19 -05001625 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001626 let expected: [u8; 10] = [
1627 0x16, /* field delta (1) | field type */
1628 0x85, /* field delta (8) | field type */
1629 0x0A, /* field type */
1630 0xD0,
1631 0x0F, /* zig-zag varint field id */
1632 0x0A, /* field type */
1633 0xA2,
1634 0x1F, /* zig-zag varint field id */
1635 0x3A, /* field delta (3) | field type */
1636 0x00 /* field stop */,
1637 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001638
Allen George0e22c362017-01-30 07:15:00 -05001639 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001640 }
1641
Allen George7ddbcc02020-11-08 09:51:19 -05001642 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001643 #[test]
1644 fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001645 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001646
1647 // no bytes should be written however
1648 let struct_ident = TStructIdentifier::new("foo");
1649 assert_success!(o_prot.write_struct_begin(&struct_ident));
1650
1651 // write three fields with field ids that cannot be encoded as deltas
1652
1653 // since the delta is > 0 and < 15 it gets a delta write
1654 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1655 assert_success!(o_prot.write_field_begin(&field_ident_1));
1656 assert_success!(o_prot.write_field_end());
1657
1658 // since this delta > 0 and < 15 it gets a delta write
1659 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1660 assert_success!(o_prot.write_field_begin(&field_ident_2));
1661 assert_success!(o_prot.write_field_end());
1662
1663 // since this delta is > 15 it is encoded as a zig-zag varint
1664 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
1665 assert_success!(o_prot.write_field_begin(&field_ident_3));
1666 assert_success!(o_prot.write_field_end());
1667
1668 // since this delta is > 15 it is encoded as a zig-zag varint
1669 let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
1670 assert_success!(o_prot.write_field_begin(&field_ident_4));
1671 assert_success!(o_prot.write_field_end());
1672
1673 // since this is only 3 up from the previous it is recorded as a delta
1674 let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
1675 assert_success!(o_prot.write_field_begin(&field_ident_5));
1676 assert_success!(o_prot.write_field_end());
1677
1678 // now, finish the struct off
1679 assert_success!(o_prot.write_field_stop());
1680 assert_success!(o_prot.write_struct_end());
1681
Allen George0e22c362017-01-30 07:15:00 -05001682 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001683
1684 // read the struct back
1685 assert_success!(i_prot.read_struct_begin());
1686
1687 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001688 assert_eq!(
1689 read_ident_1,
1690 TFieldIdentifier {
1691 name: None,
1692 ..field_ident_1
1693 }
1694 );
Allen George8b96bfb2016-11-02 08:01:08 -04001695 assert_success!(i_prot.read_field_end());
1696
1697 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001698 assert_eq!(
1699 read_ident_2,
1700 TFieldIdentifier {
1701 name: None,
1702 ..field_ident_2
1703 }
1704 );
Allen George8b96bfb2016-11-02 08:01:08 -04001705 assert_success!(i_prot.read_field_end());
1706
1707 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001708 assert_eq!(
1709 read_ident_3,
1710 TFieldIdentifier {
1711 name: None,
1712 ..field_ident_3
1713 }
1714 );
Allen George8b96bfb2016-11-02 08:01:08 -04001715 assert_success!(i_prot.read_field_end());
1716
1717 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001718 assert_eq!(
1719 read_ident_4,
1720 TFieldIdentifier {
1721 name: None,
1722 ..field_ident_4
1723 }
1724 );
Allen George8b96bfb2016-11-02 08:01:08 -04001725 assert_success!(i_prot.read_field_end());
1726
1727 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001728 assert_eq!(
1729 read_ident_5,
1730 TFieldIdentifier {
1731 name: None,
1732 ..field_ident_5
1733 }
1734 );
Allen George8b96bfb2016-11-02 08:01:08 -04001735 assert_success!(i_prot.read_field_end());
1736
1737 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001738 assert_eq!(
1739 read_ident_6,
1740 TFieldIdentifier {
1741 name: None,
1742 field_type: TType::Stop,
1743 id: None,
1744 }
1745 );
Allen George8b96bfb2016-11-02 08:01:08 -04001746
1747 assert_success!(i_prot.read_struct_end());
1748 }
1749
1750 #[test]
1751 fn must_write_nested_structs_0() {
1752 // last field of the containing struct is a delta
1753 // first field of the the contained struct is a delta
1754
Allen George0e22c362017-01-30 07:15:00 -05001755 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001756
1757 // start containing struct
1758 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1759
1760 // containing struct
1761 // since the delta is > 0 and < 15 it gets a delta write
1762 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1763 assert_success!(o_prot.write_field_end());
1764
1765 // containing struct
1766 // since this delta > 0 and < 15 it gets a delta write
1767 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1768 assert_success!(o_prot.write_field_end());
1769
1770 // start contained struct
1771 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1772
1773 // contained struct
1774 // since the delta is > 0 and < 15 it gets a delta write
1775 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
1776 assert_success!(o_prot.write_field_end());
1777
1778 // contained struct
1779 // since this delta > 15 it gets a full write
1780 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1781 assert_success!(o_prot.write_field_end());
1782
1783 // end contained struct
1784 assert_success!(o_prot.write_field_stop());
1785 assert_success!(o_prot.write_struct_end());
1786
1787 // end containing struct
1788 assert_success!(o_prot.write_field_stop());
1789 assert_success!(o_prot.write_struct_end());
1790
Allen George7ddbcc02020-11-08 09:51:19 -05001791 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001792 let expected: [u8; 7] = [
1793 0x16, /* field delta (1) | field type */
1794 0x85, /* field delta (8) | field type */
1795 0x73, /* field delta (7) | field type */
1796 0x07, /* field type */
1797 0x30, /* zig-zag varint field id */
1798 0x00, /* field stop - contained */
1799 0x00 /* field stop - containing */,
1800 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001801
Allen George0e22c362017-01-30 07:15:00 -05001802 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001803 }
1804
Allen George7ddbcc02020-11-08 09:51:19 -05001805 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001806 #[test]
1807 fn must_round_trip_nested_structs_0() {
1808 // last field of the containing struct is a delta
1809 // first field of the the contained struct is a delta
1810
Allen George0e22c362017-01-30 07:15:00 -05001811 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001812
1813 // start containing struct
1814 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1815
1816 // containing struct
1817 // since the delta is > 0 and < 15 it gets a delta write
1818 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1819 assert_success!(o_prot.write_field_begin(&field_ident_1));
1820 assert_success!(o_prot.write_field_end());
1821
1822 // containing struct
1823 // since this delta > 0 and < 15 it gets a delta write
1824 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1825 assert_success!(o_prot.write_field_begin(&field_ident_2));
1826 assert_success!(o_prot.write_field_end());
1827
1828 // start contained struct
1829 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1830
1831 // contained struct
1832 // since the delta is > 0 and < 15 it gets a delta write
1833 let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
1834 assert_success!(o_prot.write_field_begin(&field_ident_3));
1835 assert_success!(o_prot.write_field_end());
1836
1837 // contained struct
1838 // since this delta > 15 it gets a full write
1839 let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
1840 assert_success!(o_prot.write_field_begin(&field_ident_4));
1841 assert_success!(o_prot.write_field_end());
1842
1843 // end contained struct
1844 assert_success!(o_prot.write_field_stop());
1845 assert_success!(o_prot.write_struct_end());
1846
1847 // end containing struct
1848 assert_success!(o_prot.write_field_stop());
1849 assert_success!(o_prot.write_struct_end());
1850
Allen George0e22c362017-01-30 07:15:00 -05001851 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001852
1853 // read containing struct back
1854 assert_success!(i_prot.read_struct_begin());
1855
1856 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001857 assert_eq!(
1858 read_ident_1,
1859 TFieldIdentifier {
1860 name: None,
1861 ..field_ident_1
1862 }
1863 );
Allen George8b96bfb2016-11-02 08:01:08 -04001864 assert_success!(i_prot.read_field_end());
1865
1866 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001867 assert_eq!(
1868 read_ident_2,
1869 TFieldIdentifier {
1870 name: None,
1871 ..field_ident_2
1872 }
1873 );
Allen George8b96bfb2016-11-02 08:01:08 -04001874 assert_success!(i_prot.read_field_end());
1875
1876 // read contained struct back
1877 assert_success!(i_prot.read_struct_begin());
1878
1879 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001880 assert_eq!(
1881 read_ident_3,
1882 TFieldIdentifier {
1883 name: None,
1884 ..field_ident_3
1885 }
1886 );
Allen George8b96bfb2016-11-02 08:01:08 -04001887 assert_success!(i_prot.read_field_end());
1888
1889 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001890 assert_eq!(
1891 read_ident_4,
1892 TFieldIdentifier {
1893 name: None,
1894 ..field_ident_4
1895 }
1896 );
Allen George8b96bfb2016-11-02 08:01:08 -04001897 assert_success!(i_prot.read_field_end());
1898
1899 // end contained struct
1900 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001901 assert_eq!(
1902 read_ident_6,
1903 TFieldIdentifier {
1904 name: None,
1905 field_type: TType::Stop,
1906 id: None,
1907 }
1908 );
Allen George8b96bfb2016-11-02 08:01:08 -04001909 assert_success!(i_prot.read_struct_end());
1910
1911 // end containing struct
1912 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001913 assert_eq!(
1914 read_ident_7,
1915 TFieldIdentifier {
1916 name: None,
1917 field_type: TType::Stop,
1918 id: None,
1919 }
1920 );
Allen George8b96bfb2016-11-02 08:01:08 -04001921 assert_success!(i_prot.read_struct_end());
1922 }
1923
1924 #[test]
1925 fn must_write_nested_structs_1() {
1926 // last field of the containing struct is a delta
1927 // first field of the the contained struct is a full write
1928
Allen George0e22c362017-01-30 07:15:00 -05001929 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001930
1931 // start containing struct
1932 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1933
1934 // containing struct
1935 // since the delta is > 0 and < 15 it gets a delta write
1936 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1937 assert_success!(o_prot.write_field_end());
1938
1939 // containing struct
1940 // since this delta > 0 and < 15 it gets a delta write
1941 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1942 assert_success!(o_prot.write_field_end());
1943
1944 // start contained struct
1945 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1946
1947 // contained struct
1948 // since this delta > 15 it gets a full write
1949 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1950 assert_success!(o_prot.write_field_end());
1951
1952 // contained struct
1953 // since the delta is > 0 and < 15 it gets a delta write
1954 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1955 assert_success!(o_prot.write_field_end());
1956
1957 // end contained struct
1958 assert_success!(o_prot.write_field_stop());
1959 assert_success!(o_prot.write_struct_end());
1960
1961 // end containing struct
1962 assert_success!(o_prot.write_field_stop());
1963 assert_success!(o_prot.write_struct_end());
1964
Allen George7ddbcc02020-11-08 09:51:19 -05001965 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001966 let expected: [u8; 7] = [
1967 0x16, /* field delta (1) | field type */
1968 0x85, /* field delta (8) | field type */
1969 0x07, /* field type */
1970 0x30, /* zig-zag varint field id */
1971 0x33, /* field delta (3) | field type */
1972 0x00, /* field stop - contained */
1973 0x00 /* field stop - containing */,
1974 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001975
Allen George0e22c362017-01-30 07:15:00 -05001976 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001977 }
1978
Allen George7ddbcc02020-11-08 09:51:19 -05001979 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001980 #[test]
1981 fn must_round_trip_nested_structs_1() {
1982 // last field of the containing struct is a delta
1983 // first field of the the contained struct is a full write
1984
Allen George0e22c362017-01-30 07:15:00 -05001985 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001986
1987 // start containing struct
1988 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1989
1990 // containing struct
1991 // since the delta is > 0 and < 15 it gets a delta write
1992 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1993 assert_success!(o_prot.write_field_begin(&field_ident_1));
1994 assert_success!(o_prot.write_field_end());
1995
1996 // containing struct
1997 // since this delta > 0 and < 15 it gets a delta write
1998 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1999 assert_success!(o_prot.write_field_begin(&field_ident_2));
2000 assert_success!(o_prot.write_field_end());
2001
2002 // start contained struct
2003 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2004
2005 // contained struct
2006 // since this delta > 15 it gets a full write
2007 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
2008 assert_success!(o_prot.write_field_begin(&field_ident_3));
2009 assert_success!(o_prot.write_field_end());
2010
2011 // contained struct
2012 // since the delta is > 0 and < 15 it gets a delta write
2013 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2014 assert_success!(o_prot.write_field_begin(&field_ident_4));
2015 assert_success!(o_prot.write_field_end());
2016
2017 // end contained struct
2018 assert_success!(o_prot.write_field_stop());
2019 assert_success!(o_prot.write_struct_end());
2020
2021 // end containing struct
2022 assert_success!(o_prot.write_field_stop());
2023 assert_success!(o_prot.write_struct_end());
2024
Allen George0e22c362017-01-30 07:15:00 -05002025 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002026
2027 // read containing struct back
2028 assert_success!(i_prot.read_struct_begin());
2029
2030 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002031 assert_eq!(
2032 read_ident_1,
2033 TFieldIdentifier {
2034 name: None,
2035 ..field_ident_1
2036 }
2037 );
Allen George8b96bfb2016-11-02 08:01:08 -04002038 assert_success!(i_prot.read_field_end());
2039
2040 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002041 assert_eq!(
2042 read_ident_2,
2043 TFieldIdentifier {
2044 name: None,
2045 ..field_ident_2
2046 }
2047 );
Allen George8b96bfb2016-11-02 08:01:08 -04002048 assert_success!(i_prot.read_field_end());
2049
2050 // read contained struct back
2051 assert_success!(i_prot.read_struct_begin());
2052
2053 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002054 assert_eq!(
2055 read_ident_3,
2056 TFieldIdentifier {
2057 name: None,
2058 ..field_ident_3
2059 }
2060 );
Allen George8b96bfb2016-11-02 08:01:08 -04002061 assert_success!(i_prot.read_field_end());
2062
2063 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002064 assert_eq!(
2065 read_ident_4,
2066 TFieldIdentifier {
2067 name: None,
2068 ..field_ident_4
2069 }
2070 );
Allen George8b96bfb2016-11-02 08:01:08 -04002071 assert_success!(i_prot.read_field_end());
2072
2073 // end contained struct
2074 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002075 assert_eq!(
2076 read_ident_6,
2077 TFieldIdentifier {
2078 name: None,
2079 field_type: TType::Stop,
2080 id: None,
2081 }
2082 );
Allen George8b96bfb2016-11-02 08:01:08 -04002083 assert_success!(i_prot.read_struct_end());
2084
2085 // end containing struct
2086 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002087 assert_eq!(
2088 read_ident_7,
2089 TFieldIdentifier {
2090 name: None,
2091 field_type: TType::Stop,
2092 id: None,
2093 }
2094 );
Allen George8b96bfb2016-11-02 08:01:08 -04002095 assert_success!(i_prot.read_struct_end());
2096 }
2097
2098 #[test]
2099 fn must_write_nested_structs_2() {
2100 // last field of the containing struct is a full write
2101 // first field of the the contained struct is a delta write
2102
Allen George0e22c362017-01-30 07:15:00 -05002103 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002104
2105 // start containing struct
2106 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2107
2108 // containing struct
2109 // since the delta is > 0 and < 15 it gets a delta write
2110 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2111 assert_success!(o_prot.write_field_end());
2112
2113 // containing struct
2114 // since this delta > 15 it gets a full write
2115 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2116 assert_success!(o_prot.write_field_end());
2117
2118 // start contained struct
2119 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2120
2121 // contained struct
2122 // since this delta > 0 and < 15 it gets a delta write
2123 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
2124 assert_success!(o_prot.write_field_end());
2125
2126 // contained struct
2127 // since the delta is > 0 and < 15 it gets a delta write
2128 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
2129 assert_success!(o_prot.write_field_end());
2130
2131 // end contained struct
2132 assert_success!(o_prot.write_field_stop());
2133 assert_success!(o_prot.write_struct_end());
2134
2135 // end containing struct
2136 assert_success!(o_prot.write_field_stop());
2137 assert_success!(o_prot.write_struct_end());
2138
Allen George7ddbcc02020-11-08 09:51:19 -05002139 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002140 let expected: [u8; 7] = [
2141 0x16, /* field delta (1) | field type */
2142 0x08, /* field type */
2143 0x2A, /* zig-zag varint field id */
2144 0x77, /* field delta(7) | field type */
2145 0x33, /* field delta (3) | field type */
2146 0x00, /* field stop - contained */
2147 0x00 /* field stop - containing */,
2148 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002149
Allen George0e22c362017-01-30 07:15:00 -05002150 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002151 }
2152
Allen George7ddbcc02020-11-08 09:51:19 -05002153 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002154 #[test]
2155 fn must_round_trip_nested_structs_2() {
Allen George0e22c362017-01-30 07:15:00 -05002156 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002157
2158 // start containing struct
2159 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2160
2161 // containing struct
2162 // since the delta is > 0 and < 15 it gets a delta write
2163 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2164 assert_success!(o_prot.write_field_begin(&field_ident_1));
2165 assert_success!(o_prot.write_field_end());
2166
2167 // containing struct
2168 // since this delta > 15 it gets a full write
2169 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2170 assert_success!(o_prot.write_field_begin(&field_ident_2));
2171 assert_success!(o_prot.write_field_end());
2172
2173 // start contained struct
2174 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2175
2176 // contained struct
2177 // since this delta > 0 and < 15 it gets a delta write
2178 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
2179 assert_success!(o_prot.write_field_begin(&field_ident_3));
2180 assert_success!(o_prot.write_field_end());
2181
2182 // contained struct
2183 // since the delta is > 0 and < 15 it gets a delta write
2184 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
2185 assert_success!(o_prot.write_field_begin(&field_ident_4));
2186 assert_success!(o_prot.write_field_end());
2187
2188 // end contained struct
2189 assert_success!(o_prot.write_field_stop());
2190 assert_success!(o_prot.write_struct_end());
2191
2192 // end containing struct
2193 assert_success!(o_prot.write_field_stop());
2194 assert_success!(o_prot.write_struct_end());
2195
Allen George0e22c362017-01-30 07:15:00 -05002196 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002197
2198 // read containing struct back
2199 assert_success!(i_prot.read_struct_begin());
2200
2201 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002202 assert_eq!(
2203 read_ident_1,
2204 TFieldIdentifier {
2205 name: None,
2206 ..field_ident_1
2207 }
2208 );
Allen George8b96bfb2016-11-02 08:01:08 -04002209 assert_success!(i_prot.read_field_end());
2210
2211 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002212 assert_eq!(
2213 read_ident_2,
2214 TFieldIdentifier {
2215 name: None,
2216 ..field_ident_2
2217 }
2218 );
Allen George8b96bfb2016-11-02 08:01:08 -04002219 assert_success!(i_prot.read_field_end());
2220
2221 // read contained struct back
2222 assert_success!(i_prot.read_struct_begin());
2223
2224 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002225 assert_eq!(
2226 read_ident_3,
2227 TFieldIdentifier {
2228 name: None,
2229 ..field_ident_3
2230 }
2231 );
Allen George8b96bfb2016-11-02 08:01:08 -04002232 assert_success!(i_prot.read_field_end());
2233
2234 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002235 assert_eq!(
2236 read_ident_4,
2237 TFieldIdentifier {
2238 name: None,
2239 ..field_ident_4
2240 }
2241 );
Allen George8b96bfb2016-11-02 08:01:08 -04002242 assert_success!(i_prot.read_field_end());
2243
2244 // end contained struct
2245 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002246 assert_eq!(
2247 read_ident_6,
2248 TFieldIdentifier {
2249 name: None,
2250 field_type: TType::Stop,
2251 id: None,
2252 }
2253 );
Allen George8b96bfb2016-11-02 08:01:08 -04002254 assert_success!(i_prot.read_struct_end());
2255
2256 // end containing struct
2257 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002258 assert_eq!(
2259 read_ident_7,
2260 TFieldIdentifier {
2261 name: None,
2262 field_type: TType::Stop,
2263 id: None,
2264 }
2265 );
Allen George8b96bfb2016-11-02 08:01:08 -04002266 assert_success!(i_prot.read_struct_end());
2267 }
2268
2269 #[test]
2270 fn must_write_nested_structs_3() {
2271 // last field of the containing struct is a full write
2272 // first field of the the contained struct is a full write
2273
Allen George0e22c362017-01-30 07:15:00 -05002274 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002275
2276 // start containing struct
2277 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2278
2279 // containing struct
2280 // since the delta is > 0 and < 15 it gets a delta write
2281 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2282 assert_success!(o_prot.write_field_end());
2283
2284 // containing struct
2285 // since this delta > 15 it gets a full write
2286 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2287 assert_success!(o_prot.write_field_end());
2288
2289 // start contained struct
2290 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2291
2292 // contained struct
2293 // since this delta > 15 it gets a full write
2294 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
2295 assert_success!(o_prot.write_field_end());
2296
2297 // contained struct
2298 // since the delta is > 0 and < 15 it gets a delta write
2299 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
2300 assert_success!(o_prot.write_field_end());
2301
2302 // end contained struct
2303 assert_success!(o_prot.write_field_stop());
2304 assert_success!(o_prot.write_struct_end());
2305
2306 // end containing struct
2307 assert_success!(o_prot.write_field_stop());
2308 assert_success!(o_prot.write_struct_end());
2309
Allen George7ddbcc02020-11-08 09:51:19 -05002310 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002311 let expected: [u8; 8] = [
2312 0x16, /* field delta (1) | field type */
2313 0x08, /* field type */
2314 0x2A, /* zig-zag varint field id */
2315 0x07, /* field type */
2316 0x2A, /* zig-zag varint field id */
2317 0x63, /* field delta (6) | field type */
2318 0x00, /* field stop - contained */
2319 0x00 /* field stop - containing */,
2320 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002321
Allen George0e22c362017-01-30 07:15:00 -05002322 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002323 }
2324
Allen George7ddbcc02020-11-08 09:51:19 -05002325 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002326 #[test]
2327 fn must_round_trip_nested_structs_3() {
2328 // last field of the containing struct is a full write
2329 // first field of the the contained struct is a full write
2330
Allen George0e22c362017-01-30 07:15:00 -05002331 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002332
2333 // start containing struct
2334 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2335
2336 // containing struct
2337 // since the delta is > 0 and < 15 it gets a delta write
2338 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2339 assert_success!(o_prot.write_field_begin(&field_ident_1));
2340 assert_success!(o_prot.write_field_end());
2341
2342 // containing struct
2343 // since this delta > 15 it gets a full write
2344 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2345 assert_success!(o_prot.write_field_begin(&field_ident_2));
2346 assert_success!(o_prot.write_field_end());
2347
2348 // start contained struct
2349 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2350
2351 // contained struct
2352 // since this delta > 15 it gets a full write
2353 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
2354 assert_success!(o_prot.write_field_begin(&field_ident_3));
2355 assert_success!(o_prot.write_field_end());
2356
2357 // contained struct
2358 // since the delta is > 0 and < 15 it gets a delta write
2359 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2360 assert_success!(o_prot.write_field_begin(&field_ident_4));
2361 assert_success!(o_prot.write_field_end());
2362
2363 // end contained struct
2364 assert_success!(o_prot.write_field_stop());
2365 assert_success!(o_prot.write_struct_end());
2366
2367 // end containing struct
2368 assert_success!(o_prot.write_field_stop());
2369 assert_success!(o_prot.write_struct_end());
2370
Allen George0e22c362017-01-30 07:15:00 -05002371 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002372
2373 // read containing struct back
2374 assert_success!(i_prot.read_struct_begin());
2375
2376 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002377 assert_eq!(
2378 read_ident_1,
2379 TFieldIdentifier {
2380 name: None,
2381 ..field_ident_1
2382 }
2383 );
Allen George8b96bfb2016-11-02 08:01:08 -04002384 assert_success!(i_prot.read_field_end());
2385
2386 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002387 assert_eq!(
2388 read_ident_2,
2389 TFieldIdentifier {
2390 name: None,
2391 ..field_ident_2
2392 }
2393 );
Allen George8b96bfb2016-11-02 08:01:08 -04002394 assert_success!(i_prot.read_field_end());
2395
2396 // read contained struct back
2397 assert_success!(i_prot.read_struct_begin());
2398
2399 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002400 assert_eq!(
2401 read_ident_3,
2402 TFieldIdentifier {
2403 name: None,
2404 ..field_ident_3
2405 }
2406 );
Allen George8b96bfb2016-11-02 08:01:08 -04002407 assert_success!(i_prot.read_field_end());
2408
2409 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002410 assert_eq!(
2411 read_ident_4,
2412 TFieldIdentifier {
2413 name: None,
2414 ..field_ident_4
2415 }
2416 );
Allen George8b96bfb2016-11-02 08:01:08 -04002417 assert_success!(i_prot.read_field_end());
2418
2419 // end contained struct
2420 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002421 assert_eq!(
2422 read_ident_6,
2423 TFieldIdentifier {
2424 name: None,
2425 field_type: TType::Stop,
2426 id: None,
2427 }
2428 );
Allen George8b96bfb2016-11-02 08:01:08 -04002429 assert_success!(i_prot.read_struct_end());
2430
2431 // end containing struct
2432 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002433 assert_eq!(
2434 read_ident_7,
2435 TFieldIdentifier {
2436 name: None,
2437 field_type: TType::Stop,
2438 id: None,
2439 }
2440 );
Allen George8b96bfb2016-11-02 08:01:08 -04002441 assert_success!(i_prot.read_struct_end());
2442 }
2443
2444 #[test]
2445 fn must_write_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002446 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002447
2448 // no bytes should be written however
2449 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2450
2451 // write three fields with field ids that cannot be encoded as deltas
2452
2453 // since the delta is > 0 and < 16 it gets a delta write
2454 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2455 assert_success!(o_prot.write_bool(true));
2456 assert_success!(o_prot.write_field_end());
2457
2458 // since this delta > 0 and < 15 it gets a delta write
2459 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
2460 assert_success!(o_prot.write_bool(false));
2461 assert_success!(o_prot.write_field_end());
2462
2463 // since this delta > 15 it gets a full write
2464 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
2465 assert_success!(o_prot.write_bool(true));
2466 assert_success!(o_prot.write_field_end());
2467
2468 // since this delta > 15 it gets a full write
2469 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
2470 assert_success!(o_prot.write_bool(false));
2471 assert_success!(o_prot.write_field_end());
2472
2473 // now, finish the struct off
2474 assert_success!(o_prot.write_field_stop());
2475 assert_success!(o_prot.write_struct_end());
2476
Allen George7ddbcc02020-11-08 09:51:19 -05002477 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002478 let expected: [u8; 7] = [
2479 0x11, /* field delta (1) | true */
2480 0x82, /* field delta (8) | false */
2481 0x01, /* true */
2482 0x34, /* field id */
2483 0x02, /* false */
2484 0x5A, /* field id */
2485 0x00 /* stop field */,
2486 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002487
Allen George0e22c362017-01-30 07:15:00 -05002488 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002489 }
2490
Allen George7ddbcc02020-11-08 09:51:19 -05002491 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002492 #[test]
2493 fn must_round_trip_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002494 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002495
2496 // no bytes should be written however
2497 let struct_ident = TStructIdentifier::new("foo");
2498 assert_success!(o_prot.write_struct_begin(&struct_ident));
2499
2500 // write two fields
2501
2502 // since the delta is > 0 and < 16 it gets a delta write
2503 let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
2504 assert_success!(o_prot.write_field_begin(&field_ident_1));
2505 assert_success!(o_prot.write_bool(true));
2506 assert_success!(o_prot.write_field_end());
2507
2508 // since this delta > 0 and < 15 it gets a delta write
2509 let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
2510 assert_success!(o_prot.write_field_begin(&field_ident_2));
2511 assert_success!(o_prot.write_bool(false));
2512 assert_success!(o_prot.write_field_end());
2513
2514 // since this delta > 15 it gets a full write
2515 let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
2516 assert_success!(o_prot.write_field_begin(&field_ident_3));
2517 assert_success!(o_prot.write_bool(true));
2518 assert_success!(o_prot.write_field_end());
2519
2520 // since this delta > 15 it gets a full write
2521 let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
2522 assert_success!(o_prot.write_field_begin(&field_ident_4));
2523 assert_success!(o_prot.write_bool(false));
2524 assert_success!(o_prot.write_field_end());
2525
2526 // now, finish the struct off
2527 assert_success!(o_prot.write_field_stop());
2528 assert_success!(o_prot.write_struct_end());
2529
Allen George0e22c362017-01-30 07:15:00 -05002530 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002531
2532 // read the struct back
2533 assert_success!(i_prot.read_struct_begin());
2534
2535 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002536 assert_eq!(
2537 read_ident_1,
2538 TFieldIdentifier {
2539 name: None,
2540 ..field_ident_1
2541 }
2542 );
Allen George8b96bfb2016-11-02 08:01:08 -04002543 let read_value_1 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002544 assert!(read_value_1);
Allen George8b96bfb2016-11-02 08:01:08 -04002545 assert_success!(i_prot.read_field_end());
2546
2547 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002548 assert_eq!(
2549 read_ident_2,
2550 TFieldIdentifier {
2551 name: None,
2552 ..field_ident_2
2553 }
2554 );
Allen George8b96bfb2016-11-02 08:01:08 -04002555 let read_value_2 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002556 assert!(!read_value_2);
Allen George8b96bfb2016-11-02 08:01:08 -04002557 assert_success!(i_prot.read_field_end());
2558
2559 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002560 assert_eq!(
2561 read_ident_3,
2562 TFieldIdentifier {
2563 name: None,
2564 ..field_ident_3
2565 }
2566 );
Allen George8b96bfb2016-11-02 08:01:08 -04002567 let read_value_3 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002568 assert!(read_value_3);
Allen George8b96bfb2016-11-02 08:01:08 -04002569 assert_success!(i_prot.read_field_end());
2570
2571 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002572 assert_eq!(
2573 read_ident_4,
2574 TFieldIdentifier {
2575 name: None,
2576 ..field_ident_4
2577 }
2578 );
Allen George8b96bfb2016-11-02 08:01:08 -04002579 let read_value_4 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002580 assert!(!read_value_4);
Allen George8b96bfb2016-11-02 08:01:08 -04002581 assert_success!(i_prot.read_field_end());
2582
2583 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002584 assert_eq!(
2585 read_ident_5,
2586 TFieldIdentifier {
2587 name: None,
2588 field_type: TType::Stop,
2589 id: None,
2590 }
2591 );
Allen George8b96bfb2016-11-02 08:01:08 -04002592
2593 assert_success!(i_prot.read_struct_end());
2594 }
2595
2596 #[test]
2597 #[should_panic]
2598 fn must_fail_if_write_field_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002599 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002600 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2601 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2602 o_prot.write_field_end().unwrap();
2603 }
2604
2605 #[test]
2606 #[should_panic]
2607 fn must_fail_if_write_stop_field_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002608 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002609 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2610 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2611 o_prot.write_field_stop().unwrap();
2612 }
2613
2614 #[test]
2615 #[should_panic]
2616 fn must_fail_if_write_struct_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002617 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002618 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2619 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2620 o_prot.write_struct_end().unwrap();
2621 }
2622
2623 #[test]
2624 #[should_panic]
2625 fn must_fail_if_write_struct_end_without_any_fields() {
Allen George0e22c362017-01-30 07:15:00 -05002626 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002627 o_prot.write_struct_end().unwrap();
2628 }
2629
2630 #[test]
2631 fn must_write_field_end() {
2632 assert_no_write(|o| o.write_field_end());
2633 }
2634
2635 #[test]
2636 fn must_write_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002637 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002638
2639 assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
2640
2641 let expected: [u8; 1] = [0x46 /* size | elem_type */];
2642
Allen George0e22c362017-01-30 07:15:00 -05002643 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002644 }
2645
2646 #[test]
2647 fn must_round_trip_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002648 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002649
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002650 let ident = TListIdentifier::new(TType::I32, 3);
Allen George8b96bfb2016-11-02 08:01:08 -04002651 assert_success!(o_prot.write_list_begin(&ident));
2652
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002653 assert_success!(o_prot.write_i32(100));
2654 assert_success!(o_prot.write_i32(200));
2655 assert_success!(o_prot.write_i32(300));
2656
2657 assert_success!(o_prot.write_list_end());
2658
Allen George0e22c362017-01-30 07:15:00 -05002659 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002660
2661 let res = assert_success!(i_prot.read_list_begin());
2662 assert_eq!(&res, &ident);
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002663
2664 assert_eq!(i_prot.read_i32().unwrap(), 100);
2665 assert_eq!(i_prot.read_i32().unwrap(), 200);
2666 assert_eq!(i_prot.read_i32().unwrap(), 300);
2667
2668 assert_success!(i_prot.read_list_end());
Allen George8b96bfb2016-11-02 08:01:08 -04002669 }
2670
2671 #[test]
2672 fn must_write_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002673 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002674
2675 let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
2676 assert!(res.is_ok());
2677
Allen George0e22c362017-01-30 07:15:00 -05002678 let expected: [u8; 3] = [
2679 0xF9, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002680 0x8F, 0x4E, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002681 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002682
Allen George0e22c362017-01-30 07:15:00 -05002683 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002684 }
2685
2686 #[test]
2687 fn must_round_trip_large_sized_list_begin() {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002688 let (mut i_prot, mut o_prot) = test_objects_no_limits();
Allen George8b96bfb2016-11-02 08:01:08 -04002689
2690 let ident = TListIdentifier::new(TType::Set, 47381);
Allen George8b96bfb2016-11-02 08:01:08 -04002691 assert_success!(o_prot.write_list_begin(&ident));
2692
Allen George0e22c362017-01-30 07:15:00 -05002693 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002694
2695 let res = assert_success!(i_prot.read_list_begin());
2696 assert_eq!(&res, &ident);
2697 }
2698
2699 #[test]
2700 fn must_write_list_end() {
2701 assert_no_write(|o| o.write_list_end());
2702 }
2703
2704 #[test]
2705 fn must_write_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002706 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002707
2708 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
2709
2710 let expected: [u8; 1] = [0x2C /* size | elem_type */];
2711
Allen George0e22c362017-01-30 07:15:00 -05002712 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002713 }
2714
2715 #[test]
2716 fn must_round_trip_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002717 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002718
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002719 let ident = TSetIdentifier::new(TType::I16, 3);
Allen George8b96bfb2016-11-02 08:01:08 -04002720 assert_success!(o_prot.write_set_begin(&ident));
2721
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002722 assert_success!(o_prot.write_i16(111));
2723 assert_success!(o_prot.write_i16(222));
2724 assert_success!(o_prot.write_i16(333));
2725
2726 assert_success!(o_prot.write_set_end());
2727
Allen George0e22c362017-01-30 07:15:00 -05002728 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002729
2730 let res = assert_success!(i_prot.read_set_begin());
2731 assert_eq!(&res, &ident);
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002732
2733 assert_eq!(i_prot.read_i16().unwrap(), 111);
2734 assert_eq!(i_prot.read_i16().unwrap(), 222);
2735 assert_eq!(i_prot.read_i16().unwrap(), 333);
2736
2737 assert_success!(i_prot.read_set_end());
Allen George8b96bfb2016-11-02 08:01:08 -04002738 }
2739
2740 #[test]
2741 fn must_write_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002742 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002743
2744 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
2745
Allen George0e22c362017-01-30 07:15:00 -05002746 let expected: [u8; 4] = [
2747 0xF7, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002748 0xD3, 0xBA, 0x01, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002749 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002750
Allen George0e22c362017-01-30 07:15:00 -05002751 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002752 }
2753
2754 #[test]
2755 fn must_round_trip_large_sized_set_begin() {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002756 let (mut i_prot, mut o_prot) = test_objects_no_limits();
Allen George8b96bfb2016-11-02 08:01:08 -04002757
Allen George7ddbcc02020-11-08 09:51:19 -05002758 let ident = TSetIdentifier::new(TType::Map, 3_928_429);
Allen George8b96bfb2016-11-02 08:01:08 -04002759 assert_success!(o_prot.write_set_begin(&ident));
2760
Allen George0e22c362017-01-30 07:15:00 -05002761 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002762
2763 let res = assert_success!(i_prot.read_set_begin());
2764 assert_eq!(&res, &ident);
2765 }
2766
2767 #[test]
2768 fn must_write_set_end() {
2769 assert_no_write(|o| o.write_set_end());
2770 }
2771
2772 #[test]
2773 fn must_write_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002774 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002775
2776 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
2777
2778 let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything
2779
Allen George0e22c362017-01-30 07:15:00 -05002780 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002781 }
2782
2783 #[test]
2784 fn must_read_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002785 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002786
2787 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
2788
Allen George0e22c362017-01-30 07:15:00 -05002789 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002790
2791 let res = assert_success!(i_prot.read_map_begin());
Allen George0e22c362017-01-30 07:15:00 -05002792 assert_eq!(
2793 &res,
2794 &TMapIdentifier {
Allen Georgeef7a1892018-12-16 18:01:37 -05002795 key_type: None,
2796 value_type: None,
2797 size: 0,
2798 }
Allen George0e22c362017-01-30 07:15:00 -05002799 );
Allen George8b96bfb2016-11-02 08:01:08 -04002800 }
2801
2802 #[test]
2803 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002804 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002805
Allen Georgeef7a1892018-12-16 18:01:37 -05002806 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
2807 TType::Double,
2808 TType::String,
2809 238
2810 )));
Allen George8b96bfb2016-11-02 08:01:08 -04002811
Allen George0e22c362017-01-30 07:15:00 -05002812 let expected: [u8; 3] = [
Allen Georgeef7a1892018-12-16 18:01:37 -05002813 0xEE, 0x01, /* size as varint */
2814 0x78, /* key type | val type */
Allen George0e22c362017-01-30 07:15:00 -05002815 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002816
Allen George0e22c362017-01-30 07:15:00 -05002817 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002818 }
2819
2820 #[test]
2821 fn must_round_trip_map_begin() {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002822 let (mut i_prot, mut o_prot) = test_objects_no_limits();
Allen George8b96bfb2016-11-02 08:01:08 -04002823
Allen George7ddbcc02020-11-08 09:51:19 -05002824 let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349);
Allen George8b96bfb2016-11-02 08:01:08 -04002825 assert_success!(o_prot.write_map_begin(&ident));
2826
Allen George0e22c362017-01-30 07:15:00 -05002827 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002828
2829 let res = assert_success!(i_prot.read_map_begin());
2830 assert_eq!(&res, &ident);
2831 }
2832
2833 #[test]
2834 fn must_write_map_end() {
2835 assert_no_write(|o| o.write_map_end());
2836 }
2837
2838 #[test]
2839 fn must_write_map_with_bool_key_and_value() {
Allen George0e22c362017-01-30 07:15:00 -05002840 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002841
2842 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
2843 assert_success!(o_prot.write_bool(true));
2844 assert_success!(o_prot.write_bool(false));
2845 assert_success!(o_prot.write_map_end());
2846
Allen George0e22c362017-01-30 07:15:00 -05002847 let expected: [u8; 4] = [
2848 0x01, /* size as varint */
2849 0x11, /* key type | val type */
2850 0x01, /* key: true */
Allen Georgeef7a1892018-12-16 18:01:37 -05002851 0x02, /* val: false */
Allen George0e22c362017-01-30 07:15:00 -05002852 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002853
Allen George0e22c362017-01-30 07:15:00 -05002854 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002855 }
2856
2857 #[test]
2858 fn must_round_trip_map_with_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002859 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002860
2861 let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
2862 assert_success!(o_prot.write_map_begin(&map_ident));
2863 assert_success!(o_prot.write_bool(true));
2864 assert_success!(o_prot.write_bool(false));
2865 assert_success!(o_prot.write_bool(false));
2866 assert_success!(o_prot.write_bool(true));
2867 assert_success!(o_prot.write_map_end());
2868
Allen George0e22c362017-01-30 07:15:00 -05002869 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002870
2871 // map header
2872 let rcvd_ident = assert_success!(i_prot.read_map_begin());
2873 assert_eq!(&rcvd_ident, &map_ident);
2874 // key 1
2875 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002876 assert!(b);
Allen George8b96bfb2016-11-02 08:01:08 -04002877 // val 1
2878 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002879 assert!(!b);
Allen George8b96bfb2016-11-02 08:01:08 -04002880 // key 2
2881 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002882 assert!(!b);
Allen George8b96bfb2016-11-02 08:01:08 -04002883 // val 2
2884 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002885 assert!(b);
Allen George8b96bfb2016-11-02 08:01:08 -04002886 // map end
2887 assert_success!(i_prot.read_map_end());
2888 }
2889
2890 #[test]
2891 fn must_read_map_end() {
Allen George0e22c362017-01-30 07:15:00 -05002892 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002893 assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
2894 }
2895
Allen Georgeef7a1892018-12-16 18:01:37 -05002896 fn test_objects() -> (
2897 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2898 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2899 ) {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002900 let mem = TBufferChannel::with_capacity(200, 200);
Allen George8b96bfb2016-11-02 08:01:08 -04002901
Allen George0e22c362017-01-30 07:15:00 -05002902 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -04002903
Allen George0e22c362017-01-30 07:15:00 -05002904 let i_prot = TCompactInputProtocol::new(r_mem);
2905 let o_prot = TCompactOutputProtocol::new(w_mem);
Allen George8b96bfb2016-11-02 08:01:08 -04002906
Allen George0e22c362017-01-30 07:15:00 -05002907 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -04002908 }
2909
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002910 fn test_objects_no_limits() -> (
2911 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2912 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2913 ) {
2914 let mem = TBufferChannel::with_capacity(200, 200);
2915
2916 let (r_mem, w_mem) = mem.split().unwrap();
2917
2918 let i_prot = TCompactInputProtocol::with_config(r_mem, TConfiguration::no_limits());
2919 let o_prot = TCompactOutputProtocol::new(w_mem);
2920
2921 (i_prot, o_prot)
2922 }
2923
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002924 #[test]
2925 fn must_read_write_double() {
2926 let (mut i_prot, mut o_prot) = test_objects();
2927
Allen George7ddbcc02020-11-08 09:51:19 -05002928 #[allow(clippy::approx_constant)]
2929 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002930 o_prot.write_double(double).unwrap();
2931 copy_write_buffer_to_read_buffer!(o_prot);
2932
Allen George7ddbcc02020-11-08 09:51:19 -05002933 let read_double = i_prot.read_double().unwrap();
Cameron Martinda54fc82025-01-12 08:55:45 +00002934 assert!((read_double - double).abs() < f64::EPSILON);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002935 }
2936
2937 #[test]
2938 fn must_encode_double_as_other_langs() {
2939 let (_, mut o_prot) = test_objects();
2940 let expected = [24, 45, 68, 84, 251, 33, 9, 64];
2941
Allen George7ddbcc02020-11-08 09:51:19 -05002942 #[allow(clippy::approx_constant)]
2943 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002944 o_prot.write_double(double).unwrap();
2945
2946 assert_eq_written_bytes!(o_prot, expected);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002947 }
2948
Allen George0e22c362017-01-30 07:15:00 -05002949 fn assert_no_write<F>(mut write_fn: F)
2950 where
Allen Georgeb0d14132020-03-29 11:48:55 -04002951 F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> crate::Result<()>,
Allen George0e22c362017-01-30 07:15:00 -05002952 {
2953 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002954 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -05002955 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -04002956 }
Jörn Horstmann717bd792025-02-02 23:10:27 +01002957
2958 #[test]
2959 fn must_read_boolean_list() {
2960 let (mut i_prot, _) = test_objects();
2961
2962 let source_bytes: [u8; 3] = [0x21, 2, 1];
2963
2964 i_prot.transport.set_readable_bytes(&source_bytes);
2965
2966 let (ttype, element_count) = assert_success!(i_prot.read_list_set_begin());
2967
2968 assert_eq!(ttype, TType::Bool);
2969 assert_eq!(element_count, 2);
2970 assert_eq!(i_prot.read_bool().unwrap(), false);
2971 assert_eq!(i_prot.read_bool().unwrap(), true);
2972
2973 assert_success!(i_prot.read_list_end());
2974 }
2975
2976 #[test]
2977 fn must_read_boolean_list_alternative_encoding() {
2978 let (mut i_prot, _) = test_objects();
2979
2980 let source_bytes: [u8; 3] = [0x22, 0, 1];
2981
2982 i_prot.transport.set_readable_bytes(&source_bytes);
2983
2984 let (ttype, element_count) = assert_success!(i_prot.read_list_set_begin());
2985
2986 assert_eq!(ttype, TType::Bool);
2987 assert_eq!(element_count, 2);
2988 assert_eq!(i_prot.read_bool().unwrap(), false);
2989 assert_eq!(i_prot.read_bool().unwrap(), true);
2990
2991 assert_success!(i_prot.read_list_end());
2992 }
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002993
2994 #[test]
2995 fn must_enforce_recursion_depth_limit() {
2996 let channel = TBufferChannel::with_capacity(100, 100);
2997
2998 // Create a configuration with a small recursion limit
2999 let config = TConfiguration::builder()
3000 .max_recursion_depth(Some(2))
3001 .build()
3002 .unwrap();
3003
3004 let mut protocol = TCompactInputProtocol::with_config(channel, config);
3005
3006 // First struct - should succeed
3007 assert!(protocol.read_struct_begin().is_ok());
3008
3009 // Second struct - should succeed (at limit)
3010 assert!(protocol.read_struct_begin().is_ok());
3011
3012 // Third struct - should fail (exceeds limit)
3013 let result = protocol.read_struct_begin();
3014 assert!(result.is_err());
3015 match result {
3016 Err(crate::Error::Protocol(e)) => {
3017 assert_eq!(e.kind, ProtocolErrorKind::DepthLimit);
3018 }
3019 _ => panic!("Expected protocol error with DepthLimit"),
3020 }
3021 }
3022
3023 #[test]
3024 fn must_check_container_size_overflow() {
3025 // Configure a small message size limit
3026 let config = TConfiguration::builder()
3027 .max_message_size(Some(1000))
3028 .max_frame_size(Some(1000))
3029 .build()
3030 .unwrap();
3031 let transport = TBufferChannel::with_capacity(100, 0);
3032 let mut i_prot = TCompactInputProtocol::with_config(transport, config);
3033
3034 // Write a list header that would require more memory than message size limit
3035 // List of 100 UUIDs (16 bytes each) = 1600 bytes > 1000 limit
3036 i_prot.transport.set_readable_bytes(&[
3037 0xFD, // element type UUID (0x0D) | count in next bytes (0xF0)
3038 0x64, // varint 100
3039 ]);
3040
3041 let result = i_prot.read_list_begin();
3042 assert!(result.is_err());
3043 match result {
3044 Err(crate::Error::Protocol(e)) => {
3045 assert_eq!(e.kind, ProtocolErrorKind::SizeLimit);
3046 assert!(e
3047 .message
3048 .contains("1600 bytes, exceeding message size limit of 1000"));
3049 }
3050 _ => panic!("Expected protocol error with SizeLimit"),
3051 }
3052 }
3053
3054 #[test]
3055 fn must_reject_negative_container_sizes() {
3056 let mut channel = TBufferChannel::with_capacity(100, 100);
3057
3058 let mut protocol = TCompactInputProtocol::new(channel.clone());
3059
3060 // Write header with negative size when decoded
3061 // In compact protocol, lists/sets use a header byte followed by size
3062 // We'll use 0x0F for element type and then a varint-encoded negative number
3063 channel.set_readable_bytes(&[
3064 0xF0, // Header: 15 in upper nibble (triggers varint read), List type in lower
3065 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, // Varint encoding of -1
3066 ]);
3067
3068 let result = protocol.read_list_begin();
3069 assert!(result.is_err());
3070 match result {
3071 Err(crate::Error::Protocol(e)) => {
3072 assert_eq!(e.kind, ProtocolErrorKind::NegativeSize);
3073 }
3074 _ => panic!("Expected protocol error with NegativeSize"),
3075 }
3076 }
3077
3078 #[test]
3079 fn must_enforce_container_size_limit() {
3080 let channel = TBufferChannel::with_capacity(100, 100);
3081 let (r_channel, mut w_channel) = channel.split().unwrap();
3082
3083 // Create protocol with explicit container size limit
3084 let config = TConfiguration::builder()
3085 .max_container_size(Some(1000))
3086 .build()
3087 .unwrap();
3088 let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3089
3090 // Write header with large size
3091 // Compact protocol: 0xF0 means size >= 15 is encoded as varint
3092 // Then we write a varint encoding 10000 (exceeds our limit of 1000)
3093 w_channel.set_readable_bytes(&[
3094 0xF0, // Header: 15 in upper nibble (triggers varint read), element type in lower
3095 0x90, 0x4E, // Varint encoding of 10000
3096 ]);
3097
3098 let result = protocol.read_list_begin();
3099 assert!(result.is_err());
3100 match result {
3101 Err(crate::Error::Protocol(e)) => {
3102 assert_eq!(e.kind, ProtocolErrorKind::SizeLimit);
3103 assert!(e.message.contains("exceeds maximum allowed size"));
3104 }
3105 _ => panic!("Expected protocol error with SizeLimit"),
3106 }
3107 }
3108
3109 #[test]
3110 fn must_handle_varint_size_overflow() {
3111 // Test that compact protocol properly handles varint-encoded sizes that would cause overflow
3112 let mut channel = TBufferChannel::with_capacity(100, 100);
3113
3114 let mut protocol = TCompactInputProtocol::new(channel.clone());
3115
3116 // Create input that encodes a very large size using varint encoding
3117 // 0xFA = list header with size >= 15 (so size follows as varint)
3118 // Then multiple 0xFF bytes which in varint encoding create a very large number
3119 channel.set_readable_bytes(&[
3120 0xFA, // List header: size >= 15, element type = 0x0A
3121 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, // Varint encoding of a huge number
3122 ]);
3123
3124 let result = protocol.read_list_begin();
3125 assert!(result.is_err());
3126 match result {
3127 Err(crate::Error::Protocol(e)) => {
3128 // The varint decoder might interpret this as negative, which is also fine
3129 assert!(
3130 e.kind == ProtocolErrorKind::SizeLimit
3131 || e.kind == ProtocolErrorKind::NegativeSize,
3132 "Expected SizeLimit or NegativeSize but got {:?}",
3133 e.kind
3134 );
3135 }
3136 _ => panic!("Expected protocol error"),
3137 }
3138 }
3139
3140 #[test]
3141 fn must_enforce_string_size_limit() {
3142 let channel = TBufferChannel::with_capacity(100, 100);
3143 let (r_channel, mut w_channel) = channel.split().unwrap();
3144
3145 // Create protocol with string limit of 100 bytes
3146 let config = TConfiguration::builder()
3147 .max_string_size(Some(100))
3148 .build()
3149 .unwrap();
3150 let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3151
3152 // Write a varint-encoded string size that exceeds the limit
3153 w_channel.set_readable_bytes(&[
3154 0xC8, 0x01, // Varint encoding of 200
3155 ]);
3156
3157 let result = protocol.read_string();
3158 assert!(result.is_err());
3159 match result {
3160 Err(crate::Error::Protocol(e)) => {
3161 assert_eq!(e.kind, ProtocolErrorKind::SizeLimit);
3162 assert!(e.message.contains("exceeds maximum allowed size"));
3163 }
3164 _ => panic!("Expected protocol error with SizeLimit"),
3165 }
3166 }
3167
3168 #[test]
3169 fn must_allow_no_limit_configuration() {
3170 let channel = TBufferChannel::with_capacity(40, 40);
3171
3172 let config = TConfiguration::no_limits();
3173 let mut protocol = TCompactInputProtocol::with_config(channel, config);
3174
3175 // Should be able to nest structs deeply without limit
3176 for _ in 0..100 {
3177 assert!(protocol.read_struct_begin().is_ok());
3178 }
3179
3180 for _ in 0..100 {
3181 assert!(protocol.read_struct_end().is_ok());
3182 }
3183 }
3184
3185 #[test]
3186 fn must_allow_containers_within_limit() {
3187 let channel = TBufferChannel::with_capacity(200, 200);
3188 let (r_channel, mut w_channel) = channel.split().unwrap();
3189
3190 // Create protocol with container limit of 100
3191 let config = TConfiguration::builder()
3192 .max_container_size(Some(100))
3193 .build()
3194 .unwrap();
3195 let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3196
3197 // Write a list with 5 i32 elements (well within limit of 100)
3198 // Compact protocol: size < 15 is encoded in header
3199 w_channel.set_readable_bytes(&[
3200 0x55, // Header: size=5, element type=5 (i32)
3201 // 5 varint-encoded i32 values
3202 0x0A, // 10
3203 0x14, // 20
3204 0x1E, // 30
3205 0x28, // 40
3206 0x32, // 50
3207 ]);
3208
3209 let result = protocol.read_list_begin();
3210 assert!(result.is_ok());
3211 let list_ident = result.unwrap();
3212 assert_eq!(list_ident.size, 5);
3213 assert_eq!(list_ident.element_type, TType::I32);
3214 }
3215
3216 #[test]
3217 fn must_allow_strings_within_limit() {
3218 let channel = TBufferChannel::with_capacity(100, 100);
3219 let (r_channel, mut w_channel) = channel.split().unwrap();
3220
3221 let config = TConfiguration::builder()
3222 .max_string_size(Some(1000))
3223 .build()
3224 .unwrap();
3225 let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3226
3227 // Write a string "hello" (5 bytes, well within limit)
3228 w_channel.set_readable_bytes(&[
3229 0x05, // Varint-encoded length: 5
3230 b'h', b'e', b'l', b'l', b'o',
3231 ]);
3232
3233 let result = protocol.read_string();
3234 assert!(result.is_ok());
3235 assert_eq!(result.unwrap(), "hello");
3236 }
Allen George8b96bfb2016-11-02 08:01:08 -04003237}