blob: 0e6136074e2c234fa004ffe49854bf042bbac04d [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 {
Santiago Medina Rolong6f182852026-03-10 18:39:33 -0700220 self.last_read_field_id = self
221 .last_read_field_id
222 .checked_add(field_delta as i16)
223 .ok_or_else(|| {
224 crate::Error::Protocol(ProtocolError::new(
225 ProtocolErrorKind::InvalidData,
226 "field id overflow",
227 ))
228 })?;
Allen George8b96bfb2016-11-02 08:01:08 -0400229 } else {
230 self.last_read_field_id = self.read_i16()?;
231 };
232
Allen Georgeef7a1892018-12-16 18:01:37 -0500233 Ok(TFieldIdentifier {
234 name: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500235 field_type,
Allen Georgeef7a1892018-12-16 18:01:37 -0500236 id: Some(self.last_read_field_id),
237 })
Allen George8b96bfb2016-11-02 08:01:08 -0400238 }
239 }
240 }
241
Allen Georgeb0d14132020-03-29 11:48:55 -0400242 fn read_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400243 Ok(())
244 }
245
Allen Georgeb0d14132020-03-29 11:48:55 -0400246 fn read_bool(&mut self) -> crate::Result<bool> {
Allen George8b96bfb2016-11-02 08:01:08 -0400247 match self.pending_read_bool_value.take() {
248 Some(b) => Ok(b),
249 None => {
250 let b = self.read_byte()?;
251 match b {
Jörn Horstmann717bd792025-02-02 23:10:27 +0100252 // Previous versions of the thrift compact protocol specification said to use 0
253 // and 1 inside collections, but that differed from existing implementations.
254 // The specification was updated in https://github.com/apache/thrift/commit/2c29c5665bc442e703480bb0ee60fe925ffe02e8.
255 0x00 => Ok(false),
Allen George8b96bfb2016-11-02 08:01:08 -0400256 0x01 => Ok(true),
257 0x02 => Ok(false),
Allen Georgeb0d14132020-03-29 11:48:55 -0400258 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
259 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500260 message: format!("cannot convert {} into bool", unkn),
261 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400262 }
263 }
264 }
265 }
266
Allen Georgeb0d14132020-03-29 11:48:55 -0400267 fn read_bytes(&mut self) -> crate::Result<Vec<u8>> {
Allen George0e22c362017-01-30 07:15:00 -0500268 let len = self.transport.read_varint::<u32>()?;
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700269
270 if let Some(max_size) = self.config.max_string_size() {
271 if len as usize > max_size {
272 return Err(crate::Error::Protocol(ProtocolError::new(
273 ProtocolErrorKind::SizeLimit,
274 format!(
275 "Byte array size {} exceeds maximum allowed size of {}",
276 len, max_size
277 ),
278 )));
279 }
280 }
281
Allen George8b96bfb2016-11-02 08:01:08 -0400282 let mut buf = vec![0u8; len as usize];
Allen George0e22c362017-01-30 07:15:00 -0500283 self.transport
284 .read_exact(&mut buf)
285 .map_err(From::from)
286 .map(|_| buf)
Allen George8b96bfb2016-11-02 08:01:08 -0400287 }
288
Allen Georgeb0d14132020-03-29 11:48:55 -0400289 fn read_i8(&mut self) -> crate::Result<i8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400290 self.read_byte().map(|i| i as i8)
291 }
292
Allen Georgeb0d14132020-03-29 11:48:55 -0400293 fn read_i16(&mut self) -> crate::Result<i16> {
Allen George0e22c362017-01-30 07:15:00 -0500294 self.transport.read_varint::<i16>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400295 }
296
Allen Georgeb0d14132020-03-29 11:48:55 -0400297 fn read_i32(&mut self) -> crate::Result<i32> {
Allen George0e22c362017-01-30 07:15:00 -0500298 self.transport.read_varint::<i32>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400299 }
300
Allen Georgeb0d14132020-03-29 11:48:55 -0400301 fn read_i64(&mut self) -> crate::Result<i64> {
Allen George0e22c362017-01-30 07:15:00 -0500302 self.transport.read_varint::<i64>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400303 }
304
Allen Georgeb0d14132020-03-29 11:48:55 -0400305 fn read_double(&mut self) -> crate::Result<f64> {
Allen George8a1743d2020-12-05 01:19:27 -0500306 self.transport
307 .read_f64::<LittleEndian>()
308 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400309 }
310
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800311 fn read_uuid(&mut self) -> crate::Result<uuid::Uuid> {
Hasnain Lakhani57c5fc12025-08-02 21:12:07 -0700312 let mut buf = [0u8; 16];
313 self.transport
314 .read_exact(&mut buf)
315 .map(|_| uuid::Uuid::from_bytes(buf))
316 .map_err(From::from)
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800317 }
318
Allen Georgeb0d14132020-03-29 11:48:55 -0400319 fn read_string(&mut self) -> crate::Result<String> {
Allen George8b96bfb2016-11-02 08:01:08 -0400320 let bytes = self.read_bytes()?;
321 String::from_utf8(bytes).map_err(From::from)
322 }
323
Allen Georgeb0d14132020-03-29 11:48:55 -0400324 fn read_list_begin(&mut self) -> crate::Result<TListIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400325 let (element_type, element_count) = self.read_list_set_begin()?;
326 Ok(TListIdentifier::new(element_type, element_count))
327 }
328
Allen Georgeb0d14132020-03-29 11:48:55 -0400329 fn read_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400330 Ok(())
331 }
332
Allen Georgeb0d14132020-03-29 11:48:55 -0400333 fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400334 let (element_type, element_count) = self.read_list_set_begin()?;
335 Ok(TSetIdentifier::new(element_type, element_count))
336 }
337
Allen Georgeb0d14132020-03-29 11:48:55 -0400338 fn read_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400339 Ok(())
340 }
341
Allen Georgeb0d14132020-03-29 11:48:55 -0400342 fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier> {
Allen George0e22c362017-01-30 07:15:00 -0500343 let element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400344 if element_count == 0 {
345 Ok(TMapIdentifier::new(None, None, 0))
346 } else {
347 let type_header = self.read_byte()?;
348 let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
349 let val_type = collection_u8_to_type(type_header & 0x0F)?;
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700350
351 let key_min_size = self.min_serialized_size(key_type);
352 let value_min_size = self.min_serialized_size(val_type);
353 let element_size = key_min_size + value_min_size;
354 super::check_container_size(&self.config, element_count, element_size)?;
355
Allen George8b96bfb2016-11-02 08:01:08 -0400356 Ok(TMapIdentifier::new(key_type, val_type, element_count))
357 }
358 }
359
Allen Georgeb0d14132020-03-29 11:48:55 -0400360 fn read_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400361 Ok(())
362 }
363
364 // utility
365 //
366
Allen Georgeb0d14132020-03-29 11:48:55 -0400367 fn read_byte(&mut self) -> crate::Result<u8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400368 let mut buf = [0u8; 1];
Allen George0e22c362017-01-30 07:15:00 -0500369 self.transport
370 .read_exact(&mut buf)
371 .map_err(From::from)
372 .map(|_| buf[0])
Allen George8b96bfb2016-11-02 08:01:08 -0400373 }
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700374
375 fn min_serialized_size(&self, field_type: TType) -> usize {
376 compact_protocol_min_serialized_size(field_type)
377 }
378}
379
380pub(crate) fn compact_protocol_min_serialized_size(field_type: TType) -> usize {
381 match field_type {
382 TType::Stop => 1, // 1 byte
383 TType::Void => 1, // 1 byte
384 TType::Bool => 1, // 1 byte
385 TType::I08 => 1, // 1 byte
386 TType::Double => 8, // 8 bytes (not varint encoded)
387 TType::I16 => 1, // 1 byte minimum (varint)
388 TType::I32 => 1, // 1 byte minimum (varint)
389 TType::I64 => 1, // 1 byte minimum (varint)
390 TType::String => 1, // 1 byte minimum for length (varint)
391 TType::Struct => 1, // 1 byte minimum (stop field)
392 TType::Map => 1, // 1 byte minimum
393 TType::Set => 1, // 1 byte minimum
394 TType::List => 1, // 1 byte minimum
395 TType::Uuid => 16, // 16 bytes
396 TType::Utf7 => 1, // 1 byte
397 }
Allen George8b96bfb2016-11-02 08:01:08 -0400398}
399
Vadim Chekand3355af2018-01-05 23:12:47 -0500400impl<T> io::Seek for TCompactInputProtocol<T>
401where
402 T: io::Seek + TReadTransport,
403{
404 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
405 self.transport.seek(pos)
406 }
407}
408
Allen George8b96bfb2016-11-02 08:01:08 -0400409/// Factory for creating instances of `TCompactInputProtocol`.
410#[derive(Default)]
411pub struct TCompactInputProtocolFactory;
412
413impl TCompactInputProtocolFactory {
414 /// Create a `TCompactInputProtocolFactory`.
415 pub fn new() -> TCompactInputProtocolFactory {
416 TCompactInputProtocolFactory {}
417 }
418}
419
420impl TInputProtocolFactory for TCompactInputProtocolFactory {
Danny Browning77d96c12019-08-21 13:41:07 -0600421 fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500422 Box::new(TCompactInputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400423 }
424}
425
426/// Write messages using the Thrift compact protocol.
427///
428/// # Examples
429///
430/// Create and use a `TCompactOutputProtocol`.
431///
432/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -0400433/// use thrift::protocol::{TCompactOutputProtocol, TOutputProtocol};
Allen George0e22c362017-01-30 07:15:00 -0500434/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -0400435///
Allen George0e22c362017-01-30 07:15:00 -0500436/// let mut channel = TTcpChannel::new();
437/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400438///
Allen George0e22c362017-01-30 07:15:00 -0500439/// let mut protocol = TCompactOutputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -0400440///
Allen George0e22c362017-01-30 07:15:00 -0500441/// protocol.write_bool(true).unwrap();
442/// protocol.write_string("test_string").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400443/// ```
Allen George0e22c362017-01-30 07:15:00 -0500444#[derive(Debug)]
445pub struct TCompactOutputProtocol<T>
446where
447 T: TWriteTransport,
448{
Allen George8b96bfb2016-11-02 08:01:08 -0400449 // Identifier of the last field serialized for a struct.
450 last_write_field_id: i16,
Allen George0e22c362017-01-30 07:15:00 -0500451 // Stack of the last written field ids (new entry added each time a nested struct is written).
Allen George8b96bfb2016-11-02 08:01:08 -0400452 write_field_id_stack: Vec<i16>,
453 // Field identifier of the boolean field to be written.
454 // Saved because boolean fields and their value are encoded in a single byte
455 pending_write_bool_field_identifier: Option<TFieldIdentifier>,
456 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -0500457 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -0400458}
459
Allen George0e22c362017-01-30 07:15:00 -0500460impl<T> TCompactOutputProtocol<T>
461where
462 T: TWriteTransport,
463{
Allen George8b96bfb2016-11-02 08:01:08 -0400464 /// Create a `TCompactOutputProtocol` that writes bytes to `transport`.
Allen George0e22c362017-01-30 07:15:00 -0500465 pub fn new(transport: T) -> TCompactOutputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -0400466 TCompactOutputProtocol {
467 last_write_field_id: 0,
468 write_field_id_stack: Vec::new(),
469 pending_write_bool_field_identifier: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500470 transport,
Allen George8b96bfb2016-11-02 08:01:08 -0400471 }
472 }
473
474 // FIXME: field_type as unconstrained u8 is bad
Allen Georgeb0d14132020-03-29 11:48:55 -0400475 fn write_field_header(&mut self, field_type: u8, field_id: i16) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400476 let field_delta = field_id - self.last_write_field_id;
477 if field_delta > 0 && field_delta < 15 {
478 self.write_byte(((field_delta as u8) << 4) | field_type)?;
479 } else {
480 self.write_byte(field_type)?;
481 self.write_i16(field_id)?;
482 }
483 self.last_write_field_id = field_id;
484 Ok(())
485 }
486
Allen George8a1743d2020-12-05 01:19:27 -0500487 fn write_list_set_begin(
488 &mut self,
489 element_type: TType,
490 element_count: i32,
491 ) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400492 let elem_identifier = collection_type_to_u8(element_type);
493 if element_count <= 14 {
Hasnain Lakhani7ac79ab2025-08-25 14:40:43 -0700494 let header = ((element_count as u8) << 4) | elem_identifier;
Allen George8b96bfb2016-11-02 08:01:08 -0400495 self.write_byte(header)
496 } else {
497 let header = 0xF0 | elem_identifier;
498 self.write_byte(header)?;
Allen George48905102021-02-20 08:47:01 -0500499 // element count is strictly positive as per the spec, so
500 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George8b96bfb2016-11-02 08:01:08 -0400501 self.transport
Allen George8b96bfb2016-11-02 08:01:08 -0400502 .write_varint(element_count as u32)
503 .map_err(From::from)
504 .map(|_| ())
505 }
506 }
507
508 fn assert_no_pending_bool_write(&self) {
509 if let Some(ref f) = self.pending_write_bool_field_identifier {
510 panic!("pending bool field {:?} not written", f)
511 }
512 }
513}
514
Allen George0e22c362017-01-30 07:15:00 -0500515impl<T> TOutputProtocol for TCompactOutputProtocol<T>
516where
517 T: TWriteTransport,
518{
Allen Georgeb0d14132020-03-29 11:48:55 -0400519 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400520 self.write_byte(COMPACT_PROTOCOL_ID)?;
521 self.write_byte((u8::from(identifier.message_type) << 5) | COMPACT_VERSION)?;
Allen George48905102021-02-20 08:47:01 -0500522 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George55c3e4c2021-03-01 23:19:52 -0500523 self.transport
524 .write_varint(identifier.sequence_number as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400525 self.write_string(&identifier.name)?;
526 Ok(())
527 }
528
Allen Georgeb0d14132020-03-29 11:48:55 -0400529 fn write_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400530 self.assert_no_pending_bool_write();
531 Ok(())
532 }
533
Allen Georgeb0d14132020-03-29 11:48:55 -0400534 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400535 self.write_field_id_stack.push(self.last_write_field_id);
536 self.last_write_field_id = 0;
537 Ok(())
538 }
539
Allen Georgeb0d14132020-03-29 11:48:55 -0400540 fn write_struct_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400541 self.assert_no_pending_bool_write();
Allen Georgeef7a1892018-12-16 18:01:37 -0500542 self.last_write_field_id = self
543 .write_field_id_stack
Allen George0e22c362017-01-30 07:15:00 -0500544 .pop()
545 .expect("should have previous field ids");
Allen George8b96bfb2016-11-02 08:01:08 -0400546 Ok(())
547 }
548
Allen Georgeb0d14132020-03-29 11:48:55 -0400549 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400550 match identifier.field_type {
551 TType::Bool => {
552 if self.pending_write_bool_field_identifier.is_some() {
Allen George0e22c362017-01-30 07:15:00 -0500553 panic!(
554 "should not have a pending bool while writing another bool with id: \
Allen Georgeef7a1892018-12-16 18:01:37 -0500555 {:?}",
Allen George0e22c362017-01-30 07:15:00 -0500556 identifier
557 )
Allen George8b96bfb2016-11-02 08:01:08 -0400558 }
559 self.pending_write_bool_field_identifier = Some(identifier.clone());
560 Ok(())
561 }
562 _ => {
563 let field_type = type_to_u8(identifier.field_type);
Allen Georgeef7a1892018-12-16 18:01:37 -0500564 let field_id = identifier.id.expect("non-stop field should have field id");
Allen George8b96bfb2016-11-02 08:01:08 -0400565 self.write_field_header(field_type, field_id)
566 }
567 }
568 }
569
Allen Georgeb0d14132020-03-29 11:48:55 -0400570 fn write_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400571 self.assert_no_pending_bool_write();
572 Ok(())
573 }
574
Allen Georgeb0d14132020-03-29 11:48:55 -0400575 fn write_field_stop(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400576 self.assert_no_pending_bool_write();
577 self.write_byte(type_to_u8(TType::Stop))
578 }
579
Allen Georgeb0d14132020-03-29 11:48:55 -0400580 fn write_bool(&mut self, b: bool) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400581 match self.pending_write_bool_field_identifier.take() {
582 Some(pending) => {
583 let field_id = pending.id.expect("bool field should have a field id");
584 let field_type_as_u8 = if b { 0x01 } else { 0x02 };
585 self.write_field_header(field_type_as_u8, field_id)
586 }
587 None => {
588 if b {
589 self.write_byte(0x01)
590 } else {
591 self.write_byte(0x02)
592 }
593 }
594 }
595 }
596
Allen Georgeb0d14132020-03-29 11:48:55 -0400597 fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> {
Allen George48905102021-02-20 08:47:01 -0500598 // length is strictly positive as per the spec, so
599 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500600 self.transport.write_varint(b.len() as u32)?;
601 self.transport.write_all(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400602 }
603
Allen Georgeb0d14132020-03-29 11:48:55 -0400604 fn write_i8(&mut self, i: i8) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400605 self.write_byte(i as u8)
606 }
607
Allen Georgeb0d14132020-03-29 11:48:55 -0400608 fn write_i16(&mut self, i: i16) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500609 self.transport
Allen George48905102021-02-20 08:47:01 -0500610 .write_varint(i)
Allen George0e22c362017-01-30 07:15:00 -0500611 .map_err(From::from)
612 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400613 }
614
Allen Georgeb0d14132020-03-29 11:48:55 -0400615 fn write_i32(&mut self, i: i32) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500616 self.transport
617 .write_varint(i)
618 .map_err(From::from)
619 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400620 }
621
Allen Georgeb0d14132020-03-29 11:48:55 -0400622 fn write_i64(&mut self, i: i64) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500623 self.transport
624 .write_varint(i)
625 .map_err(From::from)
626 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400627 }
628
Allen Georgeb0d14132020-03-29 11:48:55 -0400629 fn write_double(&mut self, d: f64) -> crate::Result<()> {
Allen George8a1743d2020-12-05 01:19:27 -0500630 self.transport
631 .write_f64::<LittleEndian>(d)
632 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400633 }
634
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800635 fn write_uuid(&mut self, uuid: &uuid::Uuid) -> crate::Result<()> {
Hasnain Lakhani57c5fc12025-08-02 21:12:07 -0700636 self.transport
637 .write_all(uuid.as_bytes())
638 .map_err(From::from)
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800639 }
640
Allen Georgeb0d14132020-03-29 11:48:55 -0400641 fn write_string(&mut self, s: &str) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400642 self.write_bytes(s.as_bytes())
643 }
644
Allen Georgeb0d14132020-03-29 11:48:55 -0400645 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400646 self.write_list_set_begin(identifier.element_type, identifier.size)
647 }
648
Allen Georgeb0d14132020-03-29 11:48:55 -0400649 fn write_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400650 Ok(())
651 }
652
Allen Georgeb0d14132020-03-29 11:48:55 -0400653 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400654 self.write_list_set_begin(identifier.element_type, identifier.size)
655 }
656
Allen Georgeb0d14132020-03-29 11:48:55 -0400657 fn write_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400658 Ok(())
659 }
660
Allen Georgeb0d14132020-03-29 11:48:55 -0400661 fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400662 if identifier.size == 0 {
663 self.write_byte(0)
664 } else {
Allen George48905102021-02-20 08:47:01 -0500665 // element count is strictly positive as per the spec, so
666 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500667 self.transport.write_varint(identifier.size as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400668
Allen George0e22c362017-01-30 07:15:00 -0500669 let key_type = identifier
670 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400671 .expect("map identifier to write should contain key type");
672 let key_type_byte = collection_type_to_u8(key_type) << 4;
673
Allen George0e22c362017-01-30 07:15:00 -0500674 let val_type = identifier
675 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400676 .expect("map identifier to write should contain value type");
677 let val_type_byte = collection_type_to_u8(val_type);
678
679 let map_type_header = key_type_byte | val_type_byte;
680 self.write_byte(map_type_header)
681 }
682 }
683
Allen Georgeb0d14132020-03-29 11:48:55 -0400684 fn write_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400685 Ok(())
686 }
687
Allen Georgeb0d14132020-03-29 11:48:55 -0400688 fn flush(&mut self) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500689 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400690 }
691
692 // utility
693 //
694
Allen Georgeb0d14132020-03-29 11:48:55 -0400695 fn write_byte(&mut self, b: u8) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500696 self.transport.write(&[b]).map_err(From::from).map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400697 }
698}
699
700/// Factory for creating instances of `TCompactOutputProtocol`.
701#[derive(Default)]
702pub struct TCompactOutputProtocolFactory;
703
704impl TCompactOutputProtocolFactory {
705 /// Create a `TCompactOutputProtocolFactory`.
706 pub fn new() -> TCompactOutputProtocolFactory {
707 TCompactOutputProtocolFactory {}
708 }
709}
710
711impl TOutputProtocolFactory for TCompactOutputProtocolFactory {
Allen George8a1743d2020-12-05 01:19:27 -0500712 fn create(
713 &self,
714 transport: Box<dyn TWriteTransport + Send>,
715 ) -> Box<dyn TOutputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500716 Box::new(TCompactOutputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400717 }
718}
719
720fn collection_type_to_u8(field_type: TType) -> u8 {
721 match field_type {
722 TType::Bool => 0x01,
723 f => type_to_u8(f),
724 }
725}
726
727fn type_to_u8(field_type: TType) -> u8 {
728 match field_type {
729 TType::Stop => 0x00,
730 TType::I08 => 0x03, // equivalent to TType::Byte
731 TType::I16 => 0x04,
732 TType::I32 => 0x05,
733 TType::I64 => 0x06,
734 TType::Double => 0x07,
735 TType::String => 0x08,
736 TType::List => 0x09,
737 TType::Set => 0x0A,
738 TType::Map => 0x0B,
739 TType::Struct => 0x0C,
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800740 TType::Uuid => 0x0D,
Allen George2b691ee2021-10-14 22:25:07 -0400741 _ => panic!("should not have attempted to convert {} to u8", field_type),
Allen George8b96bfb2016-11-02 08:01:08 -0400742 }
743}
744
Allen Georgeb0d14132020-03-29 11:48:55 -0400745fn collection_u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400746 match b {
Jörn Horstmann717bd792025-02-02 23:10:27 +0100747 // For historical and compatibility reasons, a reader should be capable to deal with both cases.
748 // The only valid value in the original spec was 2, but due to a widespread implementation bug
749 // the defacto standard across large parts of the library became 1 instead.
750 // As a result, both values are now allowed.
751 0x01 | 0x02 => Ok(TType::Bool),
Allen George8b96bfb2016-11-02 08:01:08 -0400752 o => u8_to_type(o),
753 }
754}
755
Allen Georgeb0d14132020-03-29 11:48:55 -0400756fn u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400757 match b {
758 0x00 => Ok(TType::Stop),
759 0x03 => Ok(TType::I08), // equivalent to TType::Byte
760 0x04 => Ok(TType::I16),
761 0x05 => Ok(TType::I32),
762 0x06 => Ok(TType::I64),
763 0x07 => Ok(TType::Double),
764 0x08 => Ok(TType::String),
765 0x09 => Ok(TType::List),
766 0x0A => Ok(TType::Set),
767 0x0B => Ok(TType::Map),
768 0x0C => Ok(TType::Struct),
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800769 0x0D => Ok(TType::Uuid),
Allen Georgeb0d14132020-03-29 11:48:55 -0400770 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
771 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500772 message: format!("cannot convert {} into TType", unkn),
773 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400774 }
775}
776
777#[cfg(test)]
778mod tests {
779
Allen Georgeb0d14132020-03-29 11:48:55 -0400780 use crate::protocol::{
Allen Georgeef7a1892018-12-16 18:01:37 -0500781 TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
782 TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
783 };
Allen Georgeb0d14132020-03-29 11:48:55 -0400784 use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400785
786 use super::*;
787
788 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500789 fn must_write_message_begin_largest_maximum_positive_sequence_number() {
790 let (_, mut o_prot) = test_objects();
791
792 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
793 "bar",
794 TMessageType::Reply,
795 i32::MAX
796 )));
797
798 #[rustfmt::skip]
799 let expected: [u8; 11] = [
800 0x82, /* protocol ID */
801 0x41, /* message type | protocol version */
802 0xFF,
803 0xFF,
804 0xFF,
805 0xFF,
806 0x07, /* non-zig-zag varint sequence number */
807 0x03, /* message-name length */
808 0x62,
809 0x61,
810 0x72 /* "bar" */,
811 ];
812
813 assert_eq_written_bytes!(o_prot, expected);
814 }
815
816 #[test]
817 fn must_read_message_begin_largest_maximum_positive_sequence_number() {
818 let (mut i_prot, _) = test_objects();
819
820 #[rustfmt::skip]
821 let source_bytes: [u8; 11] = [
822 0x82, /* protocol ID */
823 0x41, /* message type | protocol version */
824 0xFF,
825 0xFF,
826 0xFF,
827 0xFF,
828 0x07, /* non-zig-zag varint sequence number */
829 0x03, /* message-name length */
830 0x62,
831 0x61,
832 0x72 /* "bar" */,
833 ];
834
835 i_prot.transport.set_readable_bytes(&source_bytes);
836
837 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MAX);
838 let res = assert_success!(i_prot.read_message_begin());
839
840 assert_eq!(&expected, &res);
841 }
842
843 #[test]
844 fn must_write_message_begin_positive_sequence_number_0() {
Allen George0e22c362017-01-30 07:15:00 -0500845 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400846
Allen Georgeef7a1892018-12-16 18:01:37 -0500847 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
848 "foo",
849 TMessageType::Call,
850 431
851 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400852
Allen George7ddbcc02020-11-08 09:51:19 -0500853 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500854 let expected: [u8; 8] = [
855 0x82, /* protocol ID */
856 0x21, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500857 0xAF,
858 0x03, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500859 0x03, /* message-name length */
860 0x66,
861 0x6F,
862 0x6F /* "foo" */,
863 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400864
Allen George0e22c362017-01-30 07:15:00 -0500865 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400866 }
867
868 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500869 fn must_read_message_begin_positive_sequence_number_0() {
870 let (mut i_prot, _) = test_objects();
871
872 #[rustfmt::skip]
873 let source_bytes: [u8; 8] = [
874 0x82, /* protocol ID */
875 0x21, /* message type | protocol version */
876 0xAF,
877 0x03, /* non-zig-zag varint sequence number */
878 0x03, /* message-name length */
879 0x66,
880 0x6F,
881 0x6F /* "foo" */,
882 ];
883
884 i_prot.transport.set_readable_bytes(&source_bytes);
885
886 let expected = TMessageIdentifier::new("foo", TMessageType::Call, 431);
887 let res = assert_success!(i_prot.read_message_begin());
888
889 assert_eq!(&expected, &res);
890 }
891
892 #[test]
893 fn must_write_message_begin_positive_sequence_number_1() {
Allen George0e22c362017-01-30 07:15:00 -0500894 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400895
Allen Georgeef7a1892018-12-16 18:01:37 -0500896 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
897 "bar",
898 TMessageType::Reply,
Allen George7ddbcc02020-11-08 09:51:19 -0500899 991_828
Allen Georgeef7a1892018-12-16 18:01:37 -0500900 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400901
Allen George7ddbcc02020-11-08 09:51:19 -0500902 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500903 let expected: [u8; 9] = [
904 0x82, /* protocol ID */
905 0x41, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500906 0xD4,
907 0xC4,
908 0x3C, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500909 0x03, /* message-name length */
910 0x62,
911 0x61,
912 0x72 /* "bar" */,
913 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400914
Allen George0e22c362017-01-30 07:15:00 -0500915 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400916 }
917
918 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500919 fn must_read_message_begin_positive_sequence_number_1() {
920 let (mut i_prot, _) = test_objects();
921
922 #[rustfmt::skip]
923 let source_bytes: [u8; 9] = [
924 0x82, /* protocol ID */
925 0x41, /* message type | protocol version */
926 0xD4,
927 0xC4,
928 0x3C, /* non-zig-zag varint sequence number */
929 0x03, /* message-name length */
930 0x62,
931 0x61,
932 0x72 /* "bar" */,
933 ];
934
935 i_prot.transport.set_readable_bytes(&source_bytes);
936
937 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 991_828);
938 let res = assert_success!(i_prot.read_message_begin());
939
940 assert_eq!(&expected, &res);
941 }
942
943 #[test]
944 fn must_write_message_begin_zero_sequence_number() {
945 let (_, mut o_prot) = test_objects();
946
947 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
948 "bar",
949 TMessageType::Reply,
950 0
951 )));
952
953 #[rustfmt::skip]
954 let expected: [u8; 7] = [
955 0x82, /* protocol ID */
956 0x41, /* message type | protocol version */
957 0x00, /* non-zig-zag varint sequence number */
958 0x03, /* message-name length */
959 0x62,
960 0x61,
961 0x72 /* "bar" */,
962 ];
963
964 assert_eq_written_bytes!(o_prot, expected);
965 }
966
967 #[test]
968 fn must_read_message_begin_zero_sequence_number() {
969 let (mut i_prot, _) = test_objects();
970
971 #[rustfmt::skip]
972 let source_bytes: [u8; 7] = [
973 0x82, /* protocol ID */
974 0x41, /* message type | protocol version */
975 0x00, /* non-zig-zag varint sequence number */
976 0x03, /* message-name length */
977 0x62,
978 0x61,
979 0x72 /* "bar" */,
980 ];
981
982 i_prot.transport.set_readable_bytes(&source_bytes);
983
984 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 0);
985 let res = assert_success!(i_prot.read_message_begin());
986
987 assert_eq!(&expected, &res);
988 }
989
990 #[test]
991 fn must_write_message_begin_largest_minimum_negative_sequence_number() {
992 let (_, mut o_prot) = test_objects();
993
994 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
995 "bar",
996 TMessageType::Reply,
997 i32::MIN
998 )));
999
1000 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
1001 #[rustfmt::skip]
1002 let expected: [u8; 11] = [
1003 0x82, /* protocol ID */
1004 0x41, /* message type | protocol version */
1005 0x80,
1006 0x80,
1007 0x80,
1008 0x80,
1009 0x08, /* non-zig-zag varint sequence number */
1010 0x03, /* message-name length */
1011 0x62,
1012 0x61,
1013 0x72 /* "bar" */,
1014 ];
1015
1016 assert_eq_written_bytes!(o_prot, expected);
1017 }
1018
1019 #[test]
1020 fn must_read_message_begin_largest_minimum_negative_sequence_number() {
1021 let (mut i_prot, _) = test_objects();
1022
1023 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
1024 #[rustfmt::skip]
1025 let source_bytes: [u8; 11] = [
1026 0x82, /* protocol ID */
1027 0x41, /* message type | protocol version */
1028 0x80,
1029 0x80,
1030 0x80,
1031 0x80,
1032 0x08, /* non-zig-zag varint sequence number */
1033 0x03, /* message-name length */
1034 0x62,
1035 0x61,
1036 0x72 /* "bar" */,
1037 ];
1038
1039 i_prot.transport.set_readable_bytes(&source_bytes);
1040
1041 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MIN);
1042 let res = assert_success!(i_prot.read_message_begin());
1043
1044 assert_eq!(&expected, &res);
1045 }
1046
1047 #[test]
1048 fn must_write_message_begin_negative_sequence_number_0() {
1049 let (_, mut o_prot) = test_objects();
1050
1051 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1052 "foo",
1053 TMessageType::Call,
1054 -431
1055 )));
1056
1057 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
1058 #[rustfmt::skip]
1059 let expected: [u8; 11] = [
1060 0x82, /* protocol ID */
1061 0x21, /* message type | protocol version */
1062 0xD1,
1063 0xFC,
1064 0xFF,
1065 0xFF,
1066 0x0F, /* non-zig-zag varint sequence number */
1067 0x03, /* message-name length */
1068 0x66,
1069 0x6F,
1070 0x6F /* "foo" */,
1071 ];
1072
1073 assert_eq_written_bytes!(o_prot, expected);
1074 }
1075
1076 #[test]
1077 fn must_read_message_begin_negative_sequence_number_0() {
1078 let (mut i_prot, _) = test_objects();
1079
1080 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
1081 #[rustfmt::skip]
1082 let source_bytes: [u8; 11] = [
1083 0x82, /* protocol ID */
1084 0x21, /* message type | protocol version */
1085 0xD1,
1086 0xFC,
1087 0xFF,
1088 0xFF,
1089 0x0F, /* non-zig-zag varint sequence number */
1090 0x03, /* message-name length */
1091 0x66,
1092 0x6F,
1093 0x6F /* "foo" */,
1094 ];
1095
1096 i_prot.transport.set_readable_bytes(&source_bytes);
1097
1098 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -431);
1099 let res = assert_success!(i_prot.read_message_begin());
1100
1101 assert_eq!(&expected, &res);
1102 }
1103
1104 #[test]
1105 fn must_write_message_begin_negative_sequence_number_1() {
1106 let (_, mut o_prot) = test_objects();
1107
1108 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1109 "foo",
1110 TMessageType::Call,
1111 -73_184_125
1112 )));
1113
1114 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1115 #[rustfmt::skip]
1116 let expected: [u8; 11] = [
1117 0x82, /* protocol ID */
1118 0x21, /* message type | protocol version */
1119 0x83,
1120 0x99,
1121 0x8D,
1122 0xDD,
1123 0x0F, /* non-zig-zag varint sequence number */
1124 0x03, /* message-name length */
1125 0x66,
1126 0x6F,
1127 0x6F /* "foo" */,
1128 ];
1129
1130 assert_eq_written_bytes!(o_prot, expected);
1131 }
1132
1133 #[test]
1134 fn must_read_message_begin_negative_sequence_number_1() {
1135 let (mut i_prot, _) = test_objects();
1136
1137 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1138 #[rustfmt::skip]
1139 let source_bytes: [u8; 11] = [
1140 0x82, /* protocol ID */
1141 0x21, /* message type | protocol version */
1142 0x83,
1143 0x99,
1144 0x8D,
1145 0xDD,
1146 0x0F, /* non-zig-zag varint sequence number */
1147 0x03, /* message-name length */
1148 0x66,
1149 0x6F,
1150 0x6F /* "foo" */,
1151 ];
1152
1153 i_prot.transport.set_readable_bytes(&source_bytes);
1154
1155 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -73_184_125);
1156 let res = assert_success!(i_prot.read_message_begin());
1157
1158 assert_eq!(&expected, &res);
1159 }
1160
1161 #[test]
1162 fn must_write_message_begin_negative_sequence_number_2() {
1163 let (_, mut o_prot) = test_objects();
1164
1165 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1166 "foo",
1167 TMessageType::Call,
1168 -1_073_741_823
1169 )));
1170
1171 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
1172 #[rustfmt::skip]
1173 let expected: [u8; 11] = [
1174 0x82, /* protocol ID */
1175 0x21, /* message type | protocol version */
1176 0x81,
1177 0x80,
1178 0x80,
1179 0x80,
1180 0x0C, /* non-zig-zag varint sequence number */
1181 0x03, /* message-name length */
1182 0x66,
1183 0x6F,
1184 0x6F /* "foo" */,
1185 ];
1186
1187 assert_eq_written_bytes!(o_prot, expected);
1188 }
1189
1190 #[test]
1191 fn must_read_message_begin_negative_sequence_number_2() {
1192 let (mut i_prot, _) = test_objects();
1193
1194 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
Allen George55c3e4c2021-03-01 23:19:52 -05001195 #[rustfmt::skip]
Allen George8a1743d2020-12-05 01:19:27 -05001196 let source_bytes: [u8; 11] = [
1197 0x82, /* protocol ID */
1198 0x21, /* message type | protocol version */
1199 0x81,
1200 0x80,
1201 0x80,
1202 0x80,
1203 0x0C, /* non-zig-zag varint sequence number */
1204 0x03, /* message-name length */
1205 0x66,
1206 0x6F,
Allen George55c3e4c2021-03-01 23:19:52 -05001207 0x6F, /* "foo" */
Allen George8a1743d2020-12-05 01:19:27 -05001208 ];
1209
1210 i_prot.transport.set_readable_bytes(&source_bytes);
1211
1212 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -1_073_741_823);
1213 let res = assert_success!(i_prot.read_message_begin());
1214
1215 assert_eq!(&expected, &res);
1216 }
1217
1218 #[test]
Nik Claytone7917602020-03-05 11:51:15 +01001219 fn must_round_trip_upto_i64_maxvalue() {
1220 // See https://issues.apache.org/jira/browse/THRIFT-5131
1221 for i in 0..64 {
1222 let (mut i_prot, mut o_prot) = test_objects();
1223 let val: i64 = ((1u64 << i) - 1) as i64;
1224
1225 o_prot
Allen George8a1743d2020-12-05 01:19:27 -05001226 .write_field_begin(&TFieldIdentifier::new("val", TType::I64, 1))
Nik Claytone7917602020-03-05 11:51:15 +01001227 .unwrap();
1228 o_prot.write_i64(val).unwrap();
1229 o_prot.write_field_end().unwrap();
1230 o_prot.flush().unwrap();
1231
1232 copy_write_buffer_to_read_buffer!(o_prot);
1233
1234 i_prot.read_field_begin().unwrap();
1235 assert_eq!(val, i_prot.read_i64().unwrap());
1236 }
1237 }
1238
1239 #[test]
Allen George8b96bfb2016-11-02 08:01:08 -04001240 fn must_round_trip_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -05001241 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001242
Allen George7ddbcc02020-11-08 09:51:19 -05001243 let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948);
Allen George8b96bfb2016-11-02 08:01:08 -04001244
1245 assert_success!(o_prot.write_message_begin(&ident));
1246
Allen George0e22c362017-01-30 07:15:00 -05001247 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001248
1249 let res = assert_success!(i_prot.read_message_begin());
1250 assert_eq!(&res, &ident);
1251 }
1252
1253 #[test]
1254 fn must_write_message_end() {
1255 assert_no_write(|o| o.write_message_end());
1256 }
1257
1258 // NOTE: structs and fields are tested together
1259 //
1260
1261 #[test]
1262 fn must_write_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001263 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001264
1265 // no bytes should be written however
1266 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1267
1268 // write three fields with tiny field ids
1269 // since they're small the field ids will be encoded as deltas
1270
1271 // since this is the first field (and it's zero) it gets the full varint write
1272 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
1273 assert_success!(o_prot.write_field_end());
1274
1275 // since this delta > 0 and < 15 it can be encoded as a delta
1276 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
1277 assert_success!(o_prot.write_field_end());
1278
1279 // since this delta > 0 and < 15 it can be encoded as a delta
1280 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
1281 assert_success!(o_prot.write_field_end());
1282
1283 // now, finish the struct off
1284 assert_success!(o_prot.write_field_stop());
1285 assert_success!(o_prot.write_struct_end());
1286
Allen George7ddbcc02020-11-08 09:51:19 -05001287 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001288 let expected: [u8; 5] = [
1289 0x03, /* field type */
1290 0x00, /* first field id */
1291 0x44, /* field delta (4) | field type */
1292 0x59, /* field delta (5) | field type */
1293 0x00 /* field stop */,
1294 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001295
Allen George0e22c362017-01-30 07:15:00 -05001296 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001297 }
1298
1299 #[test]
1300 fn must_round_trip_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001301 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001302
1303 // no bytes should be written however
1304 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1305
1306 // write three fields with tiny field ids
1307 // since they're small the field ids will be encoded as deltas
1308
1309 // since this is the first field (and it's zero) it gets the full varint write
1310 let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
1311 assert_success!(o_prot.write_field_begin(&field_ident_1));
1312 assert_success!(o_prot.write_field_end());
1313
1314 // since this delta > 0 and < 15 it can be encoded as a delta
1315 let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
1316 assert_success!(o_prot.write_field_begin(&field_ident_2));
1317 assert_success!(o_prot.write_field_end());
1318
1319 // since this delta > 0 and < 15 it can be encoded as a delta
1320 let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
1321 assert_success!(o_prot.write_field_begin(&field_ident_3));
1322 assert_success!(o_prot.write_field_end());
1323
1324 // now, finish the struct off
1325 assert_success!(o_prot.write_field_stop());
1326 assert_success!(o_prot.write_struct_end());
1327
Allen George0e22c362017-01-30 07:15:00 -05001328 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001329
1330 // read the struct back
1331 assert_success!(i_prot.read_struct_begin());
1332
1333 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001334 assert_eq!(
1335 read_ident_1,
1336 TFieldIdentifier {
1337 name: None,
1338 ..field_ident_1
1339 }
1340 );
Allen George8b96bfb2016-11-02 08:01:08 -04001341 assert_success!(i_prot.read_field_end());
1342
1343 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001344 assert_eq!(
1345 read_ident_2,
1346 TFieldIdentifier {
1347 name: None,
1348 ..field_ident_2
1349 }
1350 );
Allen George8b96bfb2016-11-02 08:01:08 -04001351 assert_success!(i_prot.read_field_end());
1352
1353 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001354 assert_eq!(
1355 read_ident_3,
1356 TFieldIdentifier {
1357 name: None,
1358 ..field_ident_3
1359 }
1360 );
Allen George8b96bfb2016-11-02 08:01:08 -04001361 assert_success!(i_prot.read_field_end());
1362
1363 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001364 assert_eq!(
1365 read_ident_4,
1366 TFieldIdentifier {
1367 name: None,
1368 field_type: TType::Stop,
1369 id: None,
1370 }
1371 );
Allen George8b96bfb2016-11-02 08:01:08 -04001372
1373 assert_success!(i_prot.read_struct_end());
1374 }
1375
1376 #[test]
1377 fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001378 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001379
1380 // no bytes should be written however
1381 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1382
1383 // write three fields with tiny field ids
1384 // since they're small the field ids will be encoded as deltas
1385
1386 // gets a delta write
1387 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
1388 assert_success!(o_prot.write_field_end());
1389
1390 // since this delta > 0 and < 15 it can be encoded as a delta
1391 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
1392 assert_success!(o_prot.write_field_end());
1393
1394 // since this delta > 0 and < 15 it can be encoded as a delta
1395 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
1396 assert_success!(o_prot.write_field_end());
1397
1398 // now, finish the struct off
1399 assert_success!(o_prot.write_field_stop());
1400 assert_success!(o_prot.write_struct_end());
1401
Allen George7ddbcc02020-11-08 09:51:19 -05001402 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001403 let expected: [u8; 4] = [
1404 0x15, /* field delta (1) | field type */
1405 0x1A, /* field delta (1) | field type */
1406 0x48, /* field delta (4) | field type */
1407 0x00 /* field stop */,
1408 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001409
Allen George0e22c362017-01-30 07:15:00 -05001410 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001411 }
1412
1413 #[test]
1414 fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001415 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001416
1417 // no bytes should be written however
1418 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1419
1420 // write three fields with tiny field ids
1421 // since they're small the field ids will be encoded as deltas
1422
1423 // gets a delta write
1424 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
1425 assert_success!(o_prot.write_field_begin(&field_ident_1));
1426 assert_success!(o_prot.write_field_end());
1427
1428 // since this delta > 0 and < 15 it can be encoded as a delta
1429 let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
1430 assert_success!(o_prot.write_field_begin(&field_ident_2));
1431 assert_success!(o_prot.write_field_end());
1432
1433 // since this delta > 0 and < 15 it can be encoded as a delta
1434 let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
1435 assert_success!(o_prot.write_field_begin(&field_ident_3));
1436 assert_success!(o_prot.write_field_end());
1437
1438 // now, finish the struct off
1439 assert_success!(o_prot.write_field_stop());
1440 assert_success!(o_prot.write_struct_end());
1441
Allen George0e22c362017-01-30 07:15:00 -05001442 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001443
1444 // read the struct back
1445 assert_success!(i_prot.read_struct_begin());
1446
1447 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001448 assert_eq!(
1449 read_ident_1,
1450 TFieldIdentifier {
1451 name: None,
1452 ..field_ident_1
1453 }
1454 );
Allen George8b96bfb2016-11-02 08:01:08 -04001455 assert_success!(i_prot.read_field_end());
1456
1457 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001458 assert_eq!(
1459 read_ident_2,
1460 TFieldIdentifier {
1461 name: None,
1462 ..field_ident_2
1463 }
1464 );
Allen George8b96bfb2016-11-02 08:01:08 -04001465 assert_success!(i_prot.read_field_end());
1466
1467 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001468 assert_eq!(
1469 read_ident_3,
1470 TFieldIdentifier {
1471 name: None,
1472 ..field_ident_3
1473 }
1474 );
Allen George8b96bfb2016-11-02 08:01:08 -04001475 assert_success!(i_prot.read_field_end());
1476
1477 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001478 assert_eq!(
1479 read_ident_4,
1480 TFieldIdentifier {
1481 name: None,
1482 field_type: TType::Stop,
1483 id: None,
1484 }
1485 );
Allen George8b96bfb2016-11-02 08:01:08 -04001486
1487 assert_success!(i_prot.read_struct_end());
1488 }
1489
1490 #[test]
1491 fn must_write_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001492 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001493
1494 // no bytes should be written however
1495 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1496
1497 // write three fields with field ids that cannot be encoded as deltas
1498
1499 // since this is the first field (and it's zero) it gets the full varint write
1500 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
1501 assert_success!(o_prot.write_field_end());
1502
1503 // since this delta is > 15 it is encoded as a zig-zag varint
1504 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
1505 assert_success!(o_prot.write_field_end());
1506
1507 // since this delta is > 15 it is encoded as a zig-zag varint
1508 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
1509 assert_success!(o_prot.write_field_end());
1510
1511 // now, finish the struct off
1512 assert_success!(o_prot.write_field_stop());
1513 assert_success!(o_prot.write_struct_end());
1514
Allen George7ddbcc02020-11-08 09:51:19 -05001515 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001516 let expected: [u8; 8] = [
1517 0x05, /* field type */
1518 0x00, /* first field id */
1519 0x06, /* field type */
1520 0x20, /* zig-zag varint field id */
1521 0x0A, /* field type */
1522 0xC6,
1523 0x01, /* zig-zag varint field id */
1524 0x00 /* field stop */,
1525 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001526
Allen George0e22c362017-01-30 07:15:00 -05001527 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001528 }
1529
1530 #[test]
1531 fn must_round_trip_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001532 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001533
1534 // no bytes should be written however
1535 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1536
1537 // write three fields with field ids that cannot be encoded as deltas
1538
1539 // since this is the first field (and it's zero) it gets the full varint write
1540 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
1541 assert_success!(o_prot.write_field_begin(&field_ident_1));
1542 assert_success!(o_prot.write_field_end());
1543
1544 // since this delta is > 15 it is encoded as a zig-zag varint
1545 let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
1546 assert_success!(o_prot.write_field_begin(&field_ident_2));
1547 assert_success!(o_prot.write_field_end());
1548
1549 // since this delta is > 15 it is encoded as a zig-zag varint
1550 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
1551 assert_success!(o_prot.write_field_begin(&field_ident_3));
1552 assert_success!(o_prot.write_field_end());
1553
1554 // now, finish the struct off
1555 assert_success!(o_prot.write_field_stop());
1556 assert_success!(o_prot.write_struct_end());
1557
Allen George0e22c362017-01-30 07:15:00 -05001558 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001559
1560 // read the struct back
1561 assert_success!(i_prot.read_struct_begin());
1562
1563 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001564 assert_eq!(
1565 read_ident_1,
1566 TFieldIdentifier {
1567 name: None,
1568 ..field_ident_1
1569 }
1570 );
Allen George8b96bfb2016-11-02 08:01:08 -04001571 assert_success!(i_prot.read_field_end());
1572
1573 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001574 assert_eq!(
1575 read_ident_2,
1576 TFieldIdentifier {
1577 name: None,
1578 ..field_ident_2
1579 }
1580 );
Allen George8b96bfb2016-11-02 08:01:08 -04001581 assert_success!(i_prot.read_field_end());
1582
1583 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001584 assert_eq!(
1585 read_ident_3,
1586 TFieldIdentifier {
1587 name: None,
1588 ..field_ident_3
1589 }
1590 );
Allen George8b96bfb2016-11-02 08:01:08 -04001591 assert_success!(i_prot.read_field_end());
1592
1593 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001594 assert_eq!(
1595 read_ident_4,
1596 TFieldIdentifier {
1597 name: None,
1598 field_type: TType::Stop,
1599 id: None,
1600 }
1601 );
Allen George8b96bfb2016-11-02 08:01:08 -04001602
1603 assert_success!(i_prot.read_struct_end());
1604 }
1605
1606 #[test]
1607 fn must_write_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001608 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001609
1610 // no bytes should be written however
1611 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1612
1613 // write three fields with field ids that cannot be encoded as deltas
1614
1615 // since the delta is > 0 and < 15 it gets a delta write
1616 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1617 assert_success!(o_prot.write_field_end());
1618
1619 // since this delta > 0 and < 15 it gets a delta write
1620 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1621 assert_success!(o_prot.write_field_end());
1622
1623 // since this delta is > 15 it is encoded as a zig-zag varint
1624 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
1625 assert_success!(o_prot.write_field_end());
1626
1627 // since this delta is > 15 it is encoded as a zig-zag varint
1628 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
1629 assert_success!(o_prot.write_field_end());
1630
1631 // since this is only 3 up from the previous it is recorded as a delta
1632 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
1633 assert_success!(o_prot.write_field_end());
1634
1635 // now, finish the struct off
1636 assert_success!(o_prot.write_field_stop());
1637 assert_success!(o_prot.write_struct_end());
1638
Allen George7ddbcc02020-11-08 09:51:19 -05001639 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001640 let expected: [u8; 10] = [
1641 0x16, /* field delta (1) | field type */
1642 0x85, /* field delta (8) | field type */
1643 0x0A, /* field type */
1644 0xD0,
1645 0x0F, /* zig-zag varint field id */
1646 0x0A, /* field type */
1647 0xA2,
1648 0x1F, /* zig-zag varint field id */
1649 0x3A, /* field delta (3) | field type */
1650 0x00 /* field stop */,
1651 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001652
Allen George0e22c362017-01-30 07:15:00 -05001653 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001654 }
1655
Allen George7ddbcc02020-11-08 09:51:19 -05001656 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001657 #[test]
1658 fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001659 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001660
1661 // no bytes should be written however
1662 let struct_ident = TStructIdentifier::new("foo");
1663 assert_success!(o_prot.write_struct_begin(&struct_ident));
1664
1665 // write three fields with field ids that cannot be encoded as deltas
1666
1667 // since the delta is > 0 and < 15 it gets a delta write
1668 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1669 assert_success!(o_prot.write_field_begin(&field_ident_1));
1670 assert_success!(o_prot.write_field_end());
1671
1672 // since this delta > 0 and < 15 it gets a delta write
1673 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1674 assert_success!(o_prot.write_field_begin(&field_ident_2));
1675 assert_success!(o_prot.write_field_end());
1676
1677 // since this delta is > 15 it is encoded as a zig-zag varint
1678 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
1679 assert_success!(o_prot.write_field_begin(&field_ident_3));
1680 assert_success!(o_prot.write_field_end());
1681
1682 // since this delta is > 15 it is encoded as a zig-zag varint
1683 let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
1684 assert_success!(o_prot.write_field_begin(&field_ident_4));
1685 assert_success!(o_prot.write_field_end());
1686
1687 // since this is only 3 up from the previous it is recorded as a delta
1688 let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
1689 assert_success!(o_prot.write_field_begin(&field_ident_5));
1690 assert_success!(o_prot.write_field_end());
1691
1692 // now, finish the struct off
1693 assert_success!(o_prot.write_field_stop());
1694 assert_success!(o_prot.write_struct_end());
1695
Allen George0e22c362017-01-30 07:15:00 -05001696 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001697
1698 // read the struct back
1699 assert_success!(i_prot.read_struct_begin());
1700
1701 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001702 assert_eq!(
1703 read_ident_1,
1704 TFieldIdentifier {
1705 name: None,
1706 ..field_ident_1
1707 }
1708 );
Allen George8b96bfb2016-11-02 08:01:08 -04001709 assert_success!(i_prot.read_field_end());
1710
1711 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001712 assert_eq!(
1713 read_ident_2,
1714 TFieldIdentifier {
1715 name: None,
1716 ..field_ident_2
1717 }
1718 );
Allen George8b96bfb2016-11-02 08:01:08 -04001719 assert_success!(i_prot.read_field_end());
1720
1721 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001722 assert_eq!(
1723 read_ident_3,
1724 TFieldIdentifier {
1725 name: None,
1726 ..field_ident_3
1727 }
1728 );
Allen George8b96bfb2016-11-02 08:01:08 -04001729 assert_success!(i_prot.read_field_end());
1730
1731 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001732 assert_eq!(
1733 read_ident_4,
1734 TFieldIdentifier {
1735 name: None,
1736 ..field_ident_4
1737 }
1738 );
Allen George8b96bfb2016-11-02 08:01:08 -04001739 assert_success!(i_prot.read_field_end());
1740
1741 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001742 assert_eq!(
1743 read_ident_5,
1744 TFieldIdentifier {
1745 name: None,
1746 ..field_ident_5
1747 }
1748 );
Allen George8b96bfb2016-11-02 08:01:08 -04001749 assert_success!(i_prot.read_field_end());
1750
1751 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001752 assert_eq!(
1753 read_ident_6,
1754 TFieldIdentifier {
1755 name: None,
1756 field_type: TType::Stop,
1757 id: None,
1758 }
1759 );
Allen George8b96bfb2016-11-02 08:01:08 -04001760
1761 assert_success!(i_prot.read_struct_end());
1762 }
1763
1764 #[test]
1765 fn must_write_nested_structs_0() {
1766 // last field of the containing struct is a delta
1767 // first field of the the contained struct is a delta
1768
Allen George0e22c362017-01-30 07:15:00 -05001769 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001770
1771 // start containing struct
1772 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1773
1774 // containing struct
1775 // since the delta is > 0 and < 15 it gets a delta write
1776 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1777 assert_success!(o_prot.write_field_end());
1778
1779 // containing struct
1780 // since this delta > 0 and < 15 it gets a delta write
1781 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1782 assert_success!(o_prot.write_field_end());
1783
1784 // start contained struct
1785 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1786
1787 // contained struct
1788 // since the delta is > 0 and < 15 it gets a delta write
1789 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
1790 assert_success!(o_prot.write_field_end());
1791
1792 // contained struct
1793 // since this delta > 15 it gets a full write
1794 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1795 assert_success!(o_prot.write_field_end());
1796
1797 // end contained struct
1798 assert_success!(o_prot.write_field_stop());
1799 assert_success!(o_prot.write_struct_end());
1800
1801 // end containing struct
1802 assert_success!(o_prot.write_field_stop());
1803 assert_success!(o_prot.write_struct_end());
1804
Allen George7ddbcc02020-11-08 09:51:19 -05001805 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001806 let expected: [u8; 7] = [
1807 0x16, /* field delta (1) | field type */
1808 0x85, /* field delta (8) | field type */
1809 0x73, /* field delta (7) | field type */
1810 0x07, /* field type */
1811 0x30, /* zig-zag varint field id */
1812 0x00, /* field stop - contained */
1813 0x00 /* field stop - containing */,
1814 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001815
Allen George0e22c362017-01-30 07:15:00 -05001816 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001817 }
1818
Allen George7ddbcc02020-11-08 09:51:19 -05001819 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001820 #[test]
1821 fn must_round_trip_nested_structs_0() {
1822 // last field of the containing struct is a delta
1823 // first field of the the contained struct is a delta
1824
Allen George0e22c362017-01-30 07:15:00 -05001825 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001826
1827 // start containing struct
1828 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1829
1830 // containing struct
1831 // since the delta is > 0 and < 15 it gets a delta write
1832 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1833 assert_success!(o_prot.write_field_begin(&field_ident_1));
1834 assert_success!(o_prot.write_field_end());
1835
1836 // containing struct
1837 // since this delta > 0 and < 15 it gets a delta write
1838 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1839 assert_success!(o_prot.write_field_begin(&field_ident_2));
1840 assert_success!(o_prot.write_field_end());
1841
1842 // start contained struct
1843 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1844
1845 // contained struct
1846 // since the delta is > 0 and < 15 it gets a delta write
1847 let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
1848 assert_success!(o_prot.write_field_begin(&field_ident_3));
1849 assert_success!(o_prot.write_field_end());
1850
1851 // contained struct
1852 // since this delta > 15 it gets a full write
1853 let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
1854 assert_success!(o_prot.write_field_begin(&field_ident_4));
1855 assert_success!(o_prot.write_field_end());
1856
1857 // end contained struct
1858 assert_success!(o_prot.write_field_stop());
1859 assert_success!(o_prot.write_struct_end());
1860
1861 // end containing struct
1862 assert_success!(o_prot.write_field_stop());
1863 assert_success!(o_prot.write_struct_end());
1864
Allen George0e22c362017-01-30 07:15:00 -05001865 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001866
1867 // read containing struct back
1868 assert_success!(i_prot.read_struct_begin());
1869
1870 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001871 assert_eq!(
1872 read_ident_1,
1873 TFieldIdentifier {
1874 name: None,
1875 ..field_ident_1
1876 }
1877 );
Allen George8b96bfb2016-11-02 08:01:08 -04001878 assert_success!(i_prot.read_field_end());
1879
1880 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001881 assert_eq!(
1882 read_ident_2,
1883 TFieldIdentifier {
1884 name: None,
1885 ..field_ident_2
1886 }
1887 );
Allen George8b96bfb2016-11-02 08:01:08 -04001888 assert_success!(i_prot.read_field_end());
1889
1890 // read contained struct back
1891 assert_success!(i_prot.read_struct_begin());
1892
1893 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001894 assert_eq!(
1895 read_ident_3,
1896 TFieldIdentifier {
1897 name: None,
1898 ..field_ident_3
1899 }
1900 );
Allen George8b96bfb2016-11-02 08:01:08 -04001901 assert_success!(i_prot.read_field_end());
1902
1903 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001904 assert_eq!(
1905 read_ident_4,
1906 TFieldIdentifier {
1907 name: None,
1908 ..field_ident_4
1909 }
1910 );
Allen George8b96bfb2016-11-02 08:01:08 -04001911 assert_success!(i_prot.read_field_end());
1912
1913 // end contained struct
1914 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001915 assert_eq!(
1916 read_ident_6,
1917 TFieldIdentifier {
1918 name: None,
1919 field_type: TType::Stop,
1920 id: None,
1921 }
1922 );
Allen George8b96bfb2016-11-02 08:01:08 -04001923 assert_success!(i_prot.read_struct_end());
1924
1925 // end containing struct
1926 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001927 assert_eq!(
1928 read_ident_7,
1929 TFieldIdentifier {
1930 name: None,
1931 field_type: TType::Stop,
1932 id: None,
1933 }
1934 );
Allen George8b96bfb2016-11-02 08:01:08 -04001935 assert_success!(i_prot.read_struct_end());
1936 }
1937
1938 #[test]
1939 fn must_write_nested_structs_1() {
1940 // last field of the containing struct is a delta
1941 // first field of the the contained struct is a full write
1942
Allen George0e22c362017-01-30 07:15:00 -05001943 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001944
1945 // start containing struct
1946 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1947
1948 // containing struct
1949 // since the delta is > 0 and < 15 it gets a delta write
1950 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1951 assert_success!(o_prot.write_field_end());
1952
1953 // containing struct
1954 // since this delta > 0 and < 15 it gets a delta write
1955 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1956 assert_success!(o_prot.write_field_end());
1957
1958 // start contained struct
1959 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1960
1961 // contained struct
1962 // since this delta > 15 it gets a full write
1963 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1964 assert_success!(o_prot.write_field_end());
1965
1966 // contained struct
1967 // since the delta is > 0 and < 15 it gets a delta write
1968 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1969 assert_success!(o_prot.write_field_end());
1970
1971 // end contained struct
1972 assert_success!(o_prot.write_field_stop());
1973 assert_success!(o_prot.write_struct_end());
1974
1975 // end containing struct
1976 assert_success!(o_prot.write_field_stop());
1977 assert_success!(o_prot.write_struct_end());
1978
Allen George7ddbcc02020-11-08 09:51:19 -05001979 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001980 let expected: [u8; 7] = [
1981 0x16, /* field delta (1) | field type */
1982 0x85, /* field delta (8) | field type */
1983 0x07, /* field type */
1984 0x30, /* zig-zag varint field id */
1985 0x33, /* field delta (3) | field type */
1986 0x00, /* field stop - contained */
1987 0x00 /* field stop - containing */,
1988 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001989
Allen George0e22c362017-01-30 07:15:00 -05001990 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001991 }
1992
Allen George7ddbcc02020-11-08 09:51:19 -05001993 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001994 #[test]
1995 fn must_round_trip_nested_structs_1() {
1996 // last field of the containing struct is a delta
1997 // first field of the the contained struct is a full write
1998
Allen George0e22c362017-01-30 07:15:00 -05001999 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002000
2001 // start containing struct
2002 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2003
2004 // containing struct
2005 // since the delta is > 0 and < 15 it gets a delta write
2006 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2007 assert_success!(o_prot.write_field_begin(&field_ident_1));
2008 assert_success!(o_prot.write_field_end());
2009
2010 // containing struct
2011 // since this delta > 0 and < 15 it gets a delta write
2012 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
2013 assert_success!(o_prot.write_field_begin(&field_ident_2));
2014 assert_success!(o_prot.write_field_end());
2015
2016 // start contained struct
2017 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2018
2019 // contained struct
2020 // since this delta > 15 it gets a full write
2021 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
2022 assert_success!(o_prot.write_field_begin(&field_ident_3));
2023 assert_success!(o_prot.write_field_end());
2024
2025 // contained struct
2026 // since the delta is > 0 and < 15 it gets a delta write
2027 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2028 assert_success!(o_prot.write_field_begin(&field_ident_4));
2029 assert_success!(o_prot.write_field_end());
2030
2031 // end contained struct
2032 assert_success!(o_prot.write_field_stop());
2033 assert_success!(o_prot.write_struct_end());
2034
2035 // end containing struct
2036 assert_success!(o_prot.write_field_stop());
2037 assert_success!(o_prot.write_struct_end());
2038
Allen George0e22c362017-01-30 07:15:00 -05002039 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002040
2041 // read containing struct back
2042 assert_success!(i_prot.read_struct_begin());
2043
2044 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002045 assert_eq!(
2046 read_ident_1,
2047 TFieldIdentifier {
2048 name: None,
2049 ..field_ident_1
2050 }
2051 );
Allen George8b96bfb2016-11-02 08:01:08 -04002052 assert_success!(i_prot.read_field_end());
2053
2054 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002055 assert_eq!(
2056 read_ident_2,
2057 TFieldIdentifier {
2058 name: None,
2059 ..field_ident_2
2060 }
2061 );
Allen George8b96bfb2016-11-02 08:01:08 -04002062 assert_success!(i_prot.read_field_end());
2063
2064 // read contained struct back
2065 assert_success!(i_prot.read_struct_begin());
2066
2067 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002068 assert_eq!(
2069 read_ident_3,
2070 TFieldIdentifier {
2071 name: None,
2072 ..field_ident_3
2073 }
2074 );
Allen George8b96bfb2016-11-02 08:01:08 -04002075 assert_success!(i_prot.read_field_end());
2076
2077 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002078 assert_eq!(
2079 read_ident_4,
2080 TFieldIdentifier {
2081 name: None,
2082 ..field_ident_4
2083 }
2084 );
Allen George8b96bfb2016-11-02 08:01:08 -04002085 assert_success!(i_prot.read_field_end());
2086
2087 // end contained struct
2088 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002089 assert_eq!(
2090 read_ident_6,
2091 TFieldIdentifier {
2092 name: None,
2093 field_type: TType::Stop,
2094 id: None,
2095 }
2096 );
Allen George8b96bfb2016-11-02 08:01:08 -04002097 assert_success!(i_prot.read_struct_end());
2098
2099 // end containing struct
2100 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002101 assert_eq!(
2102 read_ident_7,
2103 TFieldIdentifier {
2104 name: None,
2105 field_type: TType::Stop,
2106 id: None,
2107 }
2108 );
Allen George8b96bfb2016-11-02 08:01:08 -04002109 assert_success!(i_prot.read_struct_end());
2110 }
2111
2112 #[test]
2113 fn must_write_nested_structs_2() {
2114 // last field of the containing struct is a full write
2115 // first field of the the contained struct is a delta write
2116
Allen George0e22c362017-01-30 07:15:00 -05002117 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002118
2119 // start containing struct
2120 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2121
2122 // containing struct
2123 // since the delta is > 0 and < 15 it gets a delta write
2124 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2125 assert_success!(o_prot.write_field_end());
2126
2127 // containing struct
2128 // since this delta > 15 it gets a full write
2129 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2130 assert_success!(o_prot.write_field_end());
2131
2132 // start contained struct
2133 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2134
2135 // contained struct
2136 // since this delta > 0 and < 15 it gets a delta write
2137 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
2138 assert_success!(o_prot.write_field_end());
2139
2140 // contained struct
2141 // since the delta is > 0 and < 15 it gets a delta write
2142 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
2143 assert_success!(o_prot.write_field_end());
2144
2145 // end contained struct
2146 assert_success!(o_prot.write_field_stop());
2147 assert_success!(o_prot.write_struct_end());
2148
2149 // end containing struct
2150 assert_success!(o_prot.write_field_stop());
2151 assert_success!(o_prot.write_struct_end());
2152
Allen George7ddbcc02020-11-08 09:51:19 -05002153 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002154 let expected: [u8; 7] = [
2155 0x16, /* field delta (1) | field type */
2156 0x08, /* field type */
2157 0x2A, /* zig-zag varint field id */
2158 0x77, /* field delta(7) | field type */
2159 0x33, /* field delta (3) | field type */
2160 0x00, /* field stop - contained */
2161 0x00 /* field stop - containing */,
2162 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002163
Allen George0e22c362017-01-30 07:15:00 -05002164 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002165 }
2166
Allen George7ddbcc02020-11-08 09:51:19 -05002167 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002168 #[test]
2169 fn must_round_trip_nested_structs_2() {
Allen George0e22c362017-01-30 07:15:00 -05002170 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002171
2172 // start containing struct
2173 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2174
2175 // containing struct
2176 // since the delta is > 0 and < 15 it gets a delta write
2177 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2178 assert_success!(o_prot.write_field_begin(&field_ident_1));
2179 assert_success!(o_prot.write_field_end());
2180
2181 // containing struct
2182 // since this delta > 15 it gets a full write
2183 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2184 assert_success!(o_prot.write_field_begin(&field_ident_2));
2185 assert_success!(o_prot.write_field_end());
2186
2187 // start contained struct
2188 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2189
2190 // contained struct
2191 // since this delta > 0 and < 15 it gets a delta write
2192 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
2193 assert_success!(o_prot.write_field_begin(&field_ident_3));
2194 assert_success!(o_prot.write_field_end());
2195
2196 // contained struct
2197 // since the delta is > 0 and < 15 it gets a delta write
2198 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
2199 assert_success!(o_prot.write_field_begin(&field_ident_4));
2200 assert_success!(o_prot.write_field_end());
2201
2202 // end contained struct
2203 assert_success!(o_prot.write_field_stop());
2204 assert_success!(o_prot.write_struct_end());
2205
2206 // end containing struct
2207 assert_success!(o_prot.write_field_stop());
2208 assert_success!(o_prot.write_struct_end());
2209
Allen George0e22c362017-01-30 07:15:00 -05002210 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002211
2212 // read containing struct back
2213 assert_success!(i_prot.read_struct_begin());
2214
2215 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002216 assert_eq!(
2217 read_ident_1,
2218 TFieldIdentifier {
2219 name: None,
2220 ..field_ident_1
2221 }
2222 );
Allen George8b96bfb2016-11-02 08:01:08 -04002223 assert_success!(i_prot.read_field_end());
2224
2225 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002226 assert_eq!(
2227 read_ident_2,
2228 TFieldIdentifier {
2229 name: None,
2230 ..field_ident_2
2231 }
2232 );
Allen George8b96bfb2016-11-02 08:01:08 -04002233 assert_success!(i_prot.read_field_end());
2234
2235 // read contained struct back
2236 assert_success!(i_prot.read_struct_begin());
2237
2238 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002239 assert_eq!(
2240 read_ident_3,
2241 TFieldIdentifier {
2242 name: None,
2243 ..field_ident_3
2244 }
2245 );
Allen George8b96bfb2016-11-02 08:01:08 -04002246 assert_success!(i_prot.read_field_end());
2247
2248 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002249 assert_eq!(
2250 read_ident_4,
2251 TFieldIdentifier {
2252 name: None,
2253 ..field_ident_4
2254 }
2255 );
Allen George8b96bfb2016-11-02 08:01:08 -04002256 assert_success!(i_prot.read_field_end());
2257
2258 // end contained struct
2259 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002260 assert_eq!(
2261 read_ident_6,
2262 TFieldIdentifier {
2263 name: None,
2264 field_type: TType::Stop,
2265 id: None,
2266 }
2267 );
Allen George8b96bfb2016-11-02 08:01:08 -04002268 assert_success!(i_prot.read_struct_end());
2269
2270 // end containing struct
2271 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002272 assert_eq!(
2273 read_ident_7,
2274 TFieldIdentifier {
2275 name: None,
2276 field_type: TType::Stop,
2277 id: None,
2278 }
2279 );
Allen George8b96bfb2016-11-02 08:01:08 -04002280 assert_success!(i_prot.read_struct_end());
2281 }
2282
2283 #[test]
2284 fn must_write_nested_structs_3() {
2285 // last field of the containing struct is a full write
2286 // first field of the the contained struct is a full write
2287
Allen George0e22c362017-01-30 07:15:00 -05002288 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002289
2290 // start containing struct
2291 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2292
2293 // containing struct
2294 // since the delta is > 0 and < 15 it gets a delta write
2295 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2296 assert_success!(o_prot.write_field_end());
2297
2298 // containing struct
2299 // since this delta > 15 it gets a full write
2300 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2301 assert_success!(o_prot.write_field_end());
2302
2303 // start contained struct
2304 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2305
2306 // contained struct
2307 // since this delta > 15 it gets a full write
2308 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
2309 assert_success!(o_prot.write_field_end());
2310
2311 // contained struct
2312 // since the delta is > 0 and < 15 it gets a delta write
2313 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
2314 assert_success!(o_prot.write_field_end());
2315
2316 // end contained struct
2317 assert_success!(o_prot.write_field_stop());
2318 assert_success!(o_prot.write_struct_end());
2319
2320 // end containing struct
2321 assert_success!(o_prot.write_field_stop());
2322 assert_success!(o_prot.write_struct_end());
2323
Allen George7ddbcc02020-11-08 09:51:19 -05002324 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002325 let expected: [u8; 8] = [
2326 0x16, /* field delta (1) | field type */
2327 0x08, /* field type */
2328 0x2A, /* zig-zag varint field id */
2329 0x07, /* field type */
2330 0x2A, /* zig-zag varint field id */
2331 0x63, /* field delta (6) | field type */
2332 0x00, /* field stop - contained */
2333 0x00 /* field stop - containing */,
2334 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002335
Allen George0e22c362017-01-30 07:15:00 -05002336 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002337 }
2338
Allen George7ddbcc02020-11-08 09:51:19 -05002339 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002340 #[test]
2341 fn must_round_trip_nested_structs_3() {
2342 // last field of the containing struct is a full write
2343 // first field of the the contained struct is a full write
2344
Allen George0e22c362017-01-30 07:15:00 -05002345 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002346
2347 // start containing struct
2348 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2349
2350 // containing struct
2351 // since the delta is > 0 and < 15 it gets a delta write
2352 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2353 assert_success!(o_prot.write_field_begin(&field_ident_1));
2354 assert_success!(o_prot.write_field_end());
2355
2356 // containing struct
2357 // since this delta > 15 it gets a full write
2358 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2359 assert_success!(o_prot.write_field_begin(&field_ident_2));
2360 assert_success!(o_prot.write_field_end());
2361
2362 // start contained struct
2363 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2364
2365 // contained struct
2366 // since this delta > 15 it gets a full write
2367 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
2368 assert_success!(o_prot.write_field_begin(&field_ident_3));
2369 assert_success!(o_prot.write_field_end());
2370
2371 // contained struct
2372 // since the delta is > 0 and < 15 it gets a delta write
2373 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2374 assert_success!(o_prot.write_field_begin(&field_ident_4));
2375 assert_success!(o_prot.write_field_end());
2376
2377 // end contained struct
2378 assert_success!(o_prot.write_field_stop());
2379 assert_success!(o_prot.write_struct_end());
2380
2381 // end containing struct
2382 assert_success!(o_prot.write_field_stop());
2383 assert_success!(o_prot.write_struct_end());
2384
Allen George0e22c362017-01-30 07:15:00 -05002385 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002386
2387 // read containing struct back
2388 assert_success!(i_prot.read_struct_begin());
2389
2390 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002391 assert_eq!(
2392 read_ident_1,
2393 TFieldIdentifier {
2394 name: None,
2395 ..field_ident_1
2396 }
2397 );
Allen George8b96bfb2016-11-02 08:01:08 -04002398 assert_success!(i_prot.read_field_end());
2399
2400 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002401 assert_eq!(
2402 read_ident_2,
2403 TFieldIdentifier {
2404 name: None,
2405 ..field_ident_2
2406 }
2407 );
Allen George8b96bfb2016-11-02 08:01:08 -04002408 assert_success!(i_prot.read_field_end());
2409
2410 // read contained struct back
2411 assert_success!(i_prot.read_struct_begin());
2412
2413 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002414 assert_eq!(
2415 read_ident_3,
2416 TFieldIdentifier {
2417 name: None,
2418 ..field_ident_3
2419 }
2420 );
Allen George8b96bfb2016-11-02 08:01:08 -04002421 assert_success!(i_prot.read_field_end());
2422
2423 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002424 assert_eq!(
2425 read_ident_4,
2426 TFieldIdentifier {
2427 name: None,
2428 ..field_ident_4
2429 }
2430 );
Allen George8b96bfb2016-11-02 08:01:08 -04002431 assert_success!(i_prot.read_field_end());
2432
2433 // end contained struct
2434 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002435 assert_eq!(
2436 read_ident_6,
2437 TFieldIdentifier {
2438 name: None,
2439 field_type: TType::Stop,
2440 id: None,
2441 }
2442 );
Allen George8b96bfb2016-11-02 08:01:08 -04002443 assert_success!(i_prot.read_struct_end());
2444
2445 // end containing struct
2446 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002447 assert_eq!(
2448 read_ident_7,
2449 TFieldIdentifier {
2450 name: None,
2451 field_type: TType::Stop,
2452 id: None,
2453 }
2454 );
Allen George8b96bfb2016-11-02 08:01:08 -04002455 assert_success!(i_prot.read_struct_end());
2456 }
2457
2458 #[test]
2459 fn must_write_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002460 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002461
2462 // no bytes should be written however
2463 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2464
2465 // write three fields with field ids that cannot be encoded as deltas
2466
2467 // since the delta is > 0 and < 16 it gets a delta write
2468 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2469 assert_success!(o_prot.write_bool(true));
2470 assert_success!(o_prot.write_field_end());
2471
2472 // since this delta > 0 and < 15 it gets a delta write
2473 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
2474 assert_success!(o_prot.write_bool(false));
2475 assert_success!(o_prot.write_field_end());
2476
2477 // since this delta > 15 it gets a full write
2478 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
2479 assert_success!(o_prot.write_bool(true));
2480 assert_success!(o_prot.write_field_end());
2481
2482 // since this delta > 15 it gets a full write
2483 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
2484 assert_success!(o_prot.write_bool(false));
2485 assert_success!(o_prot.write_field_end());
2486
2487 // now, finish the struct off
2488 assert_success!(o_prot.write_field_stop());
2489 assert_success!(o_prot.write_struct_end());
2490
Allen George7ddbcc02020-11-08 09:51:19 -05002491 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002492 let expected: [u8; 7] = [
2493 0x11, /* field delta (1) | true */
2494 0x82, /* field delta (8) | false */
2495 0x01, /* true */
2496 0x34, /* field id */
2497 0x02, /* false */
2498 0x5A, /* field id */
2499 0x00 /* stop field */,
2500 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002501
Allen George0e22c362017-01-30 07:15:00 -05002502 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002503 }
2504
Allen George7ddbcc02020-11-08 09:51:19 -05002505 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002506 #[test]
2507 fn must_round_trip_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002508 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002509
2510 // no bytes should be written however
2511 let struct_ident = TStructIdentifier::new("foo");
2512 assert_success!(o_prot.write_struct_begin(&struct_ident));
2513
2514 // write two fields
2515
2516 // since the delta is > 0 and < 16 it gets a delta write
2517 let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
2518 assert_success!(o_prot.write_field_begin(&field_ident_1));
2519 assert_success!(o_prot.write_bool(true));
2520 assert_success!(o_prot.write_field_end());
2521
2522 // since this delta > 0 and < 15 it gets a delta write
2523 let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
2524 assert_success!(o_prot.write_field_begin(&field_ident_2));
2525 assert_success!(o_prot.write_bool(false));
2526 assert_success!(o_prot.write_field_end());
2527
2528 // since this delta > 15 it gets a full write
2529 let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
2530 assert_success!(o_prot.write_field_begin(&field_ident_3));
2531 assert_success!(o_prot.write_bool(true));
2532 assert_success!(o_prot.write_field_end());
2533
2534 // since this delta > 15 it gets a full write
2535 let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
2536 assert_success!(o_prot.write_field_begin(&field_ident_4));
2537 assert_success!(o_prot.write_bool(false));
2538 assert_success!(o_prot.write_field_end());
2539
2540 // now, finish the struct off
2541 assert_success!(o_prot.write_field_stop());
2542 assert_success!(o_prot.write_struct_end());
2543
Allen George0e22c362017-01-30 07:15:00 -05002544 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002545
2546 // read the struct back
2547 assert_success!(i_prot.read_struct_begin());
2548
2549 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002550 assert_eq!(
2551 read_ident_1,
2552 TFieldIdentifier {
2553 name: None,
2554 ..field_ident_1
2555 }
2556 );
Allen George8b96bfb2016-11-02 08:01:08 -04002557 let read_value_1 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002558 assert!(read_value_1);
Allen George8b96bfb2016-11-02 08:01:08 -04002559 assert_success!(i_prot.read_field_end());
2560
2561 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002562 assert_eq!(
2563 read_ident_2,
2564 TFieldIdentifier {
2565 name: None,
2566 ..field_ident_2
2567 }
2568 );
Allen George8b96bfb2016-11-02 08:01:08 -04002569 let read_value_2 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002570 assert!(!read_value_2);
Allen George8b96bfb2016-11-02 08:01:08 -04002571 assert_success!(i_prot.read_field_end());
2572
2573 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002574 assert_eq!(
2575 read_ident_3,
2576 TFieldIdentifier {
2577 name: None,
2578 ..field_ident_3
2579 }
2580 );
Allen George8b96bfb2016-11-02 08:01:08 -04002581 let read_value_3 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002582 assert!(read_value_3);
Allen George8b96bfb2016-11-02 08:01:08 -04002583 assert_success!(i_prot.read_field_end());
2584
2585 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002586 assert_eq!(
2587 read_ident_4,
2588 TFieldIdentifier {
2589 name: None,
2590 ..field_ident_4
2591 }
2592 );
Allen George8b96bfb2016-11-02 08:01:08 -04002593 let read_value_4 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002594 assert!(!read_value_4);
Allen George8b96bfb2016-11-02 08:01:08 -04002595 assert_success!(i_prot.read_field_end());
2596
2597 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002598 assert_eq!(
2599 read_ident_5,
2600 TFieldIdentifier {
2601 name: None,
2602 field_type: TType::Stop,
2603 id: None,
2604 }
2605 );
Allen George8b96bfb2016-11-02 08:01:08 -04002606
2607 assert_success!(i_prot.read_struct_end());
2608 }
2609
2610 #[test]
2611 #[should_panic]
2612 fn must_fail_if_write_field_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002613 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002614 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2615 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2616 o_prot.write_field_end().unwrap();
2617 }
2618
2619 #[test]
2620 #[should_panic]
2621 fn must_fail_if_write_stop_field_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002622 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002623 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2624 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2625 o_prot.write_field_stop().unwrap();
2626 }
2627
2628 #[test]
2629 #[should_panic]
2630 fn must_fail_if_write_struct_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002631 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002632 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2633 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2634 o_prot.write_struct_end().unwrap();
2635 }
2636
2637 #[test]
2638 #[should_panic]
2639 fn must_fail_if_write_struct_end_without_any_fields() {
Allen George0e22c362017-01-30 07:15:00 -05002640 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002641 o_prot.write_struct_end().unwrap();
2642 }
2643
2644 #[test]
2645 fn must_write_field_end() {
2646 assert_no_write(|o| o.write_field_end());
2647 }
2648
2649 #[test]
2650 fn must_write_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002651 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002652
2653 assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
2654
2655 let expected: [u8; 1] = [0x46 /* size | elem_type */];
2656
Allen George0e22c362017-01-30 07:15:00 -05002657 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002658 }
2659
2660 #[test]
2661 fn must_round_trip_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002662 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002663
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002664 let ident = TListIdentifier::new(TType::I32, 3);
Allen George8b96bfb2016-11-02 08:01:08 -04002665 assert_success!(o_prot.write_list_begin(&ident));
2666
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002667 assert_success!(o_prot.write_i32(100));
2668 assert_success!(o_prot.write_i32(200));
2669 assert_success!(o_prot.write_i32(300));
2670
2671 assert_success!(o_prot.write_list_end());
2672
Allen George0e22c362017-01-30 07:15:00 -05002673 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002674
2675 let res = assert_success!(i_prot.read_list_begin());
2676 assert_eq!(&res, &ident);
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002677
2678 assert_eq!(i_prot.read_i32().unwrap(), 100);
2679 assert_eq!(i_prot.read_i32().unwrap(), 200);
2680 assert_eq!(i_prot.read_i32().unwrap(), 300);
2681
2682 assert_success!(i_prot.read_list_end());
Allen George8b96bfb2016-11-02 08:01:08 -04002683 }
2684
2685 #[test]
2686 fn must_write_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002687 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002688
2689 let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
2690 assert!(res.is_ok());
2691
Allen George0e22c362017-01-30 07:15:00 -05002692 let expected: [u8; 3] = [
2693 0xF9, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002694 0x8F, 0x4E, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002695 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002696
Allen George0e22c362017-01-30 07:15:00 -05002697 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002698 }
2699
2700 #[test]
2701 fn must_round_trip_large_sized_list_begin() {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002702 let (mut i_prot, mut o_prot) = test_objects_no_limits();
Allen George8b96bfb2016-11-02 08:01:08 -04002703
2704 let ident = TListIdentifier::new(TType::Set, 47381);
Allen George8b96bfb2016-11-02 08:01:08 -04002705 assert_success!(o_prot.write_list_begin(&ident));
2706
Allen George0e22c362017-01-30 07:15:00 -05002707 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002708
2709 let res = assert_success!(i_prot.read_list_begin());
2710 assert_eq!(&res, &ident);
2711 }
2712
2713 #[test]
2714 fn must_write_list_end() {
2715 assert_no_write(|o| o.write_list_end());
2716 }
2717
2718 #[test]
2719 fn must_write_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002720 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002721
2722 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
2723
2724 let expected: [u8; 1] = [0x2C /* size | elem_type */];
2725
Allen George0e22c362017-01-30 07:15:00 -05002726 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002727 }
2728
2729 #[test]
2730 fn must_round_trip_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002731 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002732
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002733 let ident = TSetIdentifier::new(TType::I16, 3);
Allen George8b96bfb2016-11-02 08:01:08 -04002734 assert_success!(o_prot.write_set_begin(&ident));
2735
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002736 assert_success!(o_prot.write_i16(111));
2737 assert_success!(o_prot.write_i16(222));
2738 assert_success!(o_prot.write_i16(333));
2739
2740 assert_success!(o_prot.write_set_end());
2741
Allen George0e22c362017-01-30 07:15:00 -05002742 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002743
2744 let res = assert_success!(i_prot.read_set_begin());
2745 assert_eq!(&res, &ident);
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002746
2747 assert_eq!(i_prot.read_i16().unwrap(), 111);
2748 assert_eq!(i_prot.read_i16().unwrap(), 222);
2749 assert_eq!(i_prot.read_i16().unwrap(), 333);
2750
2751 assert_success!(i_prot.read_set_end());
Allen George8b96bfb2016-11-02 08:01:08 -04002752 }
2753
2754 #[test]
2755 fn must_write_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002756 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002757
2758 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
2759
Allen George0e22c362017-01-30 07:15:00 -05002760 let expected: [u8; 4] = [
2761 0xF7, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002762 0xD3, 0xBA, 0x01, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002763 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002764
Allen George0e22c362017-01-30 07:15:00 -05002765 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002766 }
2767
2768 #[test]
2769 fn must_round_trip_large_sized_set_begin() {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002770 let (mut i_prot, mut o_prot) = test_objects_no_limits();
Allen George8b96bfb2016-11-02 08:01:08 -04002771
Allen George7ddbcc02020-11-08 09:51:19 -05002772 let ident = TSetIdentifier::new(TType::Map, 3_928_429);
Allen George8b96bfb2016-11-02 08:01:08 -04002773 assert_success!(o_prot.write_set_begin(&ident));
2774
Allen George0e22c362017-01-30 07:15:00 -05002775 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002776
2777 let res = assert_success!(i_prot.read_set_begin());
2778 assert_eq!(&res, &ident);
2779 }
2780
2781 #[test]
2782 fn must_write_set_end() {
2783 assert_no_write(|o| o.write_set_end());
2784 }
2785
2786 #[test]
2787 fn must_write_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002788 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002789
2790 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
2791
2792 let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything
2793
Allen George0e22c362017-01-30 07:15:00 -05002794 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002795 }
2796
2797 #[test]
2798 fn must_read_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002799 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002800
2801 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
2802
Allen George0e22c362017-01-30 07:15:00 -05002803 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002804
2805 let res = assert_success!(i_prot.read_map_begin());
Allen George0e22c362017-01-30 07:15:00 -05002806 assert_eq!(
2807 &res,
2808 &TMapIdentifier {
Allen Georgeef7a1892018-12-16 18:01:37 -05002809 key_type: None,
2810 value_type: None,
2811 size: 0,
2812 }
Allen George0e22c362017-01-30 07:15:00 -05002813 );
Allen George8b96bfb2016-11-02 08:01:08 -04002814 }
2815
2816 #[test]
2817 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002818 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002819
Allen Georgeef7a1892018-12-16 18:01:37 -05002820 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
2821 TType::Double,
2822 TType::String,
2823 238
2824 )));
Allen George8b96bfb2016-11-02 08:01:08 -04002825
Allen George0e22c362017-01-30 07:15:00 -05002826 let expected: [u8; 3] = [
Allen Georgeef7a1892018-12-16 18:01:37 -05002827 0xEE, 0x01, /* size as varint */
2828 0x78, /* key type | val type */
Allen George0e22c362017-01-30 07:15:00 -05002829 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002830
Allen George0e22c362017-01-30 07:15:00 -05002831 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002832 }
2833
2834 #[test]
2835 fn must_round_trip_map_begin() {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002836 let (mut i_prot, mut o_prot) = test_objects_no_limits();
Allen George8b96bfb2016-11-02 08:01:08 -04002837
Allen George7ddbcc02020-11-08 09:51:19 -05002838 let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349);
Allen George8b96bfb2016-11-02 08:01:08 -04002839 assert_success!(o_prot.write_map_begin(&ident));
2840
Allen George0e22c362017-01-30 07:15:00 -05002841 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002842
2843 let res = assert_success!(i_prot.read_map_begin());
2844 assert_eq!(&res, &ident);
2845 }
2846
2847 #[test]
2848 fn must_write_map_end() {
2849 assert_no_write(|o| o.write_map_end());
2850 }
2851
2852 #[test]
2853 fn must_write_map_with_bool_key_and_value() {
Allen George0e22c362017-01-30 07:15:00 -05002854 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002855
2856 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
2857 assert_success!(o_prot.write_bool(true));
2858 assert_success!(o_prot.write_bool(false));
2859 assert_success!(o_prot.write_map_end());
2860
Allen George0e22c362017-01-30 07:15:00 -05002861 let expected: [u8; 4] = [
2862 0x01, /* size as varint */
2863 0x11, /* key type | val type */
2864 0x01, /* key: true */
Allen Georgeef7a1892018-12-16 18:01:37 -05002865 0x02, /* val: false */
Allen George0e22c362017-01-30 07:15:00 -05002866 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002867
Allen George0e22c362017-01-30 07:15:00 -05002868 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002869 }
2870
2871 #[test]
2872 fn must_round_trip_map_with_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002873 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002874
2875 let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
2876 assert_success!(o_prot.write_map_begin(&map_ident));
2877 assert_success!(o_prot.write_bool(true));
2878 assert_success!(o_prot.write_bool(false));
2879 assert_success!(o_prot.write_bool(false));
2880 assert_success!(o_prot.write_bool(true));
2881 assert_success!(o_prot.write_map_end());
2882
Allen George0e22c362017-01-30 07:15:00 -05002883 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002884
2885 // map header
2886 let rcvd_ident = assert_success!(i_prot.read_map_begin());
2887 assert_eq!(&rcvd_ident, &map_ident);
2888 // key 1
2889 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002890 assert!(b);
Allen George8b96bfb2016-11-02 08:01:08 -04002891 // val 1
2892 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002893 assert!(!b);
Allen George8b96bfb2016-11-02 08:01:08 -04002894 // key 2
2895 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002896 assert!(!b);
Allen George8b96bfb2016-11-02 08:01:08 -04002897 // val 2
2898 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002899 assert!(b);
Allen George8b96bfb2016-11-02 08:01:08 -04002900 // map end
2901 assert_success!(i_prot.read_map_end());
2902 }
2903
2904 #[test]
2905 fn must_read_map_end() {
Allen George0e22c362017-01-30 07:15:00 -05002906 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002907 assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
2908 }
2909
Allen Georgeef7a1892018-12-16 18:01:37 -05002910 fn test_objects() -> (
2911 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2912 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2913 ) {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002914 let mem = TBufferChannel::with_capacity(200, 200);
Allen George8b96bfb2016-11-02 08:01:08 -04002915
Allen George0e22c362017-01-30 07:15:00 -05002916 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -04002917
Allen George0e22c362017-01-30 07:15:00 -05002918 let i_prot = TCompactInputProtocol::new(r_mem);
2919 let o_prot = TCompactOutputProtocol::new(w_mem);
Allen George8b96bfb2016-11-02 08:01:08 -04002920
Allen George0e22c362017-01-30 07:15:00 -05002921 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -04002922 }
2923
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002924 fn test_objects_no_limits() -> (
2925 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2926 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2927 ) {
2928 let mem = TBufferChannel::with_capacity(200, 200);
2929
2930 let (r_mem, w_mem) = mem.split().unwrap();
2931
2932 let i_prot = TCompactInputProtocol::with_config(r_mem, TConfiguration::no_limits());
2933 let o_prot = TCompactOutputProtocol::new(w_mem);
2934
2935 (i_prot, o_prot)
2936 }
2937
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002938 #[test]
2939 fn must_read_write_double() {
2940 let (mut i_prot, mut o_prot) = test_objects();
2941
Allen George7ddbcc02020-11-08 09:51:19 -05002942 #[allow(clippy::approx_constant)]
2943 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002944 o_prot.write_double(double).unwrap();
2945 copy_write_buffer_to_read_buffer!(o_prot);
2946
Allen George7ddbcc02020-11-08 09:51:19 -05002947 let read_double = i_prot.read_double().unwrap();
Cameron Martinda54fc82025-01-12 08:55:45 +00002948 assert!((read_double - double).abs() < f64::EPSILON);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002949 }
2950
2951 #[test]
2952 fn must_encode_double_as_other_langs() {
2953 let (_, mut o_prot) = test_objects();
2954 let expected = [24, 45, 68, 84, 251, 33, 9, 64];
2955
Allen George7ddbcc02020-11-08 09:51:19 -05002956 #[allow(clippy::approx_constant)]
2957 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002958 o_prot.write_double(double).unwrap();
2959
2960 assert_eq_written_bytes!(o_prot, expected);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002961 }
2962
Allen George0e22c362017-01-30 07:15:00 -05002963 fn assert_no_write<F>(mut write_fn: F)
2964 where
Allen Georgeb0d14132020-03-29 11:48:55 -04002965 F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> crate::Result<()>,
Allen George0e22c362017-01-30 07:15:00 -05002966 {
2967 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002968 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -05002969 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -04002970 }
Jörn Horstmann717bd792025-02-02 23:10:27 +01002971
2972 #[test]
2973 fn must_read_boolean_list() {
2974 let (mut i_prot, _) = test_objects();
2975
2976 let source_bytes: [u8; 3] = [0x21, 2, 1];
2977
2978 i_prot.transport.set_readable_bytes(&source_bytes);
2979
2980 let (ttype, element_count) = assert_success!(i_prot.read_list_set_begin());
2981
2982 assert_eq!(ttype, TType::Bool);
2983 assert_eq!(element_count, 2);
2984 assert_eq!(i_prot.read_bool().unwrap(), false);
2985 assert_eq!(i_prot.read_bool().unwrap(), true);
2986
2987 assert_success!(i_prot.read_list_end());
2988 }
2989
2990 #[test]
2991 fn must_read_boolean_list_alternative_encoding() {
2992 let (mut i_prot, _) = test_objects();
2993
2994 let source_bytes: [u8; 3] = [0x22, 0, 1];
2995
2996 i_prot.transport.set_readable_bytes(&source_bytes);
2997
2998 let (ttype, element_count) = assert_success!(i_prot.read_list_set_begin());
2999
3000 assert_eq!(ttype, TType::Bool);
3001 assert_eq!(element_count, 2);
3002 assert_eq!(i_prot.read_bool().unwrap(), false);
3003 assert_eq!(i_prot.read_bool().unwrap(), true);
3004
3005 assert_success!(i_prot.read_list_end());
3006 }
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07003007
3008 #[test]
3009 fn must_enforce_recursion_depth_limit() {
3010 let channel = TBufferChannel::with_capacity(100, 100);
3011
3012 // Create a configuration with a small recursion limit
3013 let config = TConfiguration::builder()
3014 .max_recursion_depth(Some(2))
3015 .build()
3016 .unwrap();
3017
3018 let mut protocol = TCompactInputProtocol::with_config(channel, config);
3019
3020 // First struct - should succeed
3021 assert!(protocol.read_struct_begin().is_ok());
3022
3023 // Second struct - should succeed (at limit)
3024 assert!(protocol.read_struct_begin().is_ok());
3025
3026 // Third struct - should fail (exceeds limit)
3027 let result = protocol.read_struct_begin();
3028 assert!(result.is_err());
3029 match result {
3030 Err(crate::Error::Protocol(e)) => {
3031 assert_eq!(e.kind, ProtocolErrorKind::DepthLimit);
3032 }
3033 _ => panic!("Expected protocol error with DepthLimit"),
3034 }
3035 }
3036
3037 #[test]
3038 fn must_check_container_size_overflow() {
3039 // Configure a small message size limit
3040 let config = TConfiguration::builder()
3041 .max_message_size(Some(1000))
3042 .max_frame_size(Some(1000))
3043 .build()
3044 .unwrap();
3045 let transport = TBufferChannel::with_capacity(100, 0);
3046 let mut i_prot = TCompactInputProtocol::with_config(transport, config);
3047
3048 // Write a list header that would require more memory than message size limit
3049 // List of 100 UUIDs (16 bytes each) = 1600 bytes > 1000 limit
3050 i_prot.transport.set_readable_bytes(&[
3051 0xFD, // element type UUID (0x0D) | count in next bytes (0xF0)
3052 0x64, // varint 100
3053 ]);
3054
3055 let result = i_prot.read_list_begin();
3056 assert!(result.is_err());
3057 match result {
3058 Err(crate::Error::Protocol(e)) => {
3059 assert_eq!(e.kind, ProtocolErrorKind::SizeLimit);
3060 assert!(e
3061 .message
3062 .contains("1600 bytes, exceeding message size limit of 1000"));
3063 }
3064 _ => panic!("Expected protocol error with SizeLimit"),
3065 }
3066 }
3067
3068 #[test]
3069 fn must_reject_negative_container_sizes() {
3070 let mut channel = TBufferChannel::with_capacity(100, 100);
3071
3072 let mut protocol = TCompactInputProtocol::new(channel.clone());
3073
3074 // Write header with negative size when decoded
3075 // In compact protocol, lists/sets use a header byte followed by size
3076 // We'll use 0x0F for element type and then a varint-encoded negative number
3077 channel.set_readable_bytes(&[
3078 0xF0, // Header: 15 in upper nibble (triggers varint read), List type in lower
3079 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, // Varint encoding of -1
3080 ]);
3081
3082 let result = protocol.read_list_begin();
3083 assert!(result.is_err());
3084 match result {
3085 Err(crate::Error::Protocol(e)) => {
3086 assert_eq!(e.kind, ProtocolErrorKind::NegativeSize);
3087 }
3088 _ => panic!("Expected protocol error with NegativeSize"),
3089 }
3090 }
3091
3092 #[test]
3093 fn must_enforce_container_size_limit() {
3094 let channel = TBufferChannel::with_capacity(100, 100);
3095 let (r_channel, mut w_channel) = channel.split().unwrap();
3096
3097 // Create protocol with explicit container size limit
3098 let config = TConfiguration::builder()
3099 .max_container_size(Some(1000))
3100 .build()
3101 .unwrap();
3102 let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3103
3104 // Write header with large size
3105 // Compact protocol: 0xF0 means size >= 15 is encoded as varint
3106 // Then we write a varint encoding 10000 (exceeds our limit of 1000)
3107 w_channel.set_readable_bytes(&[
3108 0xF0, // Header: 15 in upper nibble (triggers varint read), element type in lower
3109 0x90, 0x4E, // Varint encoding of 10000
3110 ]);
3111
3112 let result = protocol.read_list_begin();
3113 assert!(result.is_err());
3114 match result {
3115 Err(crate::Error::Protocol(e)) => {
3116 assert_eq!(e.kind, ProtocolErrorKind::SizeLimit);
3117 assert!(e.message.contains("exceeds maximum allowed size"));
3118 }
3119 _ => panic!("Expected protocol error with SizeLimit"),
3120 }
3121 }
3122
3123 #[test]
3124 fn must_handle_varint_size_overflow() {
3125 // Test that compact protocol properly handles varint-encoded sizes that would cause overflow
3126 let mut channel = TBufferChannel::with_capacity(100, 100);
3127
3128 let mut protocol = TCompactInputProtocol::new(channel.clone());
3129
3130 // Create input that encodes a very large size using varint encoding
3131 // 0xFA = list header with size >= 15 (so size follows as varint)
3132 // Then multiple 0xFF bytes which in varint encoding create a very large number
3133 channel.set_readable_bytes(&[
3134 0xFA, // List header: size >= 15, element type = 0x0A
3135 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, // Varint encoding of a huge number
3136 ]);
3137
3138 let result = protocol.read_list_begin();
3139 assert!(result.is_err());
3140 match result {
3141 Err(crate::Error::Protocol(e)) => {
3142 // The varint decoder might interpret this as negative, which is also fine
3143 assert!(
3144 e.kind == ProtocolErrorKind::SizeLimit
3145 || e.kind == ProtocolErrorKind::NegativeSize,
3146 "Expected SizeLimit or NegativeSize but got {:?}",
3147 e.kind
3148 );
3149 }
3150 _ => panic!("Expected protocol error"),
3151 }
3152 }
3153
3154 #[test]
3155 fn must_enforce_string_size_limit() {
3156 let channel = TBufferChannel::with_capacity(100, 100);
3157 let (r_channel, mut w_channel) = channel.split().unwrap();
3158
3159 // Create protocol with string limit of 100 bytes
3160 let config = TConfiguration::builder()
3161 .max_string_size(Some(100))
3162 .build()
3163 .unwrap();
3164 let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3165
3166 // Write a varint-encoded string size that exceeds the limit
3167 w_channel.set_readable_bytes(&[
3168 0xC8, 0x01, // Varint encoding of 200
3169 ]);
3170
3171 let result = protocol.read_string();
3172 assert!(result.is_err());
3173 match result {
3174 Err(crate::Error::Protocol(e)) => {
3175 assert_eq!(e.kind, ProtocolErrorKind::SizeLimit);
3176 assert!(e.message.contains("exceeds maximum allowed size"));
3177 }
3178 _ => panic!("Expected protocol error with SizeLimit"),
3179 }
3180 }
3181
3182 #[test]
3183 fn must_allow_no_limit_configuration() {
3184 let channel = TBufferChannel::with_capacity(40, 40);
3185
3186 let config = TConfiguration::no_limits();
3187 let mut protocol = TCompactInputProtocol::with_config(channel, config);
3188
3189 // Should be able to nest structs deeply without limit
3190 for _ in 0..100 {
3191 assert!(protocol.read_struct_begin().is_ok());
3192 }
3193
3194 for _ in 0..100 {
3195 assert!(protocol.read_struct_end().is_ok());
3196 }
3197 }
3198
3199 #[test]
3200 fn must_allow_containers_within_limit() {
3201 let channel = TBufferChannel::with_capacity(200, 200);
3202 let (r_channel, mut w_channel) = channel.split().unwrap();
3203
3204 // Create protocol with container limit of 100
3205 let config = TConfiguration::builder()
3206 .max_container_size(Some(100))
3207 .build()
3208 .unwrap();
3209 let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3210
3211 // Write a list with 5 i32 elements (well within limit of 100)
3212 // Compact protocol: size < 15 is encoded in header
3213 w_channel.set_readable_bytes(&[
3214 0x55, // Header: size=5, element type=5 (i32)
3215 // 5 varint-encoded i32 values
3216 0x0A, // 10
3217 0x14, // 20
3218 0x1E, // 30
3219 0x28, // 40
3220 0x32, // 50
3221 ]);
3222
3223 let result = protocol.read_list_begin();
3224 assert!(result.is_ok());
3225 let list_ident = result.unwrap();
3226 assert_eq!(list_ident.size, 5);
3227 assert_eq!(list_ident.element_type, TType::I32);
3228 }
3229
3230 #[test]
3231 fn must_allow_strings_within_limit() {
3232 let channel = TBufferChannel::with_capacity(100, 100);
3233 let (r_channel, mut w_channel) = channel.split().unwrap();
3234
3235 let config = TConfiguration::builder()
3236 .max_string_size(Some(1000))
3237 .build()
3238 .unwrap();
3239 let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3240
3241 // Write a string "hello" (5 bytes, well within limit)
3242 w_channel.set_readable_bytes(&[
3243 0x05, // Varint-encoded length: 5
3244 b'h', b'e', b'l', b'l', b'o',
3245 ]);
3246
3247 let result = protocol.read_string();
3248 assert!(result.is_ok());
3249 assert_eq!(result.unwrap(), "hello");
3250 }
Allen George8b96bfb2016-11-02 08:01:08 -04003251}