blob: 0ded14a143b96e47018689cc061da8ea2dee6cb2 [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 {
Jinpeng49fe0e22024-12-12 17:31:29 -0500220 self.last_read_field_id = self
221 .last_read_field_id
222 .checked_add(field_delta as i16)
223 .ok_or(crate::Error::Protocol(crate::ProtocolError {
224 kind: crate::ProtocolErrorKind::InvalidData,
225 message: format!(
226 "invalid field delta {} for last field id {}",
227 field_delta, self.last_read_field_id
228 ),
229 }))?;
Allen George8b96bfb2016-11-02 08:01:08 -0400230 } else {
231 self.last_read_field_id = self.read_i16()?;
232 };
233
Allen Georgeef7a1892018-12-16 18:01:37 -0500234 Ok(TFieldIdentifier {
235 name: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500236 field_type,
Allen Georgeef7a1892018-12-16 18:01:37 -0500237 id: Some(self.last_read_field_id),
238 })
Allen George8b96bfb2016-11-02 08:01:08 -0400239 }
240 }
241 }
242
Allen Georgeb0d14132020-03-29 11:48:55 -0400243 fn read_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400244 Ok(())
245 }
246
Allen Georgeb0d14132020-03-29 11:48:55 -0400247 fn read_bool(&mut self) -> crate::Result<bool> {
Allen George8b96bfb2016-11-02 08:01:08 -0400248 match self.pending_read_bool_value.take() {
249 Some(b) => Ok(b),
250 None => {
251 let b = self.read_byte()?;
252 match b {
Jörn Horstmann717bd792025-02-02 23:10:27 +0100253 // Previous versions of the thrift compact protocol specification said to use 0
254 // and 1 inside collections, but that differed from existing implementations.
255 // The specification was updated in https://github.com/apache/thrift/commit/2c29c5665bc442e703480bb0ee60fe925ffe02e8.
256 0x00 => Ok(false),
Allen George8b96bfb2016-11-02 08:01:08 -0400257 0x01 => Ok(true),
258 0x02 => Ok(false),
Allen Georgeb0d14132020-03-29 11:48:55 -0400259 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
260 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500261 message: format!("cannot convert {} into bool", unkn),
262 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400263 }
264 }
265 }
266 }
267
Allen Georgeb0d14132020-03-29 11:48:55 -0400268 fn read_bytes(&mut self) -> crate::Result<Vec<u8>> {
Allen George0e22c362017-01-30 07:15:00 -0500269 let len = self.transport.read_varint::<u32>()?;
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700270
271 if let Some(max_size) = self.config.max_string_size() {
272 if len as usize > max_size {
273 return Err(crate::Error::Protocol(ProtocolError::new(
274 ProtocolErrorKind::SizeLimit,
275 format!(
276 "Byte array size {} exceeds maximum allowed size of {}",
277 len, max_size
278 ),
279 )));
280 }
281 }
282
Allen George8b96bfb2016-11-02 08:01:08 -0400283 let mut buf = vec![0u8; len as usize];
Allen George0e22c362017-01-30 07:15:00 -0500284 self.transport
285 .read_exact(&mut buf)
286 .map_err(From::from)
287 .map(|_| buf)
Allen George8b96bfb2016-11-02 08:01:08 -0400288 }
289
Allen Georgeb0d14132020-03-29 11:48:55 -0400290 fn read_i8(&mut self) -> crate::Result<i8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400291 self.read_byte().map(|i| i as i8)
292 }
293
Allen Georgeb0d14132020-03-29 11:48:55 -0400294 fn read_i16(&mut self) -> crate::Result<i16> {
Allen George0e22c362017-01-30 07:15:00 -0500295 self.transport.read_varint::<i16>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400296 }
297
Allen Georgeb0d14132020-03-29 11:48:55 -0400298 fn read_i32(&mut self) -> crate::Result<i32> {
Allen George0e22c362017-01-30 07:15:00 -0500299 self.transport.read_varint::<i32>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400300 }
301
Allen Georgeb0d14132020-03-29 11:48:55 -0400302 fn read_i64(&mut self) -> crate::Result<i64> {
Allen George0e22c362017-01-30 07:15:00 -0500303 self.transport.read_varint::<i64>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400304 }
305
Allen Georgeb0d14132020-03-29 11:48:55 -0400306 fn read_double(&mut self) -> crate::Result<f64> {
Allen George8a1743d2020-12-05 01:19:27 -0500307 self.transport
308 .read_f64::<LittleEndian>()
309 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400310 }
311
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800312 fn read_uuid(&mut self) -> crate::Result<uuid::Uuid> {
Hasnain Lakhani57c5fc12025-08-02 21:12:07 -0700313 let mut buf = [0u8; 16];
314 self.transport
315 .read_exact(&mut buf)
316 .map(|_| uuid::Uuid::from_bytes(buf))
317 .map_err(From::from)
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800318 }
319
Allen Georgeb0d14132020-03-29 11:48:55 -0400320 fn read_string(&mut self) -> crate::Result<String> {
Allen George8b96bfb2016-11-02 08:01:08 -0400321 let bytes = self.read_bytes()?;
322 String::from_utf8(bytes).map_err(From::from)
323 }
324
Allen Georgeb0d14132020-03-29 11:48:55 -0400325 fn read_list_begin(&mut self) -> crate::Result<TListIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400326 let (element_type, element_count) = self.read_list_set_begin()?;
327 Ok(TListIdentifier::new(element_type, element_count))
328 }
329
Allen Georgeb0d14132020-03-29 11:48:55 -0400330 fn read_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400331 Ok(())
332 }
333
Allen Georgeb0d14132020-03-29 11:48:55 -0400334 fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400335 let (element_type, element_count) = self.read_list_set_begin()?;
336 Ok(TSetIdentifier::new(element_type, element_count))
337 }
338
Allen Georgeb0d14132020-03-29 11:48:55 -0400339 fn read_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400340 Ok(())
341 }
342
Allen Georgeb0d14132020-03-29 11:48:55 -0400343 fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier> {
Allen George0e22c362017-01-30 07:15:00 -0500344 let element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400345 if element_count == 0 {
346 Ok(TMapIdentifier::new(None, None, 0))
347 } else {
348 let type_header = self.read_byte()?;
349 let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
350 let val_type = collection_u8_to_type(type_header & 0x0F)?;
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700351
352 let key_min_size = self.min_serialized_size(key_type);
353 let value_min_size = self.min_serialized_size(val_type);
354 let element_size = key_min_size + value_min_size;
355 super::check_container_size(&self.config, element_count, element_size)?;
356
Allen George8b96bfb2016-11-02 08:01:08 -0400357 Ok(TMapIdentifier::new(key_type, val_type, element_count))
358 }
359 }
360
Allen Georgeb0d14132020-03-29 11:48:55 -0400361 fn read_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400362 Ok(())
363 }
364
365 // utility
366 //
367
Allen Georgeb0d14132020-03-29 11:48:55 -0400368 fn read_byte(&mut self) -> crate::Result<u8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400369 let mut buf = [0u8; 1];
Allen George0e22c362017-01-30 07:15:00 -0500370 self.transport
371 .read_exact(&mut buf)
372 .map_err(From::from)
373 .map(|_| buf[0])
Allen George8b96bfb2016-11-02 08:01:08 -0400374 }
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700375
376 fn min_serialized_size(&self, field_type: TType) -> usize {
377 compact_protocol_min_serialized_size(field_type)
378 }
379}
380
381pub(crate) fn compact_protocol_min_serialized_size(field_type: TType) -> usize {
382 match field_type {
383 TType::Stop => 1, // 1 byte
384 TType::Void => 1, // 1 byte
385 TType::Bool => 1, // 1 byte
386 TType::I08 => 1, // 1 byte
387 TType::Double => 8, // 8 bytes (not varint encoded)
388 TType::I16 => 1, // 1 byte minimum (varint)
389 TType::I32 => 1, // 1 byte minimum (varint)
390 TType::I64 => 1, // 1 byte minimum (varint)
391 TType::String => 1, // 1 byte minimum for length (varint)
392 TType::Struct => 1, // 1 byte minimum (stop field)
393 TType::Map => 1, // 1 byte minimum
394 TType::Set => 1, // 1 byte minimum
395 TType::List => 1, // 1 byte minimum
396 TType::Uuid => 16, // 16 bytes
397 TType::Utf7 => 1, // 1 byte
398 }
Allen George8b96bfb2016-11-02 08:01:08 -0400399}
400
Vadim Chekand3355af2018-01-05 23:12:47 -0500401impl<T> io::Seek for TCompactInputProtocol<T>
402where
403 T: io::Seek + TReadTransport,
404{
405 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
406 self.transport.seek(pos)
407 }
408}
409
Allen George8b96bfb2016-11-02 08:01:08 -0400410/// Factory for creating instances of `TCompactInputProtocol`.
411#[derive(Default)]
412pub struct TCompactInputProtocolFactory;
413
414impl TCompactInputProtocolFactory {
415 /// Create a `TCompactInputProtocolFactory`.
416 pub fn new() -> TCompactInputProtocolFactory {
417 TCompactInputProtocolFactory {}
418 }
419}
420
421impl TInputProtocolFactory for TCompactInputProtocolFactory {
Danny Browning77d96c12019-08-21 13:41:07 -0600422 fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500423 Box::new(TCompactInputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400424 }
425}
426
427/// Write messages using the Thrift compact protocol.
428///
429/// # Examples
430///
431/// Create and use a `TCompactOutputProtocol`.
432///
433/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -0400434/// use thrift::protocol::{TCompactOutputProtocol, TOutputProtocol};
Allen George0e22c362017-01-30 07:15:00 -0500435/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -0400436///
Allen George0e22c362017-01-30 07:15:00 -0500437/// let mut channel = TTcpChannel::new();
438/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400439///
Allen George0e22c362017-01-30 07:15:00 -0500440/// let mut protocol = TCompactOutputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -0400441///
Allen George0e22c362017-01-30 07:15:00 -0500442/// protocol.write_bool(true).unwrap();
443/// protocol.write_string("test_string").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400444/// ```
Allen George0e22c362017-01-30 07:15:00 -0500445#[derive(Debug)]
446pub struct TCompactOutputProtocol<T>
447where
448 T: TWriteTransport,
449{
Allen George8b96bfb2016-11-02 08:01:08 -0400450 // Identifier of the last field serialized for a struct.
451 last_write_field_id: i16,
Allen George0e22c362017-01-30 07:15:00 -0500452 // Stack of the last written field ids (new entry added each time a nested struct is written).
Allen George8b96bfb2016-11-02 08:01:08 -0400453 write_field_id_stack: Vec<i16>,
454 // Field identifier of the boolean field to be written.
455 // Saved because boolean fields and their value are encoded in a single byte
456 pending_write_bool_field_identifier: Option<TFieldIdentifier>,
457 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -0500458 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -0400459}
460
Allen George0e22c362017-01-30 07:15:00 -0500461impl<T> TCompactOutputProtocol<T>
462where
463 T: TWriteTransport,
464{
Allen George8b96bfb2016-11-02 08:01:08 -0400465 /// Create a `TCompactOutputProtocol` that writes bytes to `transport`.
Allen George0e22c362017-01-30 07:15:00 -0500466 pub fn new(transport: T) -> TCompactOutputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -0400467 TCompactOutputProtocol {
468 last_write_field_id: 0,
469 write_field_id_stack: Vec::new(),
470 pending_write_bool_field_identifier: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500471 transport,
Allen George8b96bfb2016-11-02 08:01:08 -0400472 }
473 }
474
475 // FIXME: field_type as unconstrained u8 is bad
Allen Georgeb0d14132020-03-29 11:48:55 -0400476 fn write_field_header(&mut self, field_type: u8, field_id: i16) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400477 let field_delta = field_id - self.last_write_field_id;
478 if field_delta > 0 && field_delta < 15 {
479 self.write_byte(((field_delta as u8) << 4) | field_type)?;
480 } else {
481 self.write_byte(field_type)?;
482 self.write_i16(field_id)?;
483 }
484 self.last_write_field_id = field_id;
485 Ok(())
486 }
487
Allen George8a1743d2020-12-05 01:19:27 -0500488 fn write_list_set_begin(
489 &mut self,
490 element_type: TType,
491 element_count: i32,
492 ) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400493 let elem_identifier = collection_type_to_u8(element_type);
494 if element_count <= 14 {
Hasnain Lakhani7ac79ab2025-08-25 14:40:43 -0700495 let header = ((element_count as u8) << 4) | elem_identifier;
Allen George8b96bfb2016-11-02 08:01:08 -0400496 self.write_byte(header)
497 } else {
498 let header = 0xF0 | elem_identifier;
499 self.write_byte(header)?;
Allen George48905102021-02-20 08:47:01 -0500500 // element count is strictly positive as per the spec, so
501 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George8b96bfb2016-11-02 08:01:08 -0400502 self.transport
Allen George8b96bfb2016-11-02 08:01:08 -0400503 .write_varint(element_count as u32)
504 .map_err(From::from)
505 .map(|_| ())
506 }
507 }
508
509 fn assert_no_pending_bool_write(&self) {
510 if let Some(ref f) = self.pending_write_bool_field_identifier {
511 panic!("pending bool field {:?} not written", f)
512 }
513 }
514}
515
Allen George0e22c362017-01-30 07:15:00 -0500516impl<T> TOutputProtocol for TCompactOutputProtocol<T>
517where
518 T: TWriteTransport,
519{
Allen Georgeb0d14132020-03-29 11:48:55 -0400520 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400521 self.write_byte(COMPACT_PROTOCOL_ID)?;
522 self.write_byte((u8::from(identifier.message_type) << 5) | COMPACT_VERSION)?;
Allen George48905102021-02-20 08:47:01 -0500523 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George55c3e4c2021-03-01 23:19:52 -0500524 self.transport
525 .write_varint(identifier.sequence_number as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400526 self.write_string(&identifier.name)?;
527 Ok(())
528 }
529
Allen Georgeb0d14132020-03-29 11:48:55 -0400530 fn write_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400531 self.assert_no_pending_bool_write();
532 Ok(())
533 }
534
Allen Georgeb0d14132020-03-29 11:48:55 -0400535 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400536 self.write_field_id_stack.push(self.last_write_field_id);
537 self.last_write_field_id = 0;
538 Ok(())
539 }
540
Allen Georgeb0d14132020-03-29 11:48:55 -0400541 fn write_struct_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400542 self.assert_no_pending_bool_write();
Allen Georgeef7a1892018-12-16 18:01:37 -0500543 self.last_write_field_id = self
544 .write_field_id_stack
Allen George0e22c362017-01-30 07:15:00 -0500545 .pop()
546 .expect("should have previous field ids");
Allen George8b96bfb2016-11-02 08:01:08 -0400547 Ok(())
548 }
549
Allen Georgeb0d14132020-03-29 11:48:55 -0400550 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400551 match identifier.field_type {
552 TType::Bool => {
553 if self.pending_write_bool_field_identifier.is_some() {
Allen George0e22c362017-01-30 07:15:00 -0500554 panic!(
555 "should not have a pending bool while writing another bool with id: \
Allen Georgeef7a1892018-12-16 18:01:37 -0500556 {:?}",
Allen George0e22c362017-01-30 07:15:00 -0500557 identifier
558 )
Allen George8b96bfb2016-11-02 08:01:08 -0400559 }
560 self.pending_write_bool_field_identifier = Some(identifier.clone());
561 Ok(())
562 }
563 _ => {
564 let field_type = type_to_u8(identifier.field_type);
Allen Georgeef7a1892018-12-16 18:01:37 -0500565 let field_id = identifier.id.expect("non-stop field should have field id");
Allen George8b96bfb2016-11-02 08:01:08 -0400566 self.write_field_header(field_type, field_id)
567 }
568 }
569 }
570
Allen Georgeb0d14132020-03-29 11:48:55 -0400571 fn write_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400572 self.assert_no_pending_bool_write();
573 Ok(())
574 }
575
Allen Georgeb0d14132020-03-29 11:48:55 -0400576 fn write_field_stop(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400577 self.assert_no_pending_bool_write();
578 self.write_byte(type_to_u8(TType::Stop))
579 }
580
Allen Georgeb0d14132020-03-29 11:48:55 -0400581 fn write_bool(&mut self, b: bool) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400582 match self.pending_write_bool_field_identifier.take() {
583 Some(pending) => {
584 let field_id = pending.id.expect("bool field should have a field id");
585 let field_type_as_u8 = if b { 0x01 } else { 0x02 };
586 self.write_field_header(field_type_as_u8, field_id)
587 }
588 None => {
589 if b {
590 self.write_byte(0x01)
591 } else {
592 self.write_byte(0x02)
593 }
594 }
595 }
596 }
597
Allen Georgeb0d14132020-03-29 11:48:55 -0400598 fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> {
Allen George48905102021-02-20 08:47:01 -0500599 // length is strictly positive as per the spec, so
600 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500601 self.transport.write_varint(b.len() as u32)?;
602 self.transport.write_all(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400603 }
604
Allen Georgeb0d14132020-03-29 11:48:55 -0400605 fn write_i8(&mut self, i: i8) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400606 self.write_byte(i as u8)
607 }
608
Allen Georgeb0d14132020-03-29 11:48:55 -0400609 fn write_i16(&mut self, i: i16) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500610 self.transport
Allen George48905102021-02-20 08:47:01 -0500611 .write_varint(i)
Allen George0e22c362017-01-30 07:15:00 -0500612 .map_err(From::from)
613 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400614 }
615
Allen Georgeb0d14132020-03-29 11:48:55 -0400616 fn write_i32(&mut self, i: i32) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500617 self.transport
618 .write_varint(i)
619 .map_err(From::from)
620 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400621 }
622
Allen Georgeb0d14132020-03-29 11:48:55 -0400623 fn write_i64(&mut self, i: i64) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500624 self.transport
625 .write_varint(i)
626 .map_err(From::from)
627 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400628 }
629
Allen Georgeb0d14132020-03-29 11:48:55 -0400630 fn write_double(&mut self, d: f64) -> crate::Result<()> {
Allen George8a1743d2020-12-05 01:19:27 -0500631 self.transport
632 .write_f64::<LittleEndian>(d)
633 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400634 }
635
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800636 fn write_uuid(&mut self, uuid: &uuid::Uuid) -> crate::Result<()> {
Hasnain Lakhani57c5fc12025-08-02 21:12:07 -0700637 self.transport
638 .write_all(uuid.as_bytes())
639 .map_err(From::from)
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800640 }
641
Allen Georgeb0d14132020-03-29 11:48:55 -0400642 fn write_string(&mut self, s: &str) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400643 self.write_bytes(s.as_bytes())
644 }
645
Allen Georgeb0d14132020-03-29 11:48:55 -0400646 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400647 self.write_list_set_begin(identifier.element_type, identifier.size)
648 }
649
Allen Georgeb0d14132020-03-29 11:48:55 -0400650 fn write_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400651 Ok(())
652 }
653
Allen Georgeb0d14132020-03-29 11:48:55 -0400654 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400655 self.write_list_set_begin(identifier.element_type, identifier.size)
656 }
657
Allen Georgeb0d14132020-03-29 11:48:55 -0400658 fn write_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400659 Ok(())
660 }
661
Allen Georgeb0d14132020-03-29 11:48:55 -0400662 fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400663 if identifier.size == 0 {
664 self.write_byte(0)
665 } else {
Allen George48905102021-02-20 08:47:01 -0500666 // element count is strictly positive as per the spec, so
667 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500668 self.transport.write_varint(identifier.size as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400669
Allen George0e22c362017-01-30 07:15:00 -0500670 let key_type = identifier
671 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400672 .expect("map identifier to write should contain key type");
673 let key_type_byte = collection_type_to_u8(key_type) << 4;
674
Allen George0e22c362017-01-30 07:15:00 -0500675 let val_type = identifier
676 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400677 .expect("map identifier to write should contain value type");
678 let val_type_byte = collection_type_to_u8(val_type);
679
680 let map_type_header = key_type_byte | val_type_byte;
681 self.write_byte(map_type_header)
682 }
683 }
684
Allen Georgeb0d14132020-03-29 11:48:55 -0400685 fn write_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400686 Ok(())
687 }
688
Allen Georgeb0d14132020-03-29 11:48:55 -0400689 fn flush(&mut self) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500690 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400691 }
692
693 // utility
694 //
695
Allen Georgeb0d14132020-03-29 11:48:55 -0400696 fn write_byte(&mut self, b: u8) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500697 self.transport.write(&[b]).map_err(From::from).map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400698 }
699}
700
701/// Factory for creating instances of `TCompactOutputProtocol`.
702#[derive(Default)]
703pub struct TCompactOutputProtocolFactory;
704
705impl TCompactOutputProtocolFactory {
706 /// Create a `TCompactOutputProtocolFactory`.
707 pub fn new() -> TCompactOutputProtocolFactory {
708 TCompactOutputProtocolFactory {}
709 }
710}
711
712impl TOutputProtocolFactory for TCompactOutputProtocolFactory {
Allen George8a1743d2020-12-05 01:19:27 -0500713 fn create(
714 &self,
715 transport: Box<dyn TWriteTransport + Send>,
716 ) -> Box<dyn TOutputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500717 Box::new(TCompactOutputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400718 }
719}
720
721fn collection_type_to_u8(field_type: TType) -> u8 {
722 match field_type {
723 TType::Bool => 0x01,
724 f => type_to_u8(f),
725 }
726}
727
728fn type_to_u8(field_type: TType) -> u8 {
729 match field_type {
730 TType::Stop => 0x00,
731 TType::I08 => 0x03, // equivalent to TType::Byte
732 TType::I16 => 0x04,
733 TType::I32 => 0x05,
734 TType::I64 => 0x06,
735 TType::Double => 0x07,
736 TType::String => 0x08,
737 TType::List => 0x09,
738 TType::Set => 0x0A,
739 TType::Map => 0x0B,
740 TType::Struct => 0x0C,
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800741 TType::Uuid => 0x0D,
Allen George2b691ee2021-10-14 22:25:07 -0400742 _ => panic!("should not have attempted to convert {} to u8", field_type),
Allen George8b96bfb2016-11-02 08:01:08 -0400743 }
744}
745
Allen Georgeb0d14132020-03-29 11:48:55 -0400746fn collection_u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400747 match b {
Jörn Horstmann717bd792025-02-02 23:10:27 +0100748 // For historical and compatibility reasons, a reader should be capable to deal with both cases.
749 // The only valid value in the original spec was 2, but due to a widespread implementation bug
750 // the defacto standard across large parts of the library became 1 instead.
751 // As a result, both values are now allowed.
752 0x01 | 0x02 => Ok(TType::Bool),
Allen George8b96bfb2016-11-02 08:01:08 -0400753 o => u8_to_type(o),
754 }
755}
756
Allen Georgeb0d14132020-03-29 11:48:55 -0400757fn u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400758 match b {
759 0x00 => Ok(TType::Stop),
760 0x03 => Ok(TType::I08), // equivalent to TType::Byte
761 0x04 => Ok(TType::I16),
762 0x05 => Ok(TType::I32),
763 0x06 => Ok(TType::I64),
764 0x07 => Ok(TType::Double),
765 0x08 => Ok(TType::String),
766 0x09 => Ok(TType::List),
767 0x0A => Ok(TType::Set),
768 0x0B => Ok(TType::Map),
769 0x0C => Ok(TType::Struct),
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800770 0x0D => Ok(TType::Uuid),
Allen Georgeb0d14132020-03-29 11:48:55 -0400771 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
772 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500773 message: format!("cannot convert {} into TType", unkn),
774 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400775 }
776}
777
778#[cfg(test)]
779mod tests {
780
Allen Georgeb0d14132020-03-29 11:48:55 -0400781 use crate::protocol::{
Allen Georgeef7a1892018-12-16 18:01:37 -0500782 TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
783 TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
784 };
Allen Georgeb0d14132020-03-29 11:48:55 -0400785 use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400786
787 use super::*;
788
789 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500790 fn must_write_message_begin_largest_maximum_positive_sequence_number() {
791 let (_, mut o_prot) = test_objects();
792
793 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
794 "bar",
795 TMessageType::Reply,
796 i32::MAX
797 )));
798
799 #[rustfmt::skip]
800 let expected: [u8; 11] = [
801 0x82, /* protocol ID */
802 0x41, /* message type | protocol version */
803 0xFF,
804 0xFF,
805 0xFF,
806 0xFF,
807 0x07, /* non-zig-zag varint sequence number */
808 0x03, /* message-name length */
809 0x62,
810 0x61,
811 0x72 /* "bar" */,
812 ];
813
814 assert_eq_written_bytes!(o_prot, expected);
815 }
816
817 #[test]
818 fn must_read_message_begin_largest_maximum_positive_sequence_number() {
819 let (mut i_prot, _) = test_objects();
820
821 #[rustfmt::skip]
822 let source_bytes: [u8; 11] = [
823 0x82, /* protocol ID */
824 0x41, /* message type | protocol version */
825 0xFF,
826 0xFF,
827 0xFF,
828 0xFF,
829 0x07, /* non-zig-zag varint sequence number */
830 0x03, /* message-name length */
831 0x62,
832 0x61,
833 0x72 /* "bar" */,
834 ];
835
836 i_prot.transport.set_readable_bytes(&source_bytes);
837
838 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MAX);
839 let res = assert_success!(i_prot.read_message_begin());
840
841 assert_eq!(&expected, &res);
842 }
843
844 #[test]
845 fn must_write_message_begin_positive_sequence_number_0() {
Allen George0e22c362017-01-30 07:15:00 -0500846 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400847
Allen Georgeef7a1892018-12-16 18:01:37 -0500848 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
849 "foo",
850 TMessageType::Call,
851 431
852 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400853
Allen George7ddbcc02020-11-08 09:51:19 -0500854 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500855 let expected: [u8; 8] = [
856 0x82, /* protocol ID */
857 0x21, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500858 0xAF,
859 0x03, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500860 0x03, /* message-name length */
861 0x66,
862 0x6F,
863 0x6F /* "foo" */,
864 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400865
Allen George0e22c362017-01-30 07:15:00 -0500866 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400867 }
868
869 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500870 fn must_read_message_begin_positive_sequence_number_0() {
871 let (mut i_prot, _) = test_objects();
872
873 #[rustfmt::skip]
874 let source_bytes: [u8; 8] = [
875 0x82, /* protocol ID */
876 0x21, /* message type | protocol version */
877 0xAF,
878 0x03, /* non-zig-zag varint sequence number */
879 0x03, /* message-name length */
880 0x66,
881 0x6F,
882 0x6F /* "foo" */,
883 ];
884
885 i_prot.transport.set_readable_bytes(&source_bytes);
886
887 let expected = TMessageIdentifier::new("foo", TMessageType::Call, 431);
888 let res = assert_success!(i_prot.read_message_begin());
889
890 assert_eq!(&expected, &res);
891 }
892
893 #[test]
894 fn must_write_message_begin_positive_sequence_number_1() {
Allen George0e22c362017-01-30 07:15:00 -0500895 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400896
Allen Georgeef7a1892018-12-16 18:01:37 -0500897 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
898 "bar",
899 TMessageType::Reply,
Allen George7ddbcc02020-11-08 09:51:19 -0500900 991_828
Allen Georgeef7a1892018-12-16 18:01:37 -0500901 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400902
Allen George7ddbcc02020-11-08 09:51:19 -0500903 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500904 let expected: [u8; 9] = [
905 0x82, /* protocol ID */
906 0x41, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500907 0xD4,
908 0xC4,
909 0x3C, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500910 0x03, /* message-name length */
911 0x62,
912 0x61,
913 0x72 /* "bar" */,
914 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400915
Allen George0e22c362017-01-30 07:15:00 -0500916 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400917 }
918
919 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500920 fn must_read_message_begin_positive_sequence_number_1() {
921 let (mut i_prot, _) = test_objects();
922
923 #[rustfmt::skip]
924 let source_bytes: [u8; 9] = [
925 0x82, /* protocol ID */
926 0x41, /* message type | protocol version */
927 0xD4,
928 0xC4,
929 0x3C, /* non-zig-zag varint sequence number */
930 0x03, /* message-name length */
931 0x62,
932 0x61,
933 0x72 /* "bar" */,
934 ];
935
936 i_prot.transport.set_readable_bytes(&source_bytes);
937
938 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 991_828);
939 let res = assert_success!(i_prot.read_message_begin());
940
941 assert_eq!(&expected, &res);
942 }
943
944 #[test]
945 fn must_write_message_begin_zero_sequence_number() {
946 let (_, mut o_prot) = test_objects();
947
948 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
949 "bar",
950 TMessageType::Reply,
951 0
952 )));
953
954 #[rustfmt::skip]
955 let expected: [u8; 7] = [
956 0x82, /* protocol ID */
957 0x41, /* message type | protocol version */
958 0x00, /* non-zig-zag varint sequence number */
959 0x03, /* message-name length */
960 0x62,
961 0x61,
962 0x72 /* "bar" */,
963 ];
964
965 assert_eq_written_bytes!(o_prot, expected);
966 }
967
968 #[test]
969 fn must_read_message_begin_zero_sequence_number() {
970 let (mut i_prot, _) = test_objects();
971
972 #[rustfmt::skip]
973 let source_bytes: [u8; 7] = [
974 0x82, /* protocol ID */
975 0x41, /* message type | protocol version */
976 0x00, /* non-zig-zag varint sequence number */
977 0x03, /* message-name length */
978 0x62,
979 0x61,
980 0x72 /* "bar" */,
981 ];
982
983 i_prot.transport.set_readable_bytes(&source_bytes);
984
985 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 0);
986 let res = assert_success!(i_prot.read_message_begin());
987
988 assert_eq!(&expected, &res);
989 }
990
991 #[test]
992 fn must_write_message_begin_largest_minimum_negative_sequence_number() {
993 let (_, mut o_prot) = test_objects();
994
995 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
996 "bar",
997 TMessageType::Reply,
998 i32::MIN
999 )));
1000
1001 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
1002 #[rustfmt::skip]
1003 let expected: [u8; 11] = [
1004 0x82, /* protocol ID */
1005 0x41, /* message type | protocol version */
1006 0x80,
1007 0x80,
1008 0x80,
1009 0x80,
1010 0x08, /* non-zig-zag varint sequence number */
1011 0x03, /* message-name length */
1012 0x62,
1013 0x61,
1014 0x72 /* "bar" */,
1015 ];
1016
1017 assert_eq_written_bytes!(o_prot, expected);
1018 }
1019
1020 #[test]
1021 fn must_read_message_begin_largest_minimum_negative_sequence_number() {
1022 let (mut i_prot, _) = test_objects();
1023
1024 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
1025 #[rustfmt::skip]
1026 let source_bytes: [u8; 11] = [
1027 0x82, /* protocol ID */
1028 0x41, /* message type | protocol version */
1029 0x80,
1030 0x80,
1031 0x80,
1032 0x80,
1033 0x08, /* non-zig-zag varint sequence number */
1034 0x03, /* message-name length */
1035 0x62,
1036 0x61,
1037 0x72 /* "bar" */,
1038 ];
1039
1040 i_prot.transport.set_readable_bytes(&source_bytes);
1041
1042 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MIN);
1043 let res = assert_success!(i_prot.read_message_begin());
1044
1045 assert_eq!(&expected, &res);
1046 }
1047
1048 #[test]
1049 fn must_write_message_begin_negative_sequence_number_0() {
1050 let (_, mut o_prot) = test_objects();
1051
1052 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1053 "foo",
1054 TMessageType::Call,
1055 -431
1056 )));
1057
1058 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
1059 #[rustfmt::skip]
1060 let expected: [u8; 11] = [
1061 0x82, /* protocol ID */
1062 0x21, /* message type | protocol version */
1063 0xD1,
1064 0xFC,
1065 0xFF,
1066 0xFF,
1067 0x0F, /* non-zig-zag varint sequence number */
1068 0x03, /* message-name length */
1069 0x66,
1070 0x6F,
1071 0x6F /* "foo" */,
1072 ];
1073
1074 assert_eq_written_bytes!(o_prot, expected);
1075 }
1076
1077 #[test]
1078 fn must_read_message_begin_negative_sequence_number_0() {
1079 let (mut i_prot, _) = test_objects();
1080
1081 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
1082 #[rustfmt::skip]
1083 let source_bytes: [u8; 11] = [
1084 0x82, /* protocol ID */
1085 0x21, /* message type | protocol version */
1086 0xD1,
1087 0xFC,
1088 0xFF,
1089 0xFF,
1090 0x0F, /* non-zig-zag varint sequence number */
1091 0x03, /* message-name length */
1092 0x66,
1093 0x6F,
1094 0x6F /* "foo" */,
1095 ];
1096
1097 i_prot.transport.set_readable_bytes(&source_bytes);
1098
1099 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -431);
1100 let res = assert_success!(i_prot.read_message_begin());
1101
1102 assert_eq!(&expected, &res);
1103 }
1104
1105 #[test]
1106 fn must_write_message_begin_negative_sequence_number_1() {
1107 let (_, mut o_prot) = test_objects();
1108
1109 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1110 "foo",
1111 TMessageType::Call,
1112 -73_184_125
1113 )));
1114
1115 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1116 #[rustfmt::skip]
1117 let expected: [u8; 11] = [
1118 0x82, /* protocol ID */
1119 0x21, /* message type | protocol version */
1120 0x83,
1121 0x99,
1122 0x8D,
1123 0xDD,
1124 0x0F, /* non-zig-zag varint sequence number */
1125 0x03, /* message-name length */
1126 0x66,
1127 0x6F,
1128 0x6F /* "foo" */,
1129 ];
1130
1131 assert_eq_written_bytes!(o_prot, expected);
1132 }
1133
1134 #[test]
1135 fn must_read_message_begin_negative_sequence_number_1() {
1136 let (mut i_prot, _) = test_objects();
1137
1138 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1139 #[rustfmt::skip]
1140 let source_bytes: [u8; 11] = [
1141 0x82, /* protocol ID */
1142 0x21, /* message type | protocol version */
1143 0x83,
1144 0x99,
1145 0x8D,
1146 0xDD,
1147 0x0F, /* non-zig-zag varint sequence number */
1148 0x03, /* message-name length */
1149 0x66,
1150 0x6F,
1151 0x6F /* "foo" */,
1152 ];
1153
1154 i_prot.transport.set_readable_bytes(&source_bytes);
1155
1156 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -73_184_125);
1157 let res = assert_success!(i_prot.read_message_begin());
1158
1159 assert_eq!(&expected, &res);
1160 }
1161
1162 #[test]
1163 fn must_write_message_begin_negative_sequence_number_2() {
1164 let (_, mut o_prot) = test_objects();
1165
1166 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1167 "foo",
1168 TMessageType::Call,
1169 -1_073_741_823
1170 )));
1171
1172 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
1173 #[rustfmt::skip]
1174 let expected: [u8; 11] = [
1175 0x82, /* protocol ID */
1176 0x21, /* message type | protocol version */
1177 0x81,
1178 0x80,
1179 0x80,
1180 0x80,
1181 0x0C, /* non-zig-zag varint sequence number */
1182 0x03, /* message-name length */
1183 0x66,
1184 0x6F,
1185 0x6F /* "foo" */,
1186 ];
1187
1188 assert_eq_written_bytes!(o_prot, expected);
1189 }
1190
1191 #[test]
1192 fn must_read_message_begin_negative_sequence_number_2() {
1193 let (mut i_prot, _) = test_objects();
1194
1195 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
Allen George55c3e4c2021-03-01 23:19:52 -05001196 #[rustfmt::skip]
Allen George8a1743d2020-12-05 01:19:27 -05001197 let source_bytes: [u8; 11] = [
1198 0x82, /* protocol ID */
1199 0x21, /* message type | protocol version */
1200 0x81,
1201 0x80,
1202 0x80,
1203 0x80,
1204 0x0C, /* non-zig-zag varint sequence number */
1205 0x03, /* message-name length */
1206 0x66,
1207 0x6F,
Allen George55c3e4c2021-03-01 23:19:52 -05001208 0x6F, /* "foo" */
Allen George8a1743d2020-12-05 01:19:27 -05001209 ];
1210
1211 i_prot.transport.set_readable_bytes(&source_bytes);
1212
1213 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -1_073_741_823);
1214 let res = assert_success!(i_prot.read_message_begin());
1215
1216 assert_eq!(&expected, &res);
1217 }
1218
1219 #[test]
Nik Claytone7917602020-03-05 11:51:15 +01001220 fn must_round_trip_upto_i64_maxvalue() {
1221 // See https://issues.apache.org/jira/browse/THRIFT-5131
1222 for i in 0..64 {
1223 let (mut i_prot, mut o_prot) = test_objects();
1224 let val: i64 = ((1u64 << i) - 1) as i64;
1225
1226 o_prot
Allen George8a1743d2020-12-05 01:19:27 -05001227 .write_field_begin(&TFieldIdentifier::new("val", TType::I64, 1))
Nik Claytone7917602020-03-05 11:51:15 +01001228 .unwrap();
1229 o_prot.write_i64(val).unwrap();
1230 o_prot.write_field_end().unwrap();
1231 o_prot.flush().unwrap();
1232
1233 copy_write_buffer_to_read_buffer!(o_prot);
1234
1235 i_prot.read_field_begin().unwrap();
1236 assert_eq!(val, i_prot.read_i64().unwrap());
1237 }
1238 }
1239
1240 #[test]
Allen George8b96bfb2016-11-02 08:01:08 -04001241 fn must_round_trip_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -05001242 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001243
Allen George7ddbcc02020-11-08 09:51:19 -05001244 let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948);
Allen George8b96bfb2016-11-02 08:01:08 -04001245
1246 assert_success!(o_prot.write_message_begin(&ident));
1247
Allen George0e22c362017-01-30 07:15:00 -05001248 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001249
1250 let res = assert_success!(i_prot.read_message_begin());
1251 assert_eq!(&res, &ident);
1252 }
1253
1254 #[test]
1255 fn must_write_message_end() {
1256 assert_no_write(|o| o.write_message_end());
1257 }
1258
1259 // NOTE: structs and fields are tested together
1260 //
1261
1262 #[test]
1263 fn must_write_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001264 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001265
1266 // no bytes should be written however
1267 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1268
1269 // write three fields with tiny field ids
1270 // since they're small the field ids will be encoded as deltas
1271
1272 // since this is the first field (and it's zero) it gets the full varint write
1273 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
1274 assert_success!(o_prot.write_field_end());
1275
1276 // since this delta > 0 and < 15 it can be encoded as a delta
1277 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
1278 assert_success!(o_prot.write_field_end());
1279
1280 // since this delta > 0 and < 15 it can be encoded as a delta
1281 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
1282 assert_success!(o_prot.write_field_end());
1283
1284 // now, finish the struct off
1285 assert_success!(o_prot.write_field_stop());
1286 assert_success!(o_prot.write_struct_end());
1287
Allen George7ddbcc02020-11-08 09:51:19 -05001288 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001289 let expected: [u8; 5] = [
1290 0x03, /* field type */
1291 0x00, /* first field id */
1292 0x44, /* field delta (4) | field type */
1293 0x59, /* field delta (5) | field type */
1294 0x00 /* field stop */,
1295 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001296
Allen George0e22c362017-01-30 07:15:00 -05001297 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001298 }
1299
1300 #[test]
1301 fn must_round_trip_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001302 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001303
1304 // no bytes should be written however
1305 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1306
1307 // write three fields with tiny field ids
1308 // since they're small the field ids will be encoded as deltas
1309
1310 // since this is the first field (and it's zero) it gets the full varint write
1311 let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
1312 assert_success!(o_prot.write_field_begin(&field_ident_1));
1313 assert_success!(o_prot.write_field_end());
1314
1315 // since this delta > 0 and < 15 it can be encoded as a delta
1316 let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
1317 assert_success!(o_prot.write_field_begin(&field_ident_2));
1318 assert_success!(o_prot.write_field_end());
1319
1320 // since this delta > 0 and < 15 it can be encoded as a delta
1321 let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
1322 assert_success!(o_prot.write_field_begin(&field_ident_3));
1323 assert_success!(o_prot.write_field_end());
1324
1325 // now, finish the struct off
1326 assert_success!(o_prot.write_field_stop());
1327 assert_success!(o_prot.write_struct_end());
1328
Allen George0e22c362017-01-30 07:15:00 -05001329 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001330
1331 // read the struct back
1332 assert_success!(i_prot.read_struct_begin());
1333
1334 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001335 assert_eq!(
1336 read_ident_1,
1337 TFieldIdentifier {
1338 name: None,
1339 ..field_ident_1
1340 }
1341 );
Allen George8b96bfb2016-11-02 08:01:08 -04001342 assert_success!(i_prot.read_field_end());
1343
1344 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001345 assert_eq!(
1346 read_ident_2,
1347 TFieldIdentifier {
1348 name: None,
1349 ..field_ident_2
1350 }
1351 );
Allen George8b96bfb2016-11-02 08:01:08 -04001352 assert_success!(i_prot.read_field_end());
1353
1354 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001355 assert_eq!(
1356 read_ident_3,
1357 TFieldIdentifier {
1358 name: None,
1359 ..field_ident_3
1360 }
1361 );
Allen George8b96bfb2016-11-02 08:01:08 -04001362 assert_success!(i_prot.read_field_end());
1363
1364 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001365 assert_eq!(
1366 read_ident_4,
1367 TFieldIdentifier {
1368 name: None,
1369 field_type: TType::Stop,
1370 id: None,
1371 }
1372 );
Allen George8b96bfb2016-11-02 08:01:08 -04001373
1374 assert_success!(i_prot.read_struct_end());
1375 }
1376
1377 #[test]
1378 fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001379 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001380
1381 // no bytes should be written however
1382 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1383
1384 // write three fields with tiny field ids
1385 // since they're small the field ids will be encoded as deltas
1386
1387 // gets a delta write
1388 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
1389 assert_success!(o_prot.write_field_end());
1390
1391 // since this delta > 0 and < 15 it can be encoded as a delta
1392 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
1393 assert_success!(o_prot.write_field_end());
1394
1395 // since this delta > 0 and < 15 it can be encoded as a delta
1396 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
1397 assert_success!(o_prot.write_field_end());
1398
1399 // now, finish the struct off
1400 assert_success!(o_prot.write_field_stop());
1401 assert_success!(o_prot.write_struct_end());
1402
Allen George7ddbcc02020-11-08 09:51:19 -05001403 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001404 let expected: [u8; 4] = [
1405 0x15, /* field delta (1) | field type */
1406 0x1A, /* field delta (1) | field type */
1407 0x48, /* field delta (4) | field type */
1408 0x00 /* field stop */,
1409 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001410
Allen George0e22c362017-01-30 07:15:00 -05001411 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001412 }
1413
1414 #[test]
1415 fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001416 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001417
1418 // no bytes should be written however
1419 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1420
1421 // write three fields with tiny field ids
1422 // since they're small the field ids will be encoded as deltas
1423
1424 // gets a delta write
1425 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
1426 assert_success!(o_prot.write_field_begin(&field_ident_1));
1427 assert_success!(o_prot.write_field_end());
1428
1429 // since this delta > 0 and < 15 it can be encoded as a delta
1430 let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
1431 assert_success!(o_prot.write_field_begin(&field_ident_2));
1432 assert_success!(o_prot.write_field_end());
1433
1434 // since this delta > 0 and < 15 it can be encoded as a delta
1435 let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
1436 assert_success!(o_prot.write_field_begin(&field_ident_3));
1437 assert_success!(o_prot.write_field_end());
1438
1439 // now, finish the struct off
1440 assert_success!(o_prot.write_field_stop());
1441 assert_success!(o_prot.write_struct_end());
1442
Allen George0e22c362017-01-30 07:15:00 -05001443 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001444
1445 // read the struct back
1446 assert_success!(i_prot.read_struct_begin());
1447
1448 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001449 assert_eq!(
1450 read_ident_1,
1451 TFieldIdentifier {
1452 name: None,
1453 ..field_ident_1
1454 }
1455 );
Allen George8b96bfb2016-11-02 08:01:08 -04001456 assert_success!(i_prot.read_field_end());
1457
1458 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001459 assert_eq!(
1460 read_ident_2,
1461 TFieldIdentifier {
1462 name: None,
1463 ..field_ident_2
1464 }
1465 );
Allen George8b96bfb2016-11-02 08:01:08 -04001466 assert_success!(i_prot.read_field_end());
1467
1468 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001469 assert_eq!(
1470 read_ident_3,
1471 TFieldIdentifier {
1472 name: None,
1473 ..field_ident_3
1474 }
1475 );
Allen George8b96bfb2016-11-02 08:01:08 -04001476 assert_success!(i_prot.read_field_end());
1477
1478 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001479 assert_eq!(
1480 read_ident_4,
1481 TFieldIdentifier {
1482 name: None,
1483 field_type: TType::Stop,
1484 id: None,
1485 }
1486 );
Allen George8b96bfb2016-11-02 08:01:08 -04001487
1488 assert_success!(i_prot.read_struct_end());
1489 }
1490
1491 #[test]
1492 fn must_write_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001493 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001494
1495 // no bytes should be written however
1496 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1497
1498 // write three fields with field ids that cannot be encoded as deltas
1499
1500 // since this is the first field (and it's zero) it gets the full varint write
1501 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
1502 assert_success!(o_prot.write_field_end());
1503
1504 // since this delta is > 15 it is encoded as a zig-zag varint
1505 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
1506 assert_success!(o_prot.write_field_end());
1507
1508 // since this delta is > 15 it is encoded as a zig-zag varint
1509 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
1510 assert_success!(o_prot.write_field_end());
1511
1512 // now, finish the struct off
1513 assert_success!(o_prot.write_field_stop());
1514 assert_success!(o_prot.write_struct_end());
1515
Allen George7ddbcc02020-11-08 09:51:19 -05001516 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001517 let expected: [u8; 8] = [
1518 0x05, /* field type */
1519 0x00, /* first field id */
1520 0x06, /* field type */
1521 0x20, /* zig-zag varint field id */
1522 0x0A, /* field type */
1523 0xC6,
1524 0x01, /* zig-zag varint field id */
1525 0x00 /* field stop */,
1526 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001527
Allen George0e22c362017-01-30 07:15:00 -05001528 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001529 }
1530
1531 #[test]
1532 fn must_round_trip_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001533 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001534
1535 // no bytes should be written however
1536 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1537
1538 // write three fields with field ids that cannot be encoded as deltas
1539
1540 // since this is the first field (and it's zero) it gets the full varint write
1541 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
1542 assert_success!(o_prot.write_field_begin(&field_ident_1));
1543 assert_success!(o_prot.write_field_end());
1544
1545 // since this delta is > 15 it is encoded as a zig-zag varint
1546 let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
1547 assert_success!(o_prot.write_field_begin(&field_ident_2));
1548 assert_success!(o_prot.write_field_end());
1549
1550 // since this delta is > 15 it is encoded as a zig-zag varint
1551 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
1552 assert_success!(o_prot.write_field_begin(&field_ident_3));
1553 assert_success!(o_prot.write_field_end());
1554
1555 // now, finish the struct off
1556 assert_success!(o_prot.write_field_stop());
1557 assert_success!(o_prot.write_struct_end());
1558
Allen George0e22c362017-01-30 07:15:00 -05001559 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001560
1561 // read the struct back
1562 assert_success!(i_prot.read_struct_begin());
1563
1564 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001565 assert_eq!(
1566 read_ident_1,
1567 TFieldIdentifier {
1568 name: None,
1569 ..field_ident_1
1570 }
1571 );
Allen George8b96bfb2016-11-02 08:01:08 -04001572 assert_success!(i_prot.read_field_end());
1573
1574 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001575 assert_eq!(
1576 read_ident_2,
1577 TFieldIdentifier {
1578 name: None,
1579 ..field_ident_2
1580 }
1581 );
Allen George8b96bfb2016-11-02 08:01:08 -04001582 assert_success!(i_prot.read_field_end());
1583
1584 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001585 assert_eq!(
1586 read_ident_3,
1587 TFieldIdentifier {
1588 name: None,
1589 ..field_ident_3
1590 }
1591 );
Allen George8b96bfb2016-11-02 08:01:08 -04001592 assert_success!(i_prot.read_field_end());
1593
1594 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001595 assert_eq!(
1596 read_ident_4,
1597 TFieldIdentifier {
1598 name: None,
1599 field_type: TType::Stop,
1600 id: None,
1601 }
1602 );
Allen George8b96bfb2016-11-02 08:01:08 -04001603
1604 assert_success!(i_prot.read_struct_end());
1605 }
1606
1607 #[test]
1608 fn must_write_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001609 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001610
1611 // no bytes should be written however
1612 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1613
1614 // write three fields with field ids that cannot be encoded as deltas
1615
1616 // since the delta is > 0 and < 15 it gets a delta write
1617 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1618 assert_success!(o_prot.write_field_end());
1619
1620 // since this delta > 0 and < 15 it gets a delta write
1621 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1622 assert_success!(o_prot.write_field_end());
1623
1624 // since this delta is > 15 it is encoded as a zig-zag varint
1625 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
1626 assert_success!(o_prot.write_field_end());
1627
1628 // since this delta is > 15 it is encoded as a zig-zag varint
1629 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
1630 assert_success!(o_prot.write_field_end());
1631
1632 // since this is only 3 up from the previous it is recorded as a delta
1633 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
1634 assert_success!(o_prot.write_field_end());
1635
1636 // now, finish the struct off
1637 assert_success!(o_prot.write_field_stop());
1638 assert_success!(o_prot.write_struct_end());
1639
Allen George7ddbcc02020-11-08 09:51:19 -05001640 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001641 let expected: [u8; 10] = [
1642 0x16, /* field delta (1) | field type */
1643 0x85, /* field delta (8) | field type */
1644 0x0A, /* field type */
1645 0xD0,
1646 0x0F, /* zig-zag varint field id */
1647 0x0A, /* field type */
1648 0xA2,
1649 0x1F, /* zig-zag varint field id */
1650 0x3A, /* field delta (3) | field type */
1651 0x00 /* field stop */,
1652 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001653
Allen George0e22c362017-01-30 07:15:00 -05001654 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001655 }
1656
Allen George7ddbcc02020-11-08 09:51:19 -05001657 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001658 #[test]
1659 fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001660 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001661
1662 // no bytes should be written however
1663 let struct_ident = TStructIdentifier::new("foo");
1664 assert_success!(o_prot.write_struct_begin(&struct_ident));
1665
1666 // write three fields with field ids that cannot be encoded as deltas
1667
1668 // since the delta is > 0 and < 15 it gets a delta write
1669 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1670 assert_success!(o_prot.write_field_begin(&field_ident_1));
1671 assert_success!(o_prot.write_field_end());
1672
1673 // since this delta > 0 and < 15 it gets a delta write
1674 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1675 assert_success!(o_prot.write_field_begin(&field_ident_2));
1676 assert_success!(o_prot.write_field_end());
1677
1678 // since this delta is > 15 it is encoded as a zig-zag varint
1679 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
1680 assert_success!(o_prot.write_field_begin(&field_ident_3));
1681 assert_success!(o_prot.write_field_end());
1682
1683 // since this delta is > 15 it is encoded as a zig-zag varint
1684 let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
1685 assert_success!(o_prot.write_field_begin(&field_ident_4));
1686 assert_success!(o_prot.write_field_end());
1687
1688 // since this is only 3 up from the previous it is recorded as a delta
1689 let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
1690 assert_success!(o_prot.write_field_begin(&field_ident_5));
1691 assert_success!(o_prot.write_field_end());
1692
1693 // now, finish the struct off
1694 assert_success!(o_prot.write_field_stop());
1695 assert_success!(o_prot.write_struct_end());
1696
Allen George0e22c362017-01-30 07:15:00 -05001697 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001698
1699 // read the struct back
1700 assert_success!(i_prot.read_struct_begin());
1701
1702 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001703 assert_eq!(
1704 read_ident_1,
1705 TFieldIdentifier {
1706 name: None,
1707 ..field_ident_1
1708 }
1709 );
Allen George8b96bfb2016-11-02 08:01:08 -04001710 assert_success!(i_prot.read_field_end());
1711
1712 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001713 assert_eq!(
1714 read_ident_2,
1715 TFieldIdentifier {
1716 name: None,
1717 ..field_ident_2
1718 }
1719 );
Allen George8b96bfb2016-11-02 08:01:08 -04001720 assert_success!(i_prot.read_field_end());
1721
1722 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001723 assert_eq!(
1724 read_ident_3,
1725 TFieldIdentifier {
1726 name: None,
1727 ..field_ident_3
1728 }
1729 );
Allen George8b96bfb2016-11-02 08:01:08 -04001730 assert_success!(i_prot.read_field_end());
1731
1732 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001733 assert_eq!(
1734 read_ident_4,
1735 TFieldIdentifier {
1736 name: None,
1737 ..field_ident_4
1738 }
1739 );
Allen George8b96bfb2016-11-02 08:01:08 -04001740 assert_success!(i_prot.read_field_end());
1741
1742 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001743 assert_eq!(
1744 read_ident_5,
1745 TFieldIdentifier {
1746 name: None,
1747 ..field_ident_5
1748 }
1749 );
Allen George8b96bfb2016-11-02 08:01:08 -04001750 assert_success!(i_prot.read_field_end());
1751
1752 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001753 assert_eq!(
1754 read_ident_6,
1755 TFieldIdentifier {
1756 name: None,
1757 field_type: TType::Stop,
1758 id: None,
1759 }
1760 );
Allen George8b96bfb2016-11-02 08:01:08 -04001761
1762 assert_success!(i_prot.read_struct_end());
1763 }
1764
1765 #[test]
1766 fn must_write_nested_structs_0() {
1767 // last field of the containing struct is a delta
1768 // first field of the the contained struct is a delta
1769
Allen George0e22c362017-01-30 07:15:00 -05001770 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001771
1772 // start containing struct
1773 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1774
1775 // containing struct
1776 // since the delta is > 0 and < 15 it gets a delta write
1777 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1778 assert_success!(o_prot.write_field_end());
1779
1780 // containing struct
1781 // since this delta > 0 and < 15 it gets a delta write
1782 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1783 assert_success!(o_prot.write_field_end());
1784
1785 // start contained struct
1786 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1787
1788 // contained struct
1789 // since the delta is > 0 and < 15 it gets a delta write
1790 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
1791 assert_success!(o_prot.write_field_end());
1792
1793 // contained struct
1794 // since this delta > 15 it gets a full write
1795 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1796 assert_success!(o_prot.write_field_end());
1797
1798 // end contained struct
1799 assert_success!(o_prot.write_field_stop());
1800 assert_success!(o_prot.write_struct_end());
1801
1802 // end containing struct
1803 assert_success!(o_prot.write_field_stop());
1804 assert_success!(o_prot.write_struct_end());
1805
Allen George7ddbcc02020-11-08 09:51:19 -05001806 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001807 let expected: [u8; 7] = [
1808 0x16, /* field delta (1) | field type */
1809 0x85, /* field delta (8) | field type */
1810 0x73, /* field delta (7) | field type */
1811 0x07, /* field type */
1812 0x30, /* zig-zag varint field id */
1813 0x00, /* field stop - contained */
1814 0x00 /* field stop - containing */,
1815 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001816
Allen George0e22c362017-01-30 07:15:00 -05001817 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001818 }
1819
Allen George7ddbcc02020-11-08 09:51:19 -05001820 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001821 #[test]
1822 fn must_round_trip_nested_structs_0() {
1823 // last field of the containing struct is a delta
1824 // first field of the the contained struct is a delta
1825
Allen George0e22c362017-01-30 07:15:00 -05001826 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001827
1828 // start containing struct
1829 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1830
1831 // containing struct
1832 // since the delta is > 0 and < 15 it gets a delta write
1833 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1834 assert_success!(o_prot.write_field_begin(&field_ident_1));
1835 assert_success!(o_prot.write_field_end());
1836
1837 // containing struct
1838 // since this delta > 0 and < 15 it gets a delta write
1839 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1840 assert_success!(o_prot.write_field_begin(&field_ident_2));
1841 assert_success!(o_prot.write_field_end());
1842
1843 // start contained struct
1844 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1845
1846 // contained struct
1847 // since the delta is > 0 and < 15 it gets a delta write
1848 let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
1849 assert_success!(o_prot.write_field_begin(&field_ident_3));
1850 assert_success!(o_prot.write_field_end());
1851
1852 // contained struct
1853 // since this delta > 15 it gets a full write
1854 let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
1855 assert_success!(o_prot.write_field_begin(&field_ident_4));
1856 assert_success!(o_prot.write_field_end());
1857
1858 // end contained struct
1859 assert_success!(o_prot.write_field_stop());
1860 assert_success!(o_prot.write_struct_end());
1861
1862 // end containing struct
1863 assert_success!(o_prot.write_field_stop());
1864 assert_success!(o_prot.write_struct_end());
1865
Allen George0e22c362017-01-30 07:15:00 -05001866 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001867
1868 // read containing struct back
1869 assert_success!(i_prot.read_struct_begin());
1870
1871 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001872 assert_eq!(
1873 read_ident_1,
1874 TFieldIdentifier {
1875 name: None,
1876 ..field_ident_1
1877 }
1878 );
Allen George8b96bfb2016-11-02 08:01:08 -04001879 assert_success!(i_prot.read_field_end());
1880
1881 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001882 assert_eq!(
1883 read_ident_2,
1884 TFieldIdentifier {
1885 name: None,
1886 ..field_ident_2
1887 }
1888 );
Allen George8b96bfb2016-11-02 08:01:08 -04001889 assert_success!(i_prot.read_field_end());
1890
1891 // read contained struct back
1892 assert_success!(i_prot.read_struct_begin());
1893
1894 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001895 assert_eq!(
1896 read_ident_3,
1897 TFieldIdentifier {
1898 name: None,
1899 ..field_ident_3
1900 }
1901 );
Allen George8b96bfb2016-11-02 08:01:08 -04001902 assert_success!(i_prot.read_field_end());
1903
1904 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001905 assert_eq!(
1906 read_ident_4,
1907 TFieldIdentifier {
1908 name: None,
1909 ..field_ident_4
1910 }
1911 );
Allen George8b96bfb2016-11-02 08:01:08 -04001912 assert_success!(i_prot.read_field_end());
1913
1914 // end contained struct
1915 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001916 assert_eq!(
1917 read_ident_6,
1918 TFieldIdentifier {
1919 name: None,
1920 field_type: TType::Stop,
1921 id: None,
1922 }
1923 );
Allen George8b96bfb2016-11-02 08:01:08 -04001924 assert_success!(i_prot.read_struct_end());
1925
1926 // end containing struct
1927 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001928 assert_eq!(
1929 read_ident_7,
1930 TFieldIdentifier {
1931 name: None,
1932 field_type: TType::Stop,
1933 id: None,
1934 }
1935 );
Allen George8b96bfb2016-11-02 08:01:08 -04001936 assert_success!(i_prot.read_struct_end());
1937 }
1938
1939 #[test]
1940 fn must_write_nested_structs_1() {
1941 // last field of the containing struct is a delta
1942 // first field of the the contained struct is a full write
1943
Allen George0e22c362017-01-30 07:15:00 -05001944 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001945
1946 // start containing struct
1947 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1948
1949 // containing struct
1950 // since the delta is > 0 and < 15 it gets a delta write
1951 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1952 assert_success!(o_prot.write_field_end());
1953
1954 // containing struct
1955 // since this delta > 0 and < 15 it gets a delta write
1956 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1957 assert_success!(o_prot.write_field_end());
1958
1959 // start contained struct
1960 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1961
1962 // contained struct
1963 // since this delta > 15 it gets a full write
1964 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1965 assert_success!(o_prot.write_field_end());
1966
1967 // contained struct
1968 // since the delta is > 0 and < 15 it gets a delta write
1969 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1970 assert_success!(o_prot.write_field_end());
1971
1972 // end contained struct
1973 assert_success!(o_prot.write_field_stop());
1974 assert_success!(o_prot.write_struct_end());
1975
1976 // end containing struct
1977 assert_success!(o_prot.write_field_stop());
1978 assert_success!(o_prot.write_struct_end());
1979
Allen George7ddbcc02020-11-08 09:51:19 -05001980 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001981 let expected: [u8; 7] = [
1982 0x16, /* field delta (1) | field type */
1983 0x85, /* field delta (8) | field type */
1984 0x07, /* field type */
1985 0x30, /* zig-zag varint field id */
1986 0x33, /* field delta (3) | field type */
1987 0x00, /* field stop - contained */
1988 0x00 /* field stop - containing */,
1989 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001990
Allen George0e22c362017-01-30 07:15:00 -05001991 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001992 }
1993
Allen George7ddbcc02020-11-08 09:51:19 -05001994 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001995 #[test]
1996 fn must_round_trip_nested_structs_1() {
1997 // last field of the containing struct is a delta
1998 // first field of the the contained struct is a full write
1999
Allen George0e22c362017-01-30 07:15:00 -05002000 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002001
2002 // start containing struct
2003 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2004
2005 // containing struct
2006 // since the delta is > 0 and < 15 it gets a delta write
2007 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2008 assert_success!(o_prot.write_field_begin(&field_ident_1));
2009 assert_success!(o_prot.write_field_end());
2010
2011 // containing struct
2012 // since this delta > 0 and < 15 it gets a delta write
2013 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
2014 assert_success!(o_prot.write_field_begin(&field_ident_2));
2015 assert_success!(o_prot.write_field_end());
2016
2017 // start contained struct
2018 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2019
2020 // contained struct
2021 // since this delta > 15 it gets a full write
2022 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
2023 assert_success!(o_prot.write_field_begin(&field_ident_3));
2024 assert_success!(o_prot.write_field_end());
2025
2026 // contained struct
2027 // since the delta is > 0 and < 15 it gets a delta write
2028 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2029 assert_success!(o_prot.write_field_begin(&field_ident_4));
2030 assert_success!(o_prot.write_field_end());
2031
2032 // end contained struct
2033 assert_success!(o_prot.write_field_stop());
2034 assert_success!(o_prot.write_struct_end());
2035
2036 // end containing struct
2037 assert_success!(o_prot.write_field_stop());
2038 assert_success!(o_prot.write_struct_end());
2039
Allen George0e22c362017-01-30 07:15:00 -05002040 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002041
2042 // read containing struct back
2043 assert_success!(i_prot.read_struct_begin());
2044
2045 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002046 assert_eq!(
2047 read_ident_1,
2048 TFieldIdentifier {
2049 name: None,
2050 ..field_ident_1
2051 }
2052 );
Allen George8b96bfb2016-11-02 08:01:08 -04002053 assert_success!(i_prot.read_field_end());
2054
2055 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002056 assert_eq!(
2057 read_ident_2,
2058 TFieldIdentifier {
2059 name: None,
2060 ..field_ident_2
2061 }
2062 );
Allen George8b96bfb2016-11-02 08:01:08 -04002063 assert_success!(i_prot.read_field_end());
2064
2065 // read contained struct back
2066 assert_success!(i_prot.read_struct_begin());
2067
2068 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002069 assert_eq!(
2070 read_ident_3,
2071 TFieldIdentifier {
2072 name: None,
2073 ..field_ident_3
2074 }
2075 );
Allen George8b96bfb2016-11-02 08:01:08 -04002076 assert_success!(i_prot.read_field_end());
2077
2078 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002079 assert_eq!(
2080 read_ident_4,
2081 TFieldIdentifier {
2082 name: None,
2083 ..field_ident_4
2084 }
2085 );
Allen George8b96bfb2016-11-02 08:01:08 -04002086 assert_success!(i_prot.read_field_end());
2087
2088 // end contained struct
2089 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002090 assert_eq!(
2091 read_ident_6,
2092 TFieldIdentifier {
2093 name: None,
2094 field_type: TType::Stop,
2095 id: None,
2096 }
2097 );
Allen George8b96bfb2016-11-02 08:01:08 -04002098 assert_success!(i_prot.read_struct_end());
2099
2100 // end containing struct
2101 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002102 assert_eq!(
2103 read_ident_7,
2104 TFieldIdentifier {
2105 name: None,
2106 field_type: TType::Stop,
2107 id: None,
2108 }
2109 );
Allen George8b96bfb2016-11-02 08:01:08 -04002110 assert_success!(i_prot.read_struct_end());
2111 }
2112
2113 #[test]
2114 fn must_write_nested_structs_2() {
2115 // last field of the containing struct is a full write
2116 // first field of the the contained struct is a delta write
2117
Allen George0e22c362017-01-30 07:15:00 -05002118 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002119
2120 // start containing struct
2121 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2122
2123 // containing struct
2124 // since the delta is > 0 and < 15 it gets a delta write
2125 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2126 assert_success!(o_prot.write_field_end());
2127
2128 // containing struct
2129 // since this delta > 15 it gets a full write
2130 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2131 assert_success!(o_prot.write_field_end());
2132
2133 // start contained struct
2134 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2135
2136 // contained struct
2137 // since this delta > 0 and < 15 it gets a delta write
2138 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
2139 assert_success!(o_prot.write_field_end());
2140
2141 // contained struct
2142 // since the delta is > 0 and < 15 it gets a delta write
2143 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
2144 assert_success!(o_prot.write_field_end());
2145
2146 // end contained struct
2147 assert_success!(o_prot.write_field_stop());
2148 assert_success!(o_prot.write_struct_end());
2149
2150 // end containing struct
2151 assert_success!(o_prot.write_field_stop());
2152 assert_success!(o_prot.write_struct_end());
2153
Allen George7ddbcc02020-11-08 09:51:19 -05002154 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002155 let expected: [u8; 7] = [
2156 0x16, /* field delta (1) | field type */
2157 0x08, /* field type */
2158 0x2A, /* zig-zag varint field id */
2159 0x77, /* field delta(7) | field type */
2160 0x33, /* field delta (3) | field type */
2161 0x00, /* field stop - contained */
2162 0x00 /* field stop - containing */,
2163 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002164
Allen George0e22c362017-01-30 07:15:00 -05002165 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002166 }
2167
Allen George7ddbcc02020-11-08 09:51:19 -05002168 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002169 #[test]
2170 fn must_round_trip_nested_structs_2() {
Allen George0e22c362017-01-30 07:15:00 -05002171 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002172
2173 // start containing struct
2174 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2175
2176 // containing struct
2177 // since the delta is > 0 and < 15 it gets a delta write
2178 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2179 assert_success!(o_prot.write_field_begin(&field_ident_1));
2180 assert_success!(o_prot.write_field_end());
2181
2182 // containing struct
2183 // since this delta > 15 it gets a full write
2184 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2185 assert_success!(o_prot.write_field_begin(&field_ident_2));
2186 assert_success!(o_prot.write_field_end());
2187
2188 // start contained struct
2189 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2190
2191 // contained struct
2192 // since this delta > 0 and < 15 it gets a delta write
2193 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
2194 assert_success!(o_prot.write_field_begin(&field_ident_3));
2195 assert_success!(o_prot.write_field_end());
2196
2197 // contained struct
2198 // since the delta is > 0 and < 15 it gets a delta write
2199 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
2200 assert_success!(o_prot.write_field_begin(&field_ident_4));
2201 assert_success!(o_prot.write_field_end());
2202
2203 // end contained struct
2204 assert_success!(o_prot.write_field_stop());
2205 assert_success!(o_prot.write_struct_end());
2206
2207 // end containing struct
2208 assert_success!(o_prot.write_field_stop());
2209 assert_success!(o_prot.write_struct_end());
2210
Allen George0e22c362017-01-30 07:15:00 -05002211 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002212
2213 // read containing struct back
2214 assert_success!(i_prot.read_struct_begin());
2215
2216 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002217 assert_eq!(
2218 read_ident_1,
2219 TFieldIdentifier {
2220 name: None,
2221 ..field_ident_1
2222 }
2223 );
Allen George8b96bfb2016-11-02 08:01:08 -04002224 assert_success!(i_prot.read_field_end());
2225
2226 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002227 assert_eq!(
2228 read_ident_2,
2229 TFieldIdentifier {
2230 name: None,
2231 ..field_ident_2
2232 }
2233 );
Allen George8b96bfb2016-11-02 08:01:08 -04002234 assert_success!(i_prot.read_field_end());
2235
2236 // read contained struct back
2237 assert_success!(i_prot.read_struct_begin());
2238
2239 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002240 assert_eq!(
2241 read_ident_3,
2242 TFieldIdentifier {
2243 name: None,
2244 ..field_ident_3
2245 }
2246 );
Allen George8b96bfb2016-11-02 08:01:08 -04002247 assert_success!(i_prot.read_field_end());
2248
2249 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002250 assert_eq!(
2251 read_ident_4,
2252 TFieldIdentifier {
2253 name: None,
2254 ..field_ident_4
2255 }
2256 );
Allen George8b96bfb2016-11-02 08:01:08 -04002257 assert_success!(i_prot.read_field_end());
2258
2259 // end contained struct
2260 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002261 assert_eq!(
2262 read_ident_6,
2263 TFieldIdentifier {
2264 name: None,
2265 field_type: TType::Stop,
2266 id: None,
2267 }
2268 );
Allen George8b96bfb2016-11-02 08:01:08 -04002269 assert_success!(i_prot.read_struct_end());
2270
2271 // end containing struct
2272 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002273 assert_eq!(
2274 read_ident_7,
2275 TFieldIdentifier {
2276 name: None,
2277 field_type: TType::Stop,
2278 id: None,
2279 }
2280 );
Allen George8b96bfb2016-11-02 08:01:08 -04002281 assert_success!(i_prot.read_struct_end());
2282 }
2283
2284 #[test]
2285 fn must_write_nested_structs_3() {
2286 // last field of the containing struct is a full write
2287 // first field of the the contained struct is a full write
2288
Allen George0e22c362017-01-30 07:15:00 -05002289 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002290
2291 // start containing struct
2292 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2293
2294 // containing struct
2295 // since the delta is > 0 and < 15 it gets a delta write
2296 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2297 assert_success!(o_prot.write_field_end());
2298
2299 // containing struct
2300 // since this delta > 15 it gets a full write
2301 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2302 assert_success!(o_prot.write_field_end());
2303
2304 // start contained struct
2305 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2306
2307 // contained struct
2308 // since this delta > 15 it gets a full write
2309 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
2310 assert_success!(o_prot.write_field_end());
2311
2312 // contained struct
2313 // since the delta is > 0 and < 15 it gets a delta write
2314 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
2315 assert_success!(o_prot.write_field_end());
2316
2317 // end contained struct
2318 assert_success!(o_prot.write_field_stop());
2319 assert_success!(o_prot.write_struct_end());
2320
2321 // end containing struct
2322 assert_success!(o_prot.write_field_stop());
2323 assert_success!(o_prot.write_struct_end());
2324
Allen George7ddbcc02020-11-08 09:51:19 -05002325 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002326 let expected: [u8; 8] = [
2327 0x16, /* field delta (1) | field type */
2328 0x08, /* field type */
2329 0x2A, /* zig-zag varint field id */
2330 0x07, /* field type */
2331 0x2A, /* zig-zag varint field id */
2332 0x63, /* field delta (6) | field type */
2333 0x00, /* field stop - contained */
2334 0x00 /* field stop - containing */,
2335 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002336
Allen George0e22c362017-01-30 07:15:00 -05002337 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002338 }
2339
Allen George7ddbcc02020-11-08 09:51:19 -05002340 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002341 #[test]
2342 fn must_round_trip_nested_structs_3() {
2343 // last field of the containing struct is a full write
2344 // first field of the the contained struct is a full write
2345
Allen George0e22c362017-01-30 07:15:00 -05002346 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002347
2348 // start containing struct
2349 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2350
2351 // containing struct
2352 // since the delta is > 0 and < 15 it gets a delta write
2353 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2354 assert_success!(o_prot.write_field_begin(&field_ident_1));
2355 assert_success!(o_prot.write_field_end());
2356
2357 // containing struct
2358 // since this delta > 15 it gets a full write
2359 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2360 assert_success!(o_prot.write_field_begin(&field_ident_2));
2361 assert_success!(o_prot.write_field_end());
2362
2363 // start contained struct
2364 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2365
2366 // contained struct
2367 // since this delta > 15 it gets a full write
2368 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
2369 assert_success!(o_prot.write_field_begin(&field_ident_3));
2370 assert_success!(o_prot.write_field_end());
2371
2372 // contained struct
2373 // since the delta is > 0 and < 15 it gets a delta write
2374 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2375 assert_success!(o_prot.write_field_begin(&field_ident_4));
2376 assert_success!(o_prot.write_field_end());
2377
2378 // end contained struct
2379 assert_success!(o_prot.write_field_stop());
2380 assert_success!(o_prot.write_struct_end());
2381
2382 // end containing struct
2383 assert_success!(o_prot.write_field_stop());
2384 assert_success!(o_prot.write_struct_end());
2385
Allen George0e22c362017-01-30 07:15:00 -05002386 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002387
2388 // read containing struct back
2389 assert_success!(i_prot.read_struct_begin());
2390
2391 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002392 assert_eq!(
2393 read_ident_1,
2394 TFieldIdentifier {
2395 name: None,
2396 ..field_ident_1
2397 }
2398 );
Allen George8b96bfb2016-11-02 08:01:08 -04002399 assert_success!(i_prot.read_field_end());
2400
2401 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002402 assert_eq!(
2403 read_ident_2,
2404 TFieldIdentifier {
2405 name: None,
2406 ..field_ident_2
2407 }
2408 );
Allen George8b96bfb2016-11-02 08:01:08 -04002409 assert_success!(i_prot.read_field_end());
2410
2411 // read contained struct back
2412 assert_success!(i_prot.read_struct_begin());
2413
2414 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002415 assert_eq!(
2416 read_ident_3,
2417 TFieldIdentifier {
2418 name: None,
2419 ..field_ident_3
2420 }
2421 );
Allen George8b96bfb2016-11-02 08:01:08 -04002422 assert_success!(i_prot.read_field_end());
2423
2424 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002425 assert_eq!(
2426 read_ident_4,
2427 TFieldIdentifier {
2428 name: None,
2429 ..field_ident_4
2430 }
2431 );
Allen George8b96bfb2016-11-02 08:01:08 -04002432 assert_success!(i_prot.read_field_end());
2433
2434 // end contained struct
2435 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002436 assert_eq!(
2437 read_ident_6,
2438 TFieldIdentifier {
2439 name: None,
2440 field_type: TType::Stop,
2441 id: None,
2442 }
2443 );
Allen George8b96bfb2016-11-02 08:01:08 -04002444 assert_success!(i_prot.read_struct_end());
2445
2446 // end containing struct
2447 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002448 assert_eq!(
2449 read_ident_7,
2450 TFieldIdentifier {
2451 name: None,
2452 field_type: TType::Stop,
2453 id: None,
2454 }
2455 );
Allen George8b96bfb2016-11-02 08:01:08 -04002456 assert_success!(i_prot.read_struct_end());
2457 }
2458
2459 #[test]
2460 fn must_write_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002461 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002462
2463 // no bytes should be written however
2464 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2465
2466 // write three fields with field ids that cannot be encoded as deltas
2467
2468 // since the delta is > 0 and < 16 it gets a delta write
2469 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2470 assert_success!(o_prot.write_bool(true));
2471 assert_success!(o_prot.write_field_end());
2472
2473 // since this delta > 0 and < 15 it gets a delta write
2474 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
2475 assert_success!(o_prot.write_bool(false));
2476 assert_success!(o_prot.write_field_end());
2477
2478 // since this delta > 15 it gets a full write
2479 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
2480 assert_success!(o_prot.write_bool(true));
2481 assert_success!(o_prot.write_field_end());
2482
2483 // since this delta > 15 it gets a full write
2484 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
2485 assert_success!(o_prot.write_bool(false));
2486 assert_success!(o_prot.write_field_end());
2487
2488 // now, finish the struct off
2489 assert_success!(o_prot.write_field_stop());
2490 assert_success!(o_prot.write_struct_end());
2491
Allen George7ddbcc02020-11-08 09:51:19 -05002492 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002493 let expected: [u8; 7] = [
2494 0x11, /* field delta (1) | true */
2495 0x82, /* field delta (8) | false */
2496 0x01, /* true */
2497 0x34, /* field id */
2498 0x02, /* false */
2499 0x5A, /* field id */
2500 0x00 /* stop field */,
2501 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002502
Allen George0e22c362017-01-30 07:15:00 -05002503 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002504 }
2505
Allen George7ddbcc02020-11-08 09:51:19 -05002506 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002507 #[test]
2508 fn must_round_trip_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002509 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002510
2511 // no bytes should be written however
2512 let struct_ident = TStructIdentifier::new("foo");
2513 assert_success!(o_prot.write_struct_begin(&struct_ident));
2514
2515 // write two fields
2516
2517 // since the delta is > 0 and < 16 it gets a delta write
2518 let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
2519 assert_success!(o_prot.write_field_begin(&field_ident_1));
2520 assert_success!(o_prot.write_bool(true));
2521 assert_success!(o_prot.write_field_end());
2522
2523 // since this delta > 0 and < 15 it gets a delta write
2524 let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
2525 assert_success!(o_prot.write_field_begin(&field_ident_2));
2526 assert_success!(o_prot.write_bool(false));
2527 assert_success!(o_prot.write_field_end());
2528
2529 // since this delta > 15 it gets a full write
2530 let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
2531 assert_success!(o_prot.write_field_begin(&field_ident_3));
2532 assert_success!(o_prot.write_bool(true));
2533 assert_success!(o_prot.write_field_end());
2534
2535 // since this delta > 15 it gets a full write
2536 let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
2537 assert_success!(o_prot.write_field_begin(&field_ident_4));
2538 assert_success!(o_prot.write_bool(false));
2539 assert_success!(o_prot.write_field_end());
2540
2541 // now, finish the struct off
2542 assert_success!(o_prot.write_field_stop());
2543 assert_success!(o_prot.write_struct_end());
2544
Allen George0e22c362017-01-30 07:15:00 -05002545 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002546
2547 // read the struct back
2548 assert_success!(i_prot.read_struct_begin());
2549
2550 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002551 assert_eq!(
2552 read_ident_1,
2553 TFieldIdentifier {
2554 name: None,
2555 ..field_ident_1
2556 }
2557 );
Allen George8b96bfb2016-11-02 08:01:08 -04002558 let read_value_1 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002559 assert!(read_value_1);
Allen George8b96bfb2016-11-02 08:01:08 -04002560 assert_success!(i_prot.read_field_end());
2561
2562 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002563 assert_eq!(
2564 read_ident_2,
2565 TFieldIdentifier {
2566 name: None,
2567 ..field_ident_2
2568 }
2569 );
Allen George8b96bfb2016-11-02 08:01:08 -04002570 let read_value_2 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002571 assert!(!read_value_2);
Allen George8b96bfb2016-11-02 08:01:08 -04002572 assert_success!(i_prot.read_field_end());
2573
2574 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002575 assert_eq!(
2576 read_ident_3,
2577 TFieldIdentifier {
2578 name: None,
2579 ..field_ident_3
2580 }
2581 );
Allen George8b96bfb2016-11-02 08:01:08 -04002582 let read_value_3 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002583 assert!(read_value_3);
Allen George8b96bfb2016-11-02 08:01:08 -04002584 assert_success!(i_prot.read_field_end());
2585
2586 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002587 assert_eq!(
2588 read_ident_4,
2589 TFieldIdentifier {
2590 name: None,
2591 ..field_ident_4
2592 }
2593 );
Allen George8b96bfb2016-11-02 08:01:08 -04002594 let read_value_4 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002595 assert!(!read_value_4);
Allen George8b96bfb2016-11-02 08:01:08 -04002596 assert_success!(i_prot.read_field_end());
2597
2598 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002599 assert_eq!(
2600 read_ident_5,
2601 TFieldIdentifier {
2602 name: None,
2603 field_type: TType::Stop,
2604 id: None,
2605 }
2606 );
Allen George8b96bfb2016-11-02 08:01:08 -04002607
2608 assert_success!(i_prot.read_struct_end());
2609 }
2610
2611 #[test]
2612 #[should_panic]
2613 fn must_fail_if_write_field_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002614 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002615 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2616 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2617 o_prot.write_field_end().unwrap();
2618 }
2619
2620 #[test]
2621 #[should_panic]
2622 fn must_fail_if_write_stop_field_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002623 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002624 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2625 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2626 o_prot.write_field_stop().unwrap();
2627 }
2628
2629 #[test]
2630 #[should_panic]
2631 fn must_fail_if_write_struct_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002632 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002633 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2634 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2635 o_prot.write_struct_end().unwrap();
2636 }
2637
2638 #[test]
2639 #[should_panic]
2640 fn must_fail_if_write_struct_end_without_any_fields() {
Allen George0e22c362017-01-30 07:15:00 -05002641 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002642 o_prot.write_struct_end().unwrap();
2643 }
2644
2645 #[test]
2646 fn must_write_field_end() {
2647 assert_no_write(|o| o.write_field_end());
2648 }
2649
2650 #[test]
2651 fn must_write_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002652 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002653
2654 assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
2655
2656 let expected: [u8; 1] = [0x46 /* size | elem_type */];
2657
Allen George0e22c362017-01-30 07:15:00 -05002658 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002659 }
2660
2661 #[test]
2662 fn must_round_trip_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002663 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002664
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002665 let ident = TListIdentifier::new(TType::I32, 3);
Allen George8b96bfb2016-11-02 08:01:08 -04002666 assert_success!(o_prot.write_list_begin(&ident));
2667
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002668 assert_success!(o_prot.write_i32(100));
2669 assert_success!(o_prot.write_i32(200));
2670 assert_success!(o_prot.write_i32(300));
2671
2672 assert_success!(o_prot.write_list_end());
2673
Allen George0e22c362017-01-30 07:15:00 -05002674 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002675
2676 let res = assert_success!(i_prot.read_list_begin());
2677 assert_eq!(&res, &ident);
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002678
2679 assert_eq!(i_prot.read_i32().unwrap(), 100);
2680 assert_eq!(i_prot.read_i32().unwrap(), 200);
2681 assert_eq!(i_prot.read_i32().unwrap(), 300);
2682
2683 assert_success!(i_prot.read_list_end());
Allen George8b96bfb2016-11-02 08:01:08 -04002684 }
2685
2686 #[test]
2687 fn must_write_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002688 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002689
2690 let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
2691 assert!(res.is_ok());
2692
Allen George0e22c362017-01-30 07:15:00 -05002693 let expected: [u8; 3] = [
2694 0xF9, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002695 0x8F, 0x4E, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002696 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002697
Allen George0e22c362017-01-30 07:15:00 -05002698 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002699 }
2700
2701 #[test]
2702 fn must_round_trip_large_sized_list_begin() {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002703 let (mut i_prot, mut o_prot) = test_objects_no_limits();
Allen George8b96bfb2016-11-02 08:01:08 -04002704
2705 let ident = TListIdentifier::new(TType::Set, 47381);
Allen George8b96bfb2016-11-02 08:01:08 -04002706 assert_success!(o_prot.write_list_begin(&ident));
2707
Allen George0e22c362017-01-30 07:15:00 -05002708 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002709
2710 let res = assert_success!(i_prot.read_list_begin());
2711 assert_eq!(&res, &ident);
2712 }
2713
2714 #[test]
2715 fn must_write_list_end() {
2716 assert_no_write(|o| o.write_list_end());
2717 }
2718
2719 #[test]
2720 fn must_write_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002721 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002722
2723 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
2724
2725 let expected: [u8; 1] = [0x2C /* size | elem_type */];
2726
Allen George0e22c362017-01-30 07:15:00 -05002727 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002728 }
2729
2730 #[test]
2731 fn must_round_trip_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002732 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002733
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002734 let ident = TSetIdentifier::new(TType::I16, 3);
Allen George8b96bfb2016-11-02 08:01:08 -04002735 assert_success!(o_prot.write_set_begin(&ident));
2736
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002737 assert_success!(o_prot.write_i16(111));
2738 assert_success!(o_prot.write_i16(222));
2739 assert_success!(o_prot.write_i16(333));
2740
2741 assert_success!(o_prot.write_set_end());
2742
Allen George0e22c362017-01-30 07:15:00 -05002743 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002744
2745 let res = assert_success!(i_prot.read_set_begin());
2746 assert_eq!(&res, &ident);
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002747
2748 assert_eq!(i_prot.read_i16().unwrap(), 111);
2749 assert_eq!(i_prot.read_i16().unwrap(), 222);
2750 assert_eq!(i_prot.read_i16().unwrap(), 333);
2751
2752 assert_success!(i_prot.read_set_end());
Allen George8b96bfb2016-11-02 08:01:08 -04002753 }
2754
2755 #[test]
2756 fn must_write_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002757 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002758
2759 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
2760
Allen George0e22c362017-01-30 07:15:00 -05002761 let expected: [u8; 4] = [
2762 0xF7, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002763 0xD3, 0xBA, 0x01, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002764 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002765
Allen George0e22c362017-01-30 07:15:00 -05002766 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002767 }
2768
2769 #[test]
2770 fn must_round_trip_large_sized_set_begin() {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002771 let (mut i_prot, mut o_prot) = test_objects_no_limits();
Allen George8b96bfb2016-11-02 08:01:08 -04002772
Allen George7ddbcc02020-11-08 09:51:19 -05002773 let ident = TSetIdentifier::new(TType::Map, 3_928_429);
Allen George8b96bfb2016-11-02 08:01:08 -04002774 assert_success!(o_prot.write_set_begin(&ident));
2775
Allen George0e22c362017-01-30 07:15:00 -05002776 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002777
2778 let res = assert_success!(i_prot.read_set_begin());
2779 assert_eq!(&res, &ident);
2780 }
2781
2782 #[test]
2783 fn must_write_set_end() {
2784 assert_no_write(|o| o.write_set_end());
2785 }
2786
2787 #[test]
2788 fn must_write_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002789 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002790
2791 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
2792
2793 let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything
2794
Allen George0e22c362017-01-30 07:15:00 -05002795 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002796 }
2797
2798 #[test]
2799 fn must_read_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002800 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002801
2802 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
2803
Allen George0e22c362017-01-30 07:15:00 -05002804 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002805
2806 let res = assert_success!(i_prot.read_map_begin());
Allen George0e22c362017-01-30 07:15:00 -05002807 assert_eq!(
2808 &res,
2809 &TMapIdentifier {
Allen Georgeef7a1892018-12-16 18:01:37 -05002810 key_type: None,
2811 value_type: None,
2812 size: 0,
2813 }
Allen George0e22c362017-01-30 07:15:00 -05002814 );
Allen George8b96bfb2016-11-02 08:01:08 -04002815 }
2816
2817 #[test]
2818 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002819 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002820
Allen Georgeef7a1892018-12-16 18:01:37 -05002821 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
2822 TType::Double,
2823 TType::String,
2824 238
2825 )));
Allen George8b96bfb2016-11-02 08:01:08 -04002826
Allen George0e22c362017-01-30 07:15:00 -05002827 let expected: [u8; 3] = [
Allen Georgeef7a1892018-12-16 18:01:37 -05002828 0xEE, 0x01, /* size as varint */
2829 0x78, /* key type | val type */
Allen George0e22c362017-01-30 07:15:00 -05002830 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002831
Allen George0e22c362017-01-30 07:15:00 -05002832 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002833 }
2834
2835 #[test]
2836 fn must_round_trip_map_begin() {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002837 let (mut i_prot, mut o_prot) = test_objects_no_limits();
Allen George8b96bfb2016-11-02 08:01:08 -04002838
Allen George7ddbcc02020-11-08 09:51:19 -05002839 let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349);
Allen George8b96bfb2016-11-02 08:01:08 -04002840 assert_success!(o_prot.write_map_begin(&ident));
2841
Allen George0e22c362017-01-30 07:15:00 -05002842 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002843
2844 let res = assert_success!(i_prot.read_map_begin());
2845 assert_eq!(&res, &ident);
2846 }
2847
2848 #[test]
2849 fn must_write_map_end() {
2850 assert_no_write(|o| o.write_map_end());
2851 }
2852
2853 #[test]
2854 fn must_write_map_with_bool_key_and_value() {
Allen George0e22c362017-01-30 07:15:00 -05002855 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002856
2857 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
2858 assert_success!(o_prot.write_bool(true));
2859 assert_success!(o_prot.write_bool(false));
2860 assert_success!(o_prot.write_map_end());
2861
Allen George0e22c362017-01-30 07:15:00 -05002862 let expected: [u8; 4] = [
2863 0x01, /* size as varint */
2864 0x11, /* key type | val type */
2865 0x01, /* key: true */
Allen Georgeef7a1892018-12-16 18:01:37 -05002866 0x02, /* val: false */
Allen George0e22c362017-01-30 07:15:00 -05002867 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002868
Allen George0e22c362017-01-30 07:15:00 -05002869 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002870 }
2871
2872 #[test]
2873 fn must_round_trip_map_with_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002874 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002875
2876 let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
2877 assert_success!(o_prot.write_map_begin(&map_ident));
2878 assert_success!(o_prot.write_bool(true));
2879 assert_success!(o_prot.write_bool(false));
2880 assert_success!(o_prot.write_bool(false));
2881 assert_success!(o_prot.write_bool(true));
2882 assert_success!(o_prot.write_map_end());
2883
Allen George0e22c362017-01-30 07:15:00 -05002884 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002885
2886 // map header
2887 let rcvd_ident = assert_success!(i_prot.read_map_begin());
2888 assert_eq!(&rcvd_ident, &map_ident);
2889 // key 1
2890 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002891 assert!(b);
Allen George8b96bfb2016-11-02 08:01:08 -04002892 // val 1
2893 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002894 assert!(!b);
Allen George8b96bfb2016-11-02 08:01:08 -04002895 // key 2
2896 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002897 assert!(!b);
Allen George8b96bfb2016-11-02 08:01:08 -04002898 // val 2
2899 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002900 assert!(b);
Allen George8b96bfb2016-11-02 08:01:08 -04002901 // map end
2902 assert_success!(i_prot.read_map_end());
2903 }
2904
2905 #[test]
2906 fn must_read_map_end() {
Allen George0e22c362017-01-30 07:15:00 -05002907 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002908 assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
2909 }
2910
Allen Georgeef7a1892018-12-16 18:01:37 -05002911 fn test_objects() -> (
2912 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2913 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2914 ) {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002915 let mem = TBufferChannel::with_capacity(200, 200);
Allen George8b96bfb2016-11-02 08:01:08 -04002916
Allen George0e22c362017-01-30 07:15:00 -05002917 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -04002918
Allen George0e22c362017-01-30 07:15:00 -05002919 let i_prot = TCompactInputProtocol::new(r_mem);
2920 let o_prot = TCompactOutputProtocol::new(w_mem);
Allen George8b96bfb2016-11-02 08:01:08 -04002921
Allen George0e22c362017-01-30 07:15:00 -05002922 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -04002923 }
2924
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002925 fn test_objects_no_limits() -> (
2926 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2927 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2928 ) {
2929 let mem = TBufferChannel::with_capacity(200, 200);
2930
2931 let (r_mem, w_mem) = mem.split().unwrap();
2932
2933 let i_prot = TCompactInputProtocol::with_config(r_mem, TConfiguration::no_limits());
2934 let o_prot = TCompactOutputProtocol::new(w_mem);
2935
2936 (i_prot, o_prot)
2937 }
2938
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002939 #[test]
2940 fn must_read_write_double() {
2941 let (mut i_prot, mut o_prot) = test_objects();
2942
Allen George7ddbcc02020-11-08 09:51:19 -05002943 #[allow(clippy::approx_constant)]
2944 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002945 o_prot.write_double(double).unwrap();
2946 copy_write_buffer_to_read_buffer!(o_prot);
2947
Allen George7ddbcc02020-11-08 09:51:19 -05002948 let read_double = i_prot.read_double().unwrap();
Cameron Martinda54fc82025-01-12 08:55:45 +00002949 assert!((read_double - double).abs() < f64::EPSILON);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002950 }
2951
2952 #[test]
2953 fn must_encode_double_as_other_langs() {
2954 let (_, mut o_prot) = test_objects();
2955 let expected = [24, 45, 68, 84, 251, 33, 9, 64];
2956
Allen George7ddbcc02020-11-08 09:51:19 -05002957 #[allow(clippy::approx_constant)]
2958 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002959 o_prot.write_double(double).unwrap();
2960
2961 assert_eq_written_bytes!(o_prot, expected);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002962 }
2963
Allen George0e22c362017-01-30 07:15:00 -05002964 fn assert_no_write<F>(mut write_fn: F)
2965 where
Allen Georgeb0d14132020-03-29 11:48:55 -04002966 F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> crate::Result<()>,
Allen George0e22c362017-01-30 07:15:00 -05002967 {
2968 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002969 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -05002970 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -04002971 }
Jörn Horstmann717bd792025-02-02 23:10:27 +01002972
2973 #[test]
2974 fn must_read_boolean_list() {
2975 let (mut i_prot, _) = test_objects();
2976
2977 let source_bytes: [u8; 3] = [0x21, 2, 1];
2978
2979 i_prot.transport.set_readable_bytes(&source_bytes);
2980
2981 let (ttype, element_count) = assert_success!(i_prot.read_list_set_begin());
2982
2983 assert_eq!(ttype, TType::Bool);
2984 assert_eq!(element_count, 2);
2985 assert_eq!(i_prot.read_bool().unwrap(), false);
2986 assert_eq!(i_prot.read_bool().unwrap(), true);
2987
2988 assert_success!(i_prot.read_list_end());
2989 }
2990
2991 #[test]
2992 fn must_read_boolean_list_alternative_encoding() {
2993 let (mut i_prot, _) = test_objects();
2994
2995 let source_bytes: [u8; 3] = [0x22, 0, 1];
2996
2997 i_prot.transport.set_readable_bytes(&source_bytes);
2998
2999 let (ttype, element_count) = assert_success!(i_prot.read_list_set_begin());
3000
3001 assert_eq!(ttype, TType::Bool);
3002 assert_eq!(element_count, 2);
3003 assert_eq!(i_prot.read_bool().unwrap(), false);
3004 assert_eq!(i_prot.read_bool().unwrap(), true);
3005
3006 assert_success!(i_prot.read_list_end());
3007 }
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07003008
3009 #[test]
3010 fn must_enforce_recursion_depth_limit() {
3011 let channel = TBufferChannel::with_capacity(100, 100);
3012
3013 // Create a configuration with a small recursion limit
3014 let config = TConfiguration::builder()
3015 .max_recursion_depth(Some(2))
3016 .build()
3017 .unwrap();
3018
3019 let mut protocol = TCompactInputProtocol::with_config(channel, config);
3020
3021 // First struct - should succeed
3022 assert!(protocol.read_struct_begin().is_ok());
3023
3024 // Second struct - should succeed (at limit)
3025 assert!(protocol.read_struct_begin().is_ok());
3026
3027 // Third struct - should fail (exceeds limit)
3028 let result = protocol.read_struct_begin();
3029 assert!(result.is_err());
3030 match result {
3031 Err(crate::Error::Protocol(e)) => {
3032 assert_eq!(e.kind, ProtocolErrorKind::DepthLimit);
3033 }
3034 _ => panic!("Expected protocol error with DepthLimit"),
3035 }
3036 }
3037
3038 #[test]
3039 fn must_check_container_size_overflow() {
3040 // Configure a small message size limit
3041 let config = TConfiguration::builder()
3042 .max_message_size(Some(1000))
3043 .max_frame_size(Some(1000))
3044 .build()
3045 .unwrap();
3046 let transport = TBufferChannel::with_capacity(100, 0);
3047 let mut i_prot = TCompactInputProtocol::with_config(transport, config);
3048
3049 // Write a list header that would require more memory than message size limit
3050 // List of 100 UUIDs (16 bytes each) = 1600 bytes > 1000 limit
3051 i_prot.transport.set_readable_bytes(&[
3052 0xFD, // element type UUID (0x0D) | count in next bytes (0xF0)
3053 0x64, // varint 100
3054 ]);
3055
3056 let result = i_prot.read_list_begin();
3057 assert!(result.is_err());
3058 match result {
3059 Err(crate::Error::Protocol(e)) => {
3060 assert_eq!(e.kind, ProtocolErrorKind::SizeLimit);
3061 assert!(e
3062 .message
3063 .contains("1600 bytes, exceeding message size limit of 1000"));
3064 }
3065 _ => panic!("Expected protocol error with SizeLimit"),
3066 }
3067 }
3068
3069 #[test]
3070 fn must_reject_negative_container_sizes() {
3071 let mut channel = TBufferChannel::with_capacity(100, 100);
3072
3073 let mut protocol = TCompactInputProtocol::new(channel.clone());
3074
3075 // Write header with negative size when decoded
3076 // In compact protocol, lists/sets use a header byte followed by size
3077 // We'll use 0x0F for element type and then a varint-encoded negative number
3078 channel.set_readable_bytes(&[
3079 0xF0, // Header: 15 in upper nibble (triggers varint read), List type in lower
3080 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, // Varint encoding of -1
3081 ]);
3082
3083 let result = protocol.read_list_begin();
3084 assert!(result.is_err());
3085 match result {
3086 Err(crate::Error::Protocol(e)) => {
3087 assert_eq!(e.kind, ProtocolErrorKind::NegativeSize);
3088 }
3089 _ => panic!("Expected protocol error with NegativeSize"),
3090 }
3091 }
3092
3093 #[test]
3094 fn must_enforce_container_size_limit() {
3095 let channel = TBufferChannel::with_capacity(100, 100);
3096 let (r_channel, mut w_channel) = channel.split().unwrap();
3097
3098 // Create protocol with explicit container size limit
3099 let config = TConfiguration::builder()
3100 .max_container_size(Some(1000))
3101 .build()
3102 .unwrap();
3103 let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3104
3105 // Write header with large size
3106 // Compact protocol: 0xF0 means size >= 15 is encoded as varint
3107 // Then we write a varint encoding 10000 (exceeds our limit of 1000)
3108 w_channel.set_readable_bytes(&[
3109 0xF0, // Header: 15 in upper nibble (triggers varint read), element type in lower
3110 0x90, 0x4E, // Varint encoding of 10000
3111 ]);
3112
3113 let result = protocol.read_list_begin();
3114 assert!(result.is_err());
3115 match result {
3116 Err(crate::Error::Protocol(e)) => {
3117 assert_eq!(e.kind, ProtocolErrorKind::SizeLimit);
3118 assert!(e.message.contains("exceeds maximum allowed size"));
3119 }
3120 _ => panic!("Expected protocol error with SizeLimit"),
3121 }
3122 }
3123
3124 #[test]
3125 fn must_handle_varint_size_overflow() {
3126 // Test that compact protocol properly handles varint-encoded sizes that would cause overflow
3127 let mut channel = TBufferChannel::with_capacity(100, 100);
3128
3129 let mut protocol = TCompactInputProtocol::new(channel.clone());
3130
3131 // Create input that encodes a very large size using varint encoding
3132 // 0xFA = list header with size >= 15 (so size follows as varint)
3133 // Then multiple 0xFF bytes which in varint encoding create a very large number
3134 channel.set_readable_bytes(&[
3135 0xFA, // List header: size >= 15, element type = 0x0A
3136 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, // Varint encoding of a huge number
3137 ]);
3138
3139 let result = protocol.read_list_begin();
3140 assert!(result.is_err());
3141 match result {
3142 Err(crate::Error::Protocol(e)) => {
3143 // The varint decoder might interpret this as negative, which is also fine
3144 assert!(
3145 e.kind == ProtocolErrorKind::SizeLimit
3146 || e.kind == ProtocolErrorKind::NegativeSize,
3147 "Expected SizeLimit or NegativeSize but got {:?}",
3148 e.kind
3149 );
3150 }
3151 _ => panic!("Expected protocol error"),
3152 }
3153 }
3154
3155 #[test]
3156 fn must_enforce_string_size_limit() {
3157 let channel = TBufferChannel::with_capacity(100, 100);
3158 let (r_channel, mut w_channel) = channel.split().unwrap();
3159
3160 // Create protocol with string limit of 100 bytes
3161 let config = TConfiguration::builder()
3162 .max_string_size(Some(100))
3163 .build()
3164 .unwrap();
3165 let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3166
3167 // Write a varint-encoded string size that exceeds the limit
3168 w_channel.set_readable_bytes(&[
3169 0xC8, 0x01, // Varint encoding of 200
3170 ]);
3171
3172 let result = protocol.read_string();
3173 assert!(result.is_err());
3174 match result {
3175 Err(crate::Error::Protocol(e)) => {
3176 assert_eq!(e.kind, ProtocolErrorKind::SizeLimit);
3177 assert!(e.message.contains("exceeds maximum allowed size"));
3178 }
3179 _ => panic!("Expected protocol error with SizeLimit"),
3180 }
3181 }
3182
3183 #[test]
3184 fn must_allow_no_limit_configuration() {
3185 let channel = TBufferChannel::with_capacity(40, 40);
3186
3187 let config = TConfiguration::no_limits();
3188 let mut protocol = TCompactInputProtocol::with_config(channel, config);
3189
3190 // Should be able to nest structs deeply without limit
3191 for _ in 0..100 {
3192 assert!(protocol.read_struct_begin().is_ok());
3193 }
3194
3195 for _ in 0..100 {
3196 assert!(protocol.read_struct_end().is_ok());
3197 }
3198 }
3199
3200 #[test]
3201 fn must_allow_containers_within_limit() {
3202 let channel = TBufferChannel::with_capacity(200, 200);
3203 let (r_channel, mut w_channel) = channel.split().unwrap();
3204
3205 // Create protocol with container limit of 100
3206 let config = TConfiguration::builder()
3207 .max_container_size(Some(100))
3208 .build()
3209 .unwrap();
3210 let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3211
3212 // Write a list with 5 i32 elements (well within limit of 100)
3213 // Compact protocol: size < 15 is encoded in header
3214 w_channel.set_readable_bytes(&[
3215 0x55, // Header: size=5, element type=5 (i32)
3216 // 5 varint-encoded i32 values
3217 0x0A, // 10
3218 0x14, // 20
3219 0x1E, // 30
3220 0x28, // 40
3221 0x32, // 50
3222 ]);
3223
3224 let result = protocol.read_list_begin();
3225 assert!(result.is_ok());
3226 let list_ident = result.unwrap();
3227 assert_eq!(list_ident.size, 5);
3228 assert_eq!(list_ident.element_type, TType::I32);
3229 }
3230
3231 #[test]
3232 fn must_allow_strings_within_limit() {
3233 let channel = TBufferChannel::with_capacity(100, 100);
3234 let (r_channel, mut w_channel) = channel.split().unwrap();
3235
3236 let config = TConfiguration::builder()
3237 .max_string_size(Some(1000))
3238 .build()
3239 .unwrap();
3240 let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3241
3242 // Write a string "hello" (5 bytes, well within limit)
3243 w_channel.set_readable_bytes(&[
3244 0x05, // Varint-encoded length: 5
3245 b'h', b'e', b'l', b'l', b'o',
3246 ]);
3247
3248 let result = protocol.read_string();
3249 assert!(result.is_ok());
3250 assert_eq!(result.unwrap(), "hello");
3251 }
Allen George8b96bfb2016-11-02 08:01:08 -04003252}