blob: 319f28a0272218b7e29e6a8ab9a893e67e18525c [file] [log] [blame]
Allen George8b96bfb2016-11-02 08:01:08 -04001// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
Marcin Pajkowskib34680f2019-12-02 10:29:16 +010018use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
Allen George8b96bfb2016-11-02 08:01:08 -040019use integer_encoding::{VarIntReader, VarIntWriter};
Danny Browningddec4312019-03-08 14:20:41 -070020use std::convert::{From, TryFrom};
Vadim Chekand3355af2018-01-05 23:12:47 -050021use std::io;
Allen George8b96bfb2016-11-02 08:01:08 -040022
Allen Georgeef7a1892018-12-16 18:01:37 -050023use super::{
24 TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier, TMapIdentifier,
25 TMessageIdentifier, TMessageType,
26};
Allen George8b96bfb2016-11-02 08:01:08 -040027use super::{TOutputProtocol, TOutputProtocolFactory, TSetIdentifier, TStructIdentifier, TType};
Allen Georgeb0d14132020-03-29 11:48:55 -040028use crate::transport::{TReadTransport, TWriteTransport};
Hasnain Lakhani42d0b712025-07-17 19:57:05 -070029use crate::{ProtocolError, ProtocolErrorKind, TConfiguration};
Allen George8b96bfb2016-11-02 08:01:08 -040030
31const COMPACT_PROTOCOL_ID: u8 = 0x82;
32const COMPACT_VERSION: u8 = 0x01;
33const COMPACT_VERSION_MASK: u8 = 0x1F;
34
35/// Read messages encoded in the Thrift compact protocol.
36///
37/// # Examples
38///
39/// Create and use a `TCompactInputProtocol`.
40///
41/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -040042/// use thrift::protocol::{TCompactInputProtocol, TInputProtocol};
Allen George0e22c362017-01-30 07:15:00 -050043/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -040044///
Allen George0e22c362017-01-30 07:15:00 -050045/// let mut channel = TTcpChannel::new();
46/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040047///
Allen George0e22c362017-01-30 07:15:00 -050048/// let mut protocol = TCompactInputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -040049///
Allen George0e22c362017-01-30 07:15:00 -050050/// let recvd_bool = protocol.read_bool().unwrap();
51/// let recvd_string = protocol.read_string().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040052/// ```
Allen George0e22c362017-01-30 07:15:00 -050053#[derive(Debug)]
54pub struct TCompactInputProtocol<T>
55where
56 T: TReadTransport,
57{
Allen George8b96bfb2016-11-02 08:01:08 -040058 // Identifier of the last field deserialized for a struct.
59 last_read_field_id: i16,
60 // Stack of the last read field ids (a new entry is added each time a nested struct is read).
61 read_field_id_stack: Vec<i16>,
62 // Boolean value for a field.
63 // Saved because boolean fields and their value are encoded in a single byte,
64 // and reading the field only occurs after the field id is read.
65 pending_read_bool_value: Option<bool>,
66 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -050067 transport: T,
Hasnain Lakhani42d0b712025-07-17 19:57:05 -070068 // Configuration
69 config: TConfiguration,
70 // Current recursion depth
71 recursion_depth: usize,
Allen George8b96bfb2016-11-02 08:01:08 -040072}
73
Allen George0e22c362017-01-30 07:15:00 -050074impl<T> TCompactInputProtocol<T>
75where
76 T: TReadTransport,
77{
Allen George8b96bfb2016-11-02 08:01:08 -040078 /// Create a `TCompactInputProtocol` that reads bytes from `transport`.
Allen George0e22c362017-01-30 07:15:00 -050079 pub fn new(transport: T) -> TCompactInputProtocol<T> {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -070080 Self::with_config(transport, TConfiguration::default())
81 }
82
83 /// Create a `TCompactInputProtocol` with custom configuration.
84 pub fn with_config(transport: T, config: TConfiguration) -> TCompactInputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -040085 TCompactInputProtocol {
86 last_read_field_id: 0,
87 read_field_id_stack: Vec::new(),
88 pending_read_bool_value: None,
Allen George7ddbcc02020-11-08 09:51:19 -050089 transport,
Hasnain Lakhani42d0b712025-07-17 19:57:05 -070090 config,
91 recursion_depth: 0,
Allen George8b96bfb2016-11-02 08:01:08 -040092 }
93 }
94
Allen Georgeb0d14132020-03-29 11:48:55 -040095 fn read_list_set_begin(&mut self) -> crate::Result<(TType, i32)> {
Allen George8b96bfb2016-11-02 08:01:08 -040096 let header = self.read_byte()?;
97 let element_type = collection_u8_to_type(header & 0x0F)?;
98
Allen George8b96bfb2016-11-02 08:01:08 -040099 let possible_element_count = (header & 0xF0) >> 4;
Tdxdxoz85d82bf2022-07-17 14:14:12 +0200100 let element_count = if possible_element_count != 15 {
Allen George8b96bfb2016-11-02 08:01:08 -0400101 // high bits set high if count and type encoded separately
Tdxdxoz85d82bf2022-07-17 14:14:12 +0200102 possible_element_count as i32
Allen George8b96bfb2016-11-02 08:01:08 -0400103 } else {
Tdxdxoz85d82bf2022-07-17 14:14:12 +0200104 self.transport.read_varint::<u32>()? as i32
105 };
Allen George8b96bfb2016-11-02 08:01:08 -0400106
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700107 let min_element_size = self.min_serialized_size(element_type);
108 super::check_container_size(&self.config, element_count, min_element_size)?;
109
Allen George8b96bfb2016-11-02 08:01:08 -0400110 Ok((element_type, element_count))
111 }
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700112
113 fn check_recursion_depth(&self) -> crate::Result<()> {
114 if let Some(limit) = self.config.max_recursion_depth() {
115 if self.recursion_depth >= limit {
116 return Err(crate::Error::Protocol(ProtocolError::new(
117 ProtocolErrorKind::DepthLimit,
118 format!("Maximum recursion depth {} exceeded", limit),
119 )));
120 }
121 }
122 Ok(())
123 }
Allen George8b96bfb2016-11-02 08:01:08 -0400124}
125
Allen George0e22c362017-01-30 07:15:00 -0500126impl<T> TInputProtocol for TCompactInputProtocol<T>
127where
128 T: TReadTransport,
129{
Allen Georgeb0d14132020-03-29 11:48:55 -0400130 fn read_message_begin(&mut self) -> crate::Result<TMessageIdentifier> {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700131 // TODO: Once specialization is stable, call the message size tracking here
Allen George8b96bfb2016-11-02 08:01:08 -0400132 let compact_id = self.read_byte()?;
133 if compact_id != COMPACT_PROTOCOL_ID {
Allen Georgeb0d14132020-03-29 11:48:55 -0400134 Err(crate::Error::Protocol(crate::ProtocolError {
135 kind: crate::ProtocolErrorKind::BadVersion,
Allen Georgeef7a1892018-12-16 18:01:37 -0500136 message: format!("invalid compact protocol header {:?}", compact_id),
137 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400138 } else {
139 Ok(())
140 }?;
141
142 let type_and_byte = self.read_byte()?;
143 let received_version = type_and_byte & COMPACT_VERSION_MASK;
144 if received_version != COMPACT_VERSION {
Allen Georgeb0d14132020-03-29 11:48:55 -0400145 Err(crate::Error::Protocol(crate::ProtocolError {
146 kind: crate::ProtocolErrorKind::BadVersion,
Allen Georgeef7a1892018-12-16 18:01:37 -0500147 message: format!(
148 "cannot process compact protocol version {:?}",
149 received_version
Allen George0e22c362017-01-30 07:15:00 -0500150 ),
Allen Georgeef7a1892018-12-16 18:01:37 -0500151 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400152 } else {
153 Ok(())
154 }?;
155
156 // NOTE: unsigned right shift will pad with 0s
157 let message_type: TMessageType = TMessageType::try_from(type_and_byte >> 5)?;
Allen George48905102021-02-20 08:47:01 -0500158 // writing side wrote signed sequence number as u32 to avoid zigzag encoding
159 let sequence_number = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400160 let service_call_name = self.read_string()?;
161
162 self.last_read_field_id = 0;
163
Allen Georgeef7a1892018-12-16 18:01:37 -0500164 Ok(TMessageIdentifier::new(
165 service_call_name,
166 message_type,
167 sequence_number,
168 ))
Allen George8b96bfb2016-11-02 08:01:08 -0400169 }
170
Allen Georgeb0d14132020-03-29 11:48:55 -0400171 fn read_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400172 Ok(())
173 }
174
Allen Georgeb0d14132020-03-29 11:48:55 -0400175 fn read_struct_begin(&mut self) -> crate::Result<Option<TStructIdentifier>> {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700176 self.check_recursion_depth()?;
177 self.recursion_depth += 1;
Allen George8b96bfb2016-11-02 08:01:08 -0400178 self.read_field_id_stack.push(self.last_read_field_id);
179 self.last_read_field_id = 0;
180 Ok(None)
181 }
182
Allen Georgeb0d14132020-03-29 11:48:55 -0400183 fn read_struct_end(&mut self) -> crate::Result<()> {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700184 self.recursion_depth -= 1;
Allen Georgeef7a1892018-12-16 18:01:37 -0500185 self.last_read_field_id = self
186 .read_field_id_stack
Allen George8b96bfb2016-11-02 08:01:08 -0400187 .pop()
188 .expect("should have previous field ids");
189 Ok(())
190 }
191
Allen Georgeb0d14132020-03-29 11:48:55 -0400192 fn read_field_begin(&mut self) -> crate::Result<TFieldIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400193 // we can read at least one byte, which is:
194 // - the type
195 // - the field delta and the type
196 let field_type = self.read_byte()?;
197 let field_delta = (field_type & 0xF0) >> 4;
198 let field_type = match field_type & 0x0F {
199 0x01 => {
200 self.pending_read_bool_value = Some(true);
201 Ok(TType::Bool)
202 }
203 0x02 => {
204 self.pending_read_bool_value = Some(false);
205 Ok(TType::Bool)
206 }
207 ttu8 => u8_to_type(ttu8),
208 }?;
209
210 match field_type {
Allen Georgeef7a1892018-12-16 18:01:37 -0500211 TType::Stop => Ok(
212 TFieldIdentifier::new::<Option<String>, String, Option<i16>>(
213 None,
214 TType::Stop,
215 None,
216 ),
217 ),
Allen George8b96bfb2016-11-02 08:01:08 -0400218 _ => {
219 if field_delta != 0 {
220 self.last_read_field_id += field_delta as i16;
221 } else {
222 self.last_read_field_id = self.read_i16()?;
223 };
224
Allen Georgeef7a1892018-12-16 18:01:37 -0500225 Ok(TFieldIdentifier {
226 name: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500227 field_type,
Allen Georgeef7a1892018-12-16 18:01:37 -0500228 id: Some(self.last_read_field_id),
229 })
Allen George8b96bfb2016-11-02 08:01:08 -0400230 }
231 }
232 }
233
Allen Georgeb0d14132020-03-29 11:48:55 -0400234 fn read_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400235 Ok(())
236 }
237
Allen Georgeb0d14132020-03-29 11:48:55 -0400238 fn read_bool(&mut self) -> crate::Result<bool> {
Allen George8b96bfb2016-11-02 08:01:08 -0400239 match self.pending_read_bool_value.take() {
240 Some(b) => Ok(b),
241 None => {
242 let b = self.read_byte()?;
243 match b {
Jörn Horstmann717bd792025-02-02 23:10:27 +0100244 // Previous versions of the thrift compact protocol specification said to use 0
245 // and 1 inside collections, but that differed from existing implementations.
246 // The specification was updated in https://github.com/apache/thrift/commit/2c29c5665bc442e703480bb0ee60fe925ffe02e8.
247 0x00 => Ok(false),
Allen George8b96bfb2016-11-02 08:01:08 -0400248 0x01 => Ok(true),
249 0x02 => Ok(false),
Allen Georgeb0d14132020-03-29 11:48:55 -0400250 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
251 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500252 message: format!("cannot convert {} into bool", unkn),
253 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400254 }
255 }
256 }
257 }
258
Allen Georgeb0d14132020-03-29 11:48:55 -0400259 fn read_bytes(&mut self) -> crate::Result<Vec<u8>> {
Allen George0e22c362017-01-30 07:15:00 -0500260 let len = self.transport.read_varint::<u32>()?;
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700261
262 if let Some(max_size) = self.config.max_string_size() {
263 if len as usize > max_size {
264 return Err(crate::Error::Protocol(ProtocolError::new(
265 ProtocolErrorKind::SizeLimit,
266 format!(
267 "Byte array size {} exceeds maximum allowed size of {}",
268 len, max_size
269 ),
270 )));
271 }
272 }
273
Allen George8b96bfb2016-11-02 08:01:08 -0400274 let mut buf = vec![0u8; len as usize];
Allen George0e22c362017-01-30 07:15:00 -0500275 self.transport
276 .read_exact(&mut buf)
277 .map_err(From::from)
278 .map(|_| buf)
Allen George8b96bfb2016-11-02 08:01:08 -0400279 }
280
Allen Georgeb0d14132020-03-29 11:48:55 -0400281 fn read_i8(&mut self) -> crate::Result<i8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400282 self.read_byte().map(|i| i as i8)
283 }
284
Allen Georgeb0d14132020-03-29 11:48:55 -0400285 fn read_i16(&mut self) -> crate::Result<i16> {
Allen George0e22c362017-01-30 07:15:00 -0500286 self.transport.read_varint::<i16>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400287 }
288
Allen Georgeb0d14132020-03-29 11:48:55 -0400289 fn read_i32(&mut self) -> crate::Result<i32> {
Allen George0e22c362017-01-30 07:15:00 -0500290 self.transport.read_varint::<i32>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400291 }
292
Allen Georgeb0d14132020-03-29 11:48:55 -0400293 fn read_i64(&mut self) -> crate::Result<i64> {
Allen George0e22c362017-01-30 07:15:00 -0500294 self.transport.read_varint::<i64>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400295 }
296
Allen Georgeb0d14132020-03-29 11:48:55 -0400297 fn read_double(&mut self) -> crate::Result<f64> {
Allen George8a1743d2020-12-05 01:19:27 -0500298 self.transport
299 .read_f64::<LittleEndian>()
300 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400301 }
302
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800303 fn read_uuid(&mut self) -> crate::Result<uuid::Uuid> {
Hasnain Lakhani57c5fc12025-08-02 21:12:07 -0700304 let mut buf = [0u8; 16];
305 self.transport
306 .read_exact(&mut buf)
307 .map(|_| uuid::Uuid::from_bytes(buf))
308 .map_err(From::from)
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800309 }
310
Allen Georgeb0d14132020-03-29 11:48:55 -0400311 fn read_string(&mut self) -> crate::Result<String> {
Allen George8b96bfb2016-11-02 08:01:08 -0400312 let bytes = self.read_bytes()?;
313 String::from_utf8(bytes).map_err(From::from)
314 }
315
Allen Georgeb0d14132020-03-29 11:48:55 -0400316 fn read_list_begin(&mut self) -> crate::Result<TListIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400317 let (element_type, element_count) = self.read_list_set_begin()?;
318 Ok(TListIdentifier::new(element_type, element_count))
319 }
320
Allen Georgeb0d14132020-03-29 11:48:55 -0400321 fn read_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400322 Ok(())
323 }
324
Allen Georgeb0d14132020-03-29 11:48:55 -0400325 fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400326 let (element_type, element_count) = self.read_list_set_begin()?;
327 Ok(TSetIdentifier::new(element_type, element_count))
328 }
329
Allen Georgeb0d14132020-03-29 11:48:55 -0400330 fn read_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400331 Ok(())
332 }
333
Allen Georgeb0d14132020-03-29 11:48:55 -0400334 fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier> {
Allen George0e22c362017-01-30 07:15:00 -0500335 let element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400336 if element_count == 0 {
337 Ok(TMapIdentifier::new(None, None, 0))
338 } else {
339 let type_header = self.read_byte()?;
340 let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
341 let val_type = collection_u8_to_type(type_header & 0x0F)?;
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700342
343 let key_min_size = self.min_serialized_size(key_type);
344 let value_min_size = self.min_serialized_size(val_type);
345 let element_size = key_min_size + value_min_size;
346 super::check_container_size(&self.config, element_count, element_size)?;
347
Allen George8b96bfb2016-11-02 08:01:08 -0400348 Ok(TMapIdentifier::new(key_type, val_type, element_count))
349 }
350 }
351
Allen Georgeb0d14132020-03-29 11:48:55 -0400352 fn read_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400353 Ok(())
354 }
355
356 // utility
357 //
358
Allen Georgeb0d14132020-03-29 11:48:55 -0400359 fn read_byte(&mut self) -> crate::Result<u8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400360 let mut buf = [0u8; 1];
Allen George0e22c362017-01-30 07:15:00 -0500361 self.transport
362 .read_exact(&mut buf)
363 .map_err(From::from)
364 .map(|_| buf[0])
Allen George8b96bfb2016-11-02 08:01:08 -0400365 }
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700366
367 fn min_serialized_size(&self, field_type: TType) -> usize {
368 compact_protocol_min_serialized_size(field_type)
369 }
370}
371
372pub(crate) fn compact_protocol_min_serialized_size(field_type: TType) -> usize {
373 match field_type {
374 TType::Stop => 1, // 1 byte
375 TType::Void => 1, // 1 byte
376 TType::Bool => 1, // 1 byte
377 TType::I08 => 1, // 1 byte
378 TType::Double => 8, // 8 bytes (not varint encoded)
379 TType::I16 => 1, // 1 byte minimum (varint)
380 TType::I32 => 1, // 1 byte minimum (varint)
381 TType::I64 => 1, // 1 byte minimum (varint)
382 TType::String => 1, // 1 byte minimum for length (varint)
383 TType::Struct => 1, // 1 byte minimum (stop field)
384 TType::Map => 1, // 1 byte minimum
385 TType::Set => 1, // 1 byte minimum
386 TType::List => 1, // 1 byte minimum
387 TType::Uuid => 16, // 16 bytes
388 TType::Utf7 => 1, // 1 byte
389 }
Allen George8b96bfb2016-11-02 08:01:08 -0400390}
391
Vadim Chekand3355af2018-01-05 23:12:47 -0500392impl<T> io::Seek for TCompactInputProtocol<T>
393where
394 T: io::Seek + TReadTransport,
395{
396 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
397 self.transport.seek(pos)
398 }
399}
400
Allen George8b96bfb2016-11-02 08:01:08 -0400401/// Factory for creating instances of `TCompactInputProtocol`.
402#[derive(Default)]
403pub struct TCompactInputProtocolFactory;
404
405impl TCompactInputProtocolFactory {
406 /// Create a `TCompactInputProtocolFactory`.
407 pub fn new() -> TCompactInputProtocolFactory {
408 TCompactInputProtocolFactory {}
409 }
410}
411
412impl TInputProtocolFactory for TCompactInputProtocolFactory {
Danny Browning77d96c12019-08-21 13:41:07 -0600413 fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500414 Box::new(TCompactInputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400415 }
416}
417
418/// Write messages using the Thrift compact protocol.
419///
420/// # Examples
421///
422/// Create and use a `TCompactOutputProtocol`.
423///
424/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -0400425/// use thrift::protocol::{TCompactOutputProtocol, TOutputProtocol};
Allen George0e22c362017-01-30 07:15:00 -0500426/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -0400427///
Allen George0e22c362017-01-30 07:15:00 -0500428/// let mut channel = TTcpChannel::new();
429/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400430///
Allen George0e22c362017-01-30 07:15:00 -0500431/// let mut protocol = TCompactOutputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -0400432///
Allen George0e22c362017-01-30 07:15:00 -0500433/// protocol.write_bool(true).unwrap();
434/// protocol.write_string("test_string").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400435/// ```
Allen George0e22c362017-01-30 07:15:00 -0500436#[derive(Debug)]
437pub struct TCompactOutputProtocol<T>
438where
439 T: TWriteTransport,
440{
Allen George8b96bfb2016-11-02 08:01:08 -0400441 // Identifier of the last field serialized for a struct.
442 last_write_field_id: i16,
Allen George0e22c362017-01-30 07:15:00 -0500443 // Stack of the last written field ids (new entry added each time a nested struct is written).
Allen George8b96bfb2016-11-02 08:01:08 -0400444 write_field_id_stack: Vec<i16>,
445 // Field identifier of the boolean field to be written.
446 // Saved because boolean fields and their value are encoded in a single byte
447 pending_write_bool_field_identifier: Option<TFieldIdentifier>,
448 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -0500449 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -0400450}
451
Allen George0e22c362017-01-30 07:15:00 -0500452impl<T> TCompactOutputProtocol<T>
453where
454 T: TWriteTransport,
455{
Allen George8b96bfb2016-11-02 08:01:08 -0400456 /// Create a `TCompactOutputProtocol` that writes bytes to `transport`.
Allen George0e22c362017-01-30 07:15:00 -0500457 pub fn new(transport: T) -> TCompactOutputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -0400458 TCompactOutputProtocol {
459 last_write_field_id: 0,
460 write_field_id_stack: Vec::new(),
461 pending_write_bool_field_identifier: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500462 transport,
Allen George8b96bfb2016-11-02 08:01:08 -0400463 }
464 }
465
466 // FIXME: field_type as unconstrained u8 is bad
Allen Georgeb0d14132020-03-29 11:48:55 -0400467 fn write_field_header(&mut self, field_type: u8, field_id: i16) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400468 let field_delta = field_id - self.last_write_field_id;
469 if field_delta > 0 && field_delta < 15 {
470 self.write_byte(((field_delta as u8) << 4) | field_type)?;
471 } else {
472 self.write_byte(field_type)?;
473 self.write_i16(field_id)?;
474 }
475 self.last_write_field_id = field_id;
476 Ok(())
477 }
478
Allen George8a1743d2020-12-05 01:19:27 -0500479 fn write_list_set_begin(
480 &mut self,
481 element_type: TType,
482 element_count: i32,
483 ) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400484 let elem_identifier = collection_type_to_u8(element_type);
485 if element_count <= 14 {
Hasnain Lakhani7ac79ab2025-08-25 14:40:43 -0700486 let header = ((element_count as u8) << 4) | elem_identifier;
Allen George8b96bfb2016-11-02 08:01:08 -0400487 self.write_byte(header)
488 } else {
489 let header = 0xF0 | elem_identifier;
490 self.write_byte(header)?;
Allen George48905102021-02-20 08:47:01 -0500491 // element count is strictly positive as per the spec, so
492 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George8b96bfb2016-11-02 08:01:08 -0400493 self.transport
Allen George8b96bfb2016-11-02 08:01:08 -0400494 .write_varint(element_count as u32)
495 .map_err(From::from)
496 .map(|_| ())
497 }
498 }
499
500 fn assert_no_pending_bool_write(&self) {
501 if let Some(ref f) = self.pending_write_bool_field_identifier {
502 panic!("pending bool field {:?} not written", f)
503 }
504 }
505}
506
Allen George0e22c362017-01-30 07:15:00 -0500507impl<T> TOutputProtocol for TCompactOutputProtocol<T>
508where
509 T: TWriteTransport,
510{
Allen Georgeb0d14132020-03-29 11:48:55 -0400511 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400512 self.write_byte(COMPACT_PROTOCOL_ID)?;
513 self.write_byte((u8::from(identifier.message_type) << 5) | COMPACT_VERSION)?;
Allen George48905102021-02-20 08:47:01 -0500514 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George55c3e4c2021-03-01 23:19:52 -0500515 self.transport
516 .write_varint(identifier.sequence_number as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400517 self.write_string(&identifier.name)?;
518 Ok(())
519 }
520
Allen Georgeb0d14132020-03-29 11:48:55 -0400521 fn write_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400522 self.assert_no_pending_bool_write();
523 Ok(())
524 }
525
Allen Georgeb0d14132020-03-29 11:48:55 -0400526 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400527 self.write_field_id_stack.push(self.last_write_field_id);
528 self.last_write_field_id = 0;
529 Ok(())
530 }
531
Allen Georgeb0d14132020-03-29 11:48:55 -0400532 fn write_struct_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400533 self.assert_no_pending_bool_write();
Allen Georgeef7a1892018-12-16 18:01:37 -0500534 self.last_write_field_id = self
535 .write_field_id_stack
Allen George0e22c362017-01-30 07:15:00 -0500536 .pop()
537 .expect("should have previous field ids");
Allen George8b96bfb2016-11-02 08:01:08 -0400538 Ok(())
539 }
540
Allen Georgeb0d14132020-03-29 11:48:55 -0400541 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400542 match identifier.field_type {
543 TType::Bool => {
544 if self.pending_write_bool_field_identifier.is_some() {
Allen George0e22c362017-01-30 07:15:00 -0500545 panic!(
546 "should not have a pending bool while writing another bool with id: \
Allen Georgeef7a1892018-12-16 18:01:37 -0500547 {:?}",
Allen George0e22c362017-01-30 07:15:00 -0500548 identifier
549 )
Allen George8b96bfb2016-11-02 08:01:08 -0400550 }
551 self.pending_write_bool_field_identifier = Some(identifier.clone());
552 Ok(())
553 }
554 _ => {
555 let field_type = type_to_u8(identifier.field_type);
Allen Georgeef7a1892018-12-16 18:01:37 -0500556 let field_id = identifier.id.expect("non-stop field should have field id");
Allen George8b96bfb2016-11-02 08:01:08 -0400557 self.write_field_header(field_type, field_id)
558 }
559 }
560 }
561
Allen Georgeb0d14132020-03-29 11:48:55 -0400562 fn write_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400563 self.assert_no_pending_bool_write();
564 Ok(())
565 }
566
Allen Georgeb0d14132020-03-29 11:48:55 -0400567 fn write_field_stop(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400568 self.assert_no_pending_bool_write();
569 self.write_byte(type_to_u8(TType::Stop))
570 }
571
Allen Georgeb0d14132020-03-29 11:48:55 -0400572 fn write_bool(&mut self, b: bool) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400573 match self.pending_write_bool_field_identifier.take() {
574 Some(pending) => {
575 let field_id = pending.id.expect("bool field should have a field id");
576 let field_type_as_u8 = if b { 0x01 } else { 0x02 };
577 self.write_field_header(field_type_as_u8, field_id)
578 }
579 None => {
580 if b {
581 self.write_byte(0x01)
582 } else {
583 self.write_byte(0x02)
584 }
585 }
586 }
587 }
588
Allen Georgeb0d14132020-03-29 11:48:55 -0400589 fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> {
Allen George48905102021-02-20 08:47:01 -0500590 // length is strictly positive as per the spec, so
591 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500592 self.transport.write_varint(b.len() as u32)?;
593 self.transport.write_all(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400594 }
595
Allen Georgeb0d14132020-03-29 11:48:55 -0400596 fn write_i8(&mut self, i: i8) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400597 self.write_byte(i as u8)
598 }
599
Allen Georgeb0d14132020-03-29 11:48:55 -0400600 fn write_i16(&mut self, i: i16) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500601 self.transport
Allen George48905102021-02-20 08:47:01 -0500602 .write_varint(i)
Allen George0e22c362017-01-30 07:15:00 -0500603 .map_err(From::from)
604 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400605 }
606
Allen Georgeb0d14132020-03-29 11:48:55 -0400607 fn write_i32(&mut self, i: i32) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500608 self.transport
609 .write_varint(i)
610 .map_err(From::from)
611 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400612 }
613
Allen Georgeb0d14132020-03-29 11:48:55 -0400614 fn write_i64(&mut self, i: i64) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500615 self.transport
616 .write_varint(i)
617 .map_err(From::from)
618 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400619 }
620
Allen Georgeb0d14132020-03-29 11:48:55 -0400621 fn write_double(&mut self, d: f64) -> crate::Result<()> {
Allen George8a1743d2020-12-05 01:19:27 -0500622 self.transport
623 .write_f64::<LittleEndian>(d)
624 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400625 }
626
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800627 fn write_uuid(&mut self, uuid: &uuid::Uuid) -> crate::Result<()> {
Hasnain Lakhani57c5fc12025-08-02 21:12:07 -0700628 self.transport
629 .write_all(uuid.as_bytes())
630 .map_err(From::from)
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800631 }
632
Allen Georgeb0d14132020-03-29 11:48:55 -0400633 fn write_string(&mut self, s: &str) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400634 self.write_bytes(s.as_bytes())
635 }
636
Allen Georgeb0d14132020-03-29 11:48:55 -0400637 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400638 self.write_list_set_begin(identifier.element_type, identifier.size)
639 }
640
Allen Georgeb0d14132020-03-29 11:48:55 -0400641 fn write_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400642 Ok(())
643 }
644
Allen Georgeb0d14132020-03-29 11:48:55 -0400645 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> 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_set_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_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400654 if identifier.size == 0 {
655 self.write_byte(0)
656 } else {
Allen George48905102021-02-20 08:47:01 -0500657 // element count is strictly positive as per the spec, so
658 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500659 self.transport.write_varint(identifier.size as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400660
Allen George0e22c362017-01-30 07:15:00 -0500661 let key_type = identifier
662 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400663 .expect("map identifier to write should contain key type");
664 let key_type_byte = collection_type_to_u8(key_type) << 4;
665
Allen George0e22c362017-01-30 07:15:00 -0500666 let val_type = identifier
667 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400668 .expect("map identifier to write should contain value type");
669 let val_type_byte = collection_type_to_u8(val_type);
670
671 let map_type_header = key_type_byte | val_type_byte;
672 self.write_byte(map_type_header)
673 }
674 }
675
Allen Georgeb0d14132020-03-29 11:48:55 -0400676 fn write_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400677 Ok(())
678 }
679
Allen Georgeb0d14132020-03-29 11:48:55 -0400680 fn flush(&mut self) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500681 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400682 }
683
684 // utility
685 //
686
Allen Georgeb0d14132020-03-29 11:48:55 -0400687 fn write_byte(&mut self, b: u8) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500688 self.transport.write(&[b]).map_err(From::from).map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400689 }
690}
691
692/// Factory for creating instances of `TCompactOutputProtocol`.
693#[derive(Default)]
694pub struct TCompactOutputProtocolFactory;
695
696impl TCompactOutputProtocolFactory {
697 /// Create a `TCompactOutputProtocolFactory`.
698 pub fn new() -> TCompactOutputProtocolFactory {
699 TCompactOutputProtocolFactory {}
700 }
701}
702
703impl TOutputProtocolFactory for TCompactOutputProtocolFactory {
Allen George8a1743d2020-12-05 01:19:27 -0500704 fn create(
705 &self,
706 transport: Box<dyn TWriteTransport + Send>,
707 ) -> Box<dyn TOutputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500708 Box::new(TCompactOutputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400709 }
710}
711
712fn collection_type_to_u8(field_type: TType) -> u8 {
713 match field_type {
714 TType::Bool => 0x01,
715 f => type_to_u8(f),
716 }
717}
718
719fn type_to_u8(field_type: TType) -> u8 {
720 match field_type {
721 TType::Stop => 0x00,
722 TType::I08 => 0x03, // equivalent to TType::Byte
723 TType::I16 => 0x04,
724 TType::I32 => 0x05,
725 TType::I64 => 0x06,
726 TType::Double => 0x07,
727 TType::String => 0x08,
728 TType::List => 0x09,
729 TType::Set => 0x0A,
730 TType::Map => 0x0B,
731 TType::Struct => 0x0C,
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800732 TType::Uuid => 0x0D,
Allen George2b691ee2021-10-14 22:25:07 -0400733 _ => panic!("should not have attempted to convert {} to u8", field_type),
Allen George8b96bfb2016-11-02 08:01:08 -0400734 }
735}
736
Allen Georgeb0d14132020-03-29 11:48:55 -0400737fn collection_u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400738 match b {
Jörn Horstmann717bd792025-02-02 23:10:27 +0100739 // For historical and compatibility reasons, a reader should be capable to deal with both cases.
740 // The only valid value in the original spec was 2, but due to a widespread implementation bug
741 // the defacto standard across large parts of the library became 1 instead.
742 // As a result, both values are now allowed.
743 0x01 | 0x02 => Ok(TType::Bool),
Allen George8b96bfb2016-11-02 08:01:08 -0400744 o => u8_to_type(o),
745 }
746}
747
Allen Georgeb0d14132020-03-29 11:48:55 -0400748fn u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400749 match b {
750 0x00 => Ok(TType::Stop),
751 0x03 => Ok(TType::I08), // equivalent to TType::Byte
752 0x04 => Ok(TType::I16),
753 0x05 => Ok(TType::I32),
754 0x06 => Ok(TType::I64),
755 0x07 => Ok(TType::Double),
756 0x08 => Ok(TType::String),
757 0x09 => Ok(TType::List),
758 0x0A => Ok(TType::Set),
759 0x0B => Ok(TType::Map),
760 0x0C => Ok(TType::Struct),
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800761 0x0D => Ok(TType::Uuid),
Allen Georgeb0d14132020-03-29 11:48:55 -0400762 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
763 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500764 message: format!("cannot convert {} into TType", unkn),
765 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400766 }
767}
768
769#[cfg(test)]
770mod tests {
771
Allen Georgeb0d14132020-03-29 11:48:55 -0400772 use crate::protocol::{
Allen Georgeef7a1892018-12-16 18:01:37 -0500773 TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
774 TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
775 };
Allen Georgeb0d14132020-03-29 11:48:55 -0400776 use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400777
778 use super::*;
779
780 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500781 fn must_write_message_begin_largest_maximum_positive_sequence_number() {
782 let (_, mut o_prot) = test_objects();
783
784 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
785 "bar",
786 TMessageType::Reply,
787 i32::MAX
788 )));
789
790 #[rustfmt::skip]
791 let expected: [u8; 11] = [
792 0x82, /* protocol ID */
793 0x41, /* message type | protocol version */
794 0xFF,
795 0xFF,
796 0xFF,
797 0xFF,
798 0x07, /* non-zig-zag varint sequence number */
799 0x03, /* message-name length */
800 0x62,
801 0x61,
802 0x72 /* "bar" */,
803 ];
804
805 assert_eq_written_bytes!(o_prot, expected);
806 }
807
808 #[test]
809 fn must_read_message_begin_largest_maximum_positive_sequence_number() {
810 let (mut i_prot, _) = test_objects();
811
812 #[rustfmt::skip]
813 let source_bytes: [u8; 11] = [
814 0x82, /* protocol ID */
815 0x41, /* message type | protocol version */
816 0xFF,
817 0xFF,
818 0xFF,
819 0xFF,
820 0x07, /* non-zig-zag varint sequence number */
821 0x03, /* message-name length */
822 0x62,
823 0x61,
824 0x72 /* "bar" */,
825 ];
826
827 i_prot.transport.set_readable_bytes(&source_bytes);
828
829 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MAX);
830 let res = assert_success!(i_prot.read_message_begin());
831
832 assert_eq!(&expected, &res);
833 }
834
835 #[test]
836 fn must_write_message_begin_positive_sequence_number_0() {
Allen George0e22c362017-01-30 07:15:00 -0500837 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400838
Allen Georgeef7a1892018-12-16 18:01:37 -0500839 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
840 "foo",
841 TMessageType::Call,
842 431
843 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400844
Allen George7ddbcc02020-11-08 09:51:19 -0500845 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500846 let expected: [u8; 8] = [
847 0x82, /* protocol ID */
848 0x21, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500849 0xAF,
850 0x03, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500851 0x03, /* message-name length */
852 0x66,
853 0x6F,
854 0x6F /* "foo" */,
855 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400856
Allen George0e22c362017-01-30 07:15:00 -0500857 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400858 }
859
860 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500861 fn must_read_message_begin_positive_sequence_number_0() {
862 let (mut i_prot, _) = test_objects();
863
864 #[rustfmt::skip]
865 let source_bytes: [u8; 8] = [
866 0x82, /* protocol ID */
867 0x21, /* message type | protocol version */
868 0xAF,
869 0x03, /* non-zig-zag varint sequence number */
870 0x03, /* message-name length */
871 0x66,
872 0x6F,
873 0x6F /* "foo" */,
874 ];
875
876 i_prot.transport.set_readable_bytes(&source_bytes);
877
878 let expected = TMessageIdentifier::new("foo", TMessageType::Call, 431);
879 let res = assert_success!(i_prot.read_message_begin());
880
881 assert_eq!(&expected, &res);
882 }
883
884 #[test]
885 fn must_write_message_begin_positive_sequence_number_1() {
Allen George0e22c362017-01-30 07:15:00 -0500886 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400887
Allen Georgeef7a1892018-12-16 18:01:37 -0500888 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
889 "bar",
890 TMessageType::Reply,
Allen George7ddbcc02020-11-08 09:51:19 -0500891 991_828
Allen Georgeef7a1892018-12-16 18:01:37 -0500892 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400893
Allen George7ddbcc02020-11-08 09:51:19 -0500894 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500895 let expected: [u8; 9] = [
896 0x82, /* protocol ID */
897 0x41, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500898 0xD4,
899 0xC4,
900 0x3C, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500901 0x03, /* message-name length */
902 0x62,
903 0x61,
904 0x72 /* "bar" */,
905 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400906
Allen George0e22c362017-01-30 07:15:00 -0500907 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400908 }
909
910 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500911 fn must_read_message_begin_positive_sequence_number_1() {
912 let (mut i_prot, _) = test_objects();
913
914 #[rustfmt::skip]
915 let source_bytes: [u8; 9] = [
916 0x82, /* protocol ID */
917 0x41, /* message type | protocol version */
918 0xD4,
919 0xC4,
920 0x3C, /* non-zig-zag varint sequence number */
921 0x03, /* message-name length */
922 0x62,
923 0x61,
924 0x72 /* "bar" */,
925 ];
926
927 i_prot.transport.set_readable_bytes(&source_bytes);
928
929 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 991_828);
930 let res = assert_success!(i_prot.read_message_begin());
931
932 assert_eq!(&expected, &res);
933 }
934
935 #[test]
936 fn must_write_message_begin_zero_sequence_number() {
937 let (_, mut o_prot) = test_objects();
938
939 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
940 "bar",
941 TMessageType::Reply,
942 0
943 )));
944
945 #[rustfmt::skip]
946 let expected: [u8; 7] = [
947 0x82, /* protocol ID */
948 0x41, /* message type | protocol version */
949 0x00, /* non-zig-zag varint sequence number */
950 0x03, /* message-name length */
951 0x62,
952 0x61,
953 0x72 /* "bar" */,
954 ];
955
956 assert_eq_written_bytes!(o_prot, expected);
957 }
958
959 #[test]
960 fn must_read_message_begin_zero_sequence_number() {
961 let (mut i_prot, _) = test_objects();
962
963 #[rustfmt::skip]
964 let source_bytes: [u8; 7] = [
965 0x82, /* protocol ID */
966 0x41, /* message type | protocol version */
967 0x00, /* non-zig-zag varint sequence number */
968 0x03, /* message-name length */
969 0x62,
970 0x61,
971 0x72 /* "bar" */,
972 ];
973
974 i_prot.transport.set_readable_bytes(&source_bytes);
975
976 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 0);
977 let res = assert_success!(i_prot.read_message_begin());
978
979 assert_eq!(&expected, &res);
980 }
981
982 #[test]
983 fn must_write_message_begin_largest_minimum_negative_sequence_number() {
984 let (_, mut o_prot) = test_objects();
985
986 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
987 "bar",
988 TMessageType::Reply,
989 i32::MIN
990 )));
991
992 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
993 #[rustfmt::skip]
994 let expected: [u8; 11] = [
995 0x82, /* protocol ID */
996 0x41, /* message type | protocol version */
997 0x80,
998 0x80,
999 0x80,
1000 0x80,
1001 0x08, /* non-zig-zag varint sequence number */
1002 0x03, /* message-name length */
1003 0x62,
1004 0x61,
1005 0x72 /* "bar" */,
1006 ];
1007
1008 assert_eq_written_bytes!(o_prot, expected);
1009 }
1010
1011 #[test]
1012 fn must_read_message_begin_largest_minimum_negative_sequence_number() {
1013 let (mut i_prot, _) = test_objects();
1014
1015 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
1016 #[rustfmt::skip]
1017 let source_bytes: [u8; 11] = [
1018 0x82, /* protocol ID */
1019 0x41, /* message type | protocol version */
1020 0x80,
1021 0x80,
1022 0x80,
1023 0x80,
1024 0x08, /* non-zig-zag varint sequence number */
1025 0x03, /* message-name length */
1026 0x62,
1027 0x61,
1028 0x72 /* "bar" */,
1029 ];
1030
1031 i_prot.transport.set_readable_bytes(&source_bytes);
1032
1033 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MIN);
1034 let res = assert_success!(i_prot.read_message_begin());
1035
1036 assert_eq!(&expected, &res);
1037 }
1038
1039 #[test]
1040 fn must_write_message_begin_negative_sequence_number_0() {
1041 let (_, mut o_prot) = test_objects();
1042
1043 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1044 "foo",
1045 TMessageType::Call,
1046 -431
1047 )));
1048
1049 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
1050 #[rustfmt::skip]
1051 let expected: [u8; 11] = [
1052 0x82, /* protocol ID */
1053 0x21, /* message type | protocol version */
1054 0xD1,
1055 0xFC,
1056 0xFF,
1057 0xFF,
1058 0x0F, /* non-zig-zag varint sequence number */
1059 0x03, /* message-name length */
1060 0x66,
1061 0x6F,
1062 0x6F /* "foo" */,
1063 ];
1064
1065 assert_eq_written_bytes!(o_prot, expected);
1066 }
1067
1068 #[test]
1069 fn must_read_message_begin_negative_sequence_number_0() {
1070 let (mut i_prot, _) = test_objects();
1071
1072 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
1073 #[rustfmt::skip]
1074 let source_bytes: [u8; 11] = [
1075 0x82, /* protocol ID */
1076 0x21, /* message type | protocol version */
1077 0xD1,
1078 0xFC,
1079 0xFF,
1080 0xFF,
1081 0x0F, /* non-zig-zag varint sequence number */
1082 0x03, /* message-name length */
1083 0x66,
1084 0x6F,
1085 0x6F /* "foo" */,
1086 ];
1087
1088 i_prot.transport.set_readable_bytes(&source_bytes);
1089
1090 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -431);
1091 let res = assert_success!(i_prot.read_message_begin());
1092
1093 assert_eq!(&expected, &res);
1094 }
1095
1096 #[test]
1097 fn must_write_message_begin_negative_sequence_number_1() {
1098 let (_, mut o_prot) = test_objects();
1099
1100 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1101 "foo",
1102 TMessageType::Call,
1103 -73_184_125
1104 )));
1105
1106 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1107 #[rustfmt::skip]
1108 let expected: [u8; 11] = [
1109 0x82, /* protocol ID */
1110 0x21, /* message type | protocol version */
1111 0x83,
1112 0x99,
1113 0x8D,
1114 0xDD,
1115 0x0F, /* non-zig-zag varint sequence number */
1116 0x03, /* message-name length */
1117 0x66,
1118 0x6F,
1119 0x6F /* "foo" */,
1120 ];
1121
1122 assert_eq_written_bytes!(o_prot, expected);
1123 }
1124
1125 #[test]
1126 fn must_read_message_begin_negative_sequence_number_1() {
1127 let (mut i_prot, _) = test_objects();
1128
1129 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1130 #[rustfmt::skip]
1131 let source_bytes: [u8; 11] = [
1132 0x82, /* protocol ID */
1133 0x21, /* message type | protocol version */
1134 0x83,
1135 0x99,
1136 0x8D,
1137 0xDD,
1138 0x0F, /* non-zig-zag varint sequence number */
1139 0x03, /* message-name length */
1140 0x66,
1141 0x6F,
1142 0x6F /* "foo" */,
1143 ];
1144
1145 i_prot.transport.set_readable_bytes(&source_bytes);
1146
1147 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -73_184_125);
1148 let res = assert_success!(i_prot.read_message_begin());
1149
1150 assert_eq!(&expected, &res);
1151 }
1152
1153 #[test]
1154 fn must_write_message_begin_negative_sequence_number_2() {
1155 let (_, mut o_prot) = test_objects();
1156
1157 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1158 "foo",
1159 TMessageType::Call,
1160 -1_073_741_823
1161 )));
1162
1163 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
1164 #[rustfmt::skip]
1165 let expected: [u8; 11] = [
1166 0x82, /* protocol ID */
1167 0x21, /* message type | protocol version */
1168 0x81,
1169 0x80,
1170 0x80,
1171 0x80,
1172 0x0C, /* non-zig-zag varint sequence number */
1173 0x03, /* message-name length */
1174 0x66,
1175 0x6F,
1176 0x6F /* "foo" */,
1177 ];
1178
1179 assert_eq_written_bytes!(o_prot, expected);
1180 }
1181
1182 #[test]
1183 fn must_read_message_begin_negative_sequence_number_2() {
1184 let (mut i_prot, _) = test_objects();
1185
1186 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
Allen George55c3e4c2021-03-01 23:19:52 -05001187 #[rustfmt::skip]
Allen George8a1743d2020-12-05 01:19:27 -05001188 let source_bytes: [u8; 11] = [
1189 0x82, /* protocol ID */
1190 0x21, /* message type | protocol version */
1191 0x81,
1192 0x80,
1193 0x80,
1194 0x80,
1195 0x0C, /* non-zig-zag varint sequence number */
1196 0x03, /* message-name length */
1197 0x66,
1198 0x6F,
Allen George55c3e4c2021-03-01 23:19:52 -05001199 0x6F, /* "foo" */
Allen George8a1743d2020-12-05 01:19:27 -05001200 ];
1201
1202 i_prot.transport.set_readable_bytes(&source_bytes);
1203
1204 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -1_073_741_823);
1205 let res = assert_success!(i_prot.read_message_begin());
1206
1207 assert_eq!(&expected, &res);
1208 }
1209
1210 #[test]
Nik Claytone7917602020-03-05 11:51:15 +01001211 fn must_round_trip_upto_i64_maxvalue() {
1212 // See https://issues.apache.org/jira/browse/THRIFT-5131
1213 for i in 0..64 {
1214 let (mut i_prot, mut o_prot) = test_objects();
1215 let val: i64 = ((1u64 << i) - 1) as i64;
1216
1217 o_prot
Allen George8a1743d2020-12-05 01:19:27 -05001218 .write_field_begin(&TFieldIdentifier::new("val", TType::I64, 1))
Nik Claytone7917602020-03-05 11:51:15 +01001219 .unwrap();
1220 o_prot.write_i64(val).unwrap();
1221 o_prot.write_field_end().unwrap();
1222 o_prot.flush().unwrap();
1223
1224 copy_write_buffer_to_read_buffer!(o_prot);
1225
1226 i_prot.read_field_begin().unwrap();
1227 assert_eq!(val, i_prot.read_i64().unwrap());
1228 }
1229 }
1230
1231 #[test]
Allen George8b96bfb2016-11-02 08:01:08 -04001232 fn must_round_trip_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -05001233 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001234
Allen George7ddbcc02020-11-08 09:51:19 -05001235 let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948);
Allen George8b96bfb2016-11-02 08:01:08 -04001236
1237 assert_success!(o_prot.write_message_begin(&ident));
1238
Allen George0e22c362017-01-30 07:15:00 -05001239 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001240
1241 let res = assert_success!(i_prot.read_message_begin());
1242 assert_eq!(&res, &ident);
1243 }
1244
1245 #[test]
1246 fn must_write_message_end() {
1247 assert_no_write(|o| o.write_message_end());
1248 }
1249
1250 // NOTE: structs and fields are tested together
1251 //
1252
1253 #[test]
1254 fn must_write_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001255 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001256
1257 // no bytes should be written however
1258 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1259
1260 // write three fields with tiny field ids
1261 // since they're small the field ids will be encoded as deltas
1262
1263 // since this is the first field (and it's zero) it gets the full varint write
1264 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
1265 assert_success!(o_prot.write_field_end());
1266
1267 // since this delta > 0 and < 15 it can be encoded as a delta
1268 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
1269 assert_success!(o_prot.write_field_end());
1270
1271 // since this delta > 0 and < 15 it can be encoded as a delta
1272 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
1273 assert_success!(o_prot.write_field_end());
1274
1275 // now, finish the struct off
1276 assert_success!(o_prot.write_field_stop());
1277 assert_success!(o_prot.write_struct_end());
1278
Allen George7ddbcc02020-11-08 09:51:19 -05001279 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001280 let expected: [u8; 5] = [
1281 0x03, /* field type */
1282 0x00, /* first field id */
1283 0x44, /* field delta (4) | field type */
1284 0x59, /* field delta (5) | field type */
1285 0x00 /* field stop */,
1286 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001287
Allen George0e22c362017-01-30 07:15:00 -05001288 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001289 }
1290
1291 #[test]
1292 fn must_round_trip_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001293 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001294
1295 // no bytes should be written however
1296 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1297
1298 // write three fields with tiny field ids
1299 // since they're small the field ids will be encoded as deltas
1300
1301 // since this is the first field (and it's zero) it gets the full varint write
1302 let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
1303 assert_success!(o_prot.write_field_begin(&field_ident_1));
1304 assert_success!(o_prot.write_field_end());
1305
1306 // since this delta > 0 and < 15 it can be encoded as a delta
1307 let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
1308 assert_success!(o_prot.write_field_begin(&field_ident_2));
1309 assert_success!(o_prot.write_field_end());
1310
1311 // since this delta > 0 and < 15 it can be encoded as a delta
1312 let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
1313 assert_success!(o_prot.write_field_begin(&field_ident_3));
1314 assert_success!(o_prot.write_field_end());
1315
1316 // now, finish the struct off
1317 assert_success!(o_prot.write_field_stop());
1318 assert_success!(o_prot.write_struct_end());
1319
Allen George0e22c362017-01-30 07:15:00 -05001320 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001321
1322 // read the struct back
1323 assert_success!(i_prot.read_struct_begin());
1324
1325 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001326 assert_eq!(
1327 read_ident_1,
1328 TFieldIdentifier {
1329 name: None,
1330 ..field_ident_1
1331 }
1332 );
Allen George8b96bfb2016-11-02 08:01:08 -04001333 assert_success!(i_prot.read_field_end());
1334
1335 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001336 assert_eq!(
1337 read_ident_2,
1338 TFieldIdentifier {
1339 name: None,
1340 ..field_ident_2
1341 }
1342 );
Allen George8b96bfb2016-11-02 08:01:08 -04001343 assert_success!(i_prot.read_field_end());
1344
1345 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001346 assert_eq!(
1347 read_ident_3,
1348 TFieldIdentifier {
1349 name: None,
1350 ..field_ident_3
1351 }
1352 );
Allen George8b96bfb2016-11-02 08:01:08 -04001353 assert_success!(i_prot.read_field_end());
1354
1355 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001356 assert_eq!(
1357 read_ident_4,
1358 TFieldIdentifier {
1359 name: None,
1360 field_type: TType::Stop,
1361 id: None,
1362 }
1363 );
Allen George8b96bfb2016-11-02 08:01:08 -04001364
1365 assert_success!(i_prot.read_struct_end());
1366 }
1367
1368 #[test]
1369 fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001370 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001371
1372 // no bytes should be written however
1373 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1374
1375 // write three fields with tiny field ids
1376 // since they're small the field ids will be encoded as deltas
1377
1378 // gets a delta write
1379 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
1380 assert_success!(o_prot.write_field_end());
1381
1382 // since this delta > 0 and < 15 it can be encoded as a delta
1383 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
1384 assert_success!(o_prot.write_field_end());
1385
1386 // since this delta > 0 and < 15 it can be encoded as a delta
1387 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
1388 assert_success!(o_prot.write_field_end());
1389
1390 // now, finish the struct off
1391 assert_success!(o_prot.write_field_stop());
1392 assert_success!(o_prot.write_struct_end());
1393
Allen George7ddbcc02020-11-08 09:51:19 -05001394 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001395 let expected: [u8; 4] = [
1396 0x15, /* field delta (1) | field type */
1397 0x1A, /* field delta (1) | field type */
1398 0x48, /* field delta (4) | field type */
1399 0x00 /* field stop */,
1400 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001401
Allen George0e22c362017-01-30 07:15:00 -05001402 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001403 }
1404
1405 #[test]
1406 fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001407 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001408
1409 // no bytes should be written however
1410 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1411
1412 // write three fields with tiny field ids
1413 // since they're small the field ids will be encoded as deltas
1414
1415 // gets a delta write
1416 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
1417 assert_success!(o_prot.write_field_begin(&field_ident_1));
1418 assert_success!(o_prot.write_field_end());
1419
1420 // since this delta > 0 and < 15 it can be encoded as a delta
1421 let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
1422 assert_success!(o_prot.write_field_begin(&field_ident_2));
1423 assert_success!(o_prot.write_field_end());
1424
1425 // since this delta > 0 and < 15 it can be encoded as a delta
1426 let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
1427 assert_success!(o_prot.write_field_begin(&field_ident_3));
1428 assert_success!(o_prot.write_field_end());
1429
1430 // now, finish the struct off
1431 assert_success!(o_prot.write_field_stop());
1432 assert_success!(o_prot.write_struct_end());
1433
Allen George0e22c362017-01-30 07:15:00 -05001434 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001435
1436 // read the struct back
1437 assert_success!(i_prot.read_struct_begin());
1438
1439 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001440 assert_eq!(
1441 read_ident_1,
1442 TFieldIdentifier {
1443 name: None,
1444 ..field_ident_1
1445 }
1446 );
Allen George8b96bfb2016-11-02 08:01:08 -04001447 assert_success!(i_prot.read_field_end());
1448
1449 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001450 assert_eq!(
1451 read_ident_2,
1452 TFieldIdentifier {
1453 name: None,
1454 ..field_ident_2
1455 }
1456 );
Allen George8b96bfb2016-11-02 08:01:08 -04001457 assert_success!(i_prot.read_field_end());
1458
1459 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001460 assert_eq!(
1461 read_ident_3,
1462 TFieldIdentifier {
1463 name: None,
1464 ..field_ident_3
1465 }
1466 );
Allen George8b96bfb2016-11-02 08:01:08 -04001467 assert_success!(i_prot.read_field_end());
1468
1469 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001470 assert_eq!(
1471 read_ident_4,
1472 TFieldIdentifier {
1473 name: None,
1474 field_type: TType::Stop,
1475 id: None,
1476 }
1477 );
Allen George8b96bfb2016-11-02 08:01:08 -04001478
1479 assert_success!(i_prot.read_struct_end());
1480 }
1481
1482 #[test]
1483 fn must_write_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001484 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001485
1486 // no bytes should be written however
1487 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1488
1489 // write three fields with field ids that cannot be encoded as deltas
1490
1491 // since this is the first field (and it's zero) it gets the full varint write
1492 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
1493 assert_success!(o_prot.write_field_end());
1494
1495 // since this delta is > 15 it is encoded as a zig-zag varint
1496 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
1497 assert_success!(o_prot.write_field_end());
1498
1499 // since this delta is > 15 it is encoded as a zig-zag varint
1500 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
1501 assert_success!(o_prot.write_field_end());
1502
1503 // now, finish the struct off
1504 assert_success!(o_prot.write_field_stop());
1505 assert_success!(o_prot.write_struct_end());
1506
Allen George7ddbcc02020-11-08 09:51:19 -05001507 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001508 let expected: [u8; 8] = [
1509 0x05, /* field type */
1510 0x00, /* first field id */
1511 0x06, /* field type */
1512 0x20, /* zig-zag varint field id */
1513 0x0A, /* field type */
1514 0xC6,
1515 0x01, /* zig-zag varint field id */
1516 0x00 /* field stop */,
1517 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001518
Allen George0e22c362017-01-30 07:15:00 -05001519 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001520 }
1521
1522 #[test]
1523 fn must_round_trip_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001524 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001525
1526 // no bytes should be written however
1527 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1528
1529 // write three fields with field ids that cannot be encoded as deltas
1530
1531 // since this is the first field (and it's zero) it gets the full varint write
1532 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
1533 assert_success!(o_prot.write_field_begin(&field_ident_1));
1534 assert_success!(o_prot.write_field_end());
1535
1536 // since this delta is > 15 it is encoded as a zig-zag varint
1537 let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
1538 assert_success!(o_prot.write_field_begin(&field_ident_2));
1539 assert_success!(o_prot.write_field_end());
1540
1541 // since this delta is > 15 it is encoded as a zig-zag varint
1542 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
1543 assert_success!(o_prot.write_field_begin(&field_ident_3));
1544 assert_success!(o_prot.write_field_end());
1545
1546 // now, finish the struct off
1547 assert_success!(o_prot.write_field_stop());
1548 assert_success!(o_prot.write_struct_end());
1549
Allen George0e22c362017-01-30 07:15:00 -05001550 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001551
1552 // read the struct back
1553 assert_success!(i_prot.read_struct_begin());
1554
1555 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001556 assert_eq!(
1557 read_ident_1,
1558 TFieldIdentifier {
1559 name: None,
1560 ..field_ident_1
1561 }
1562 );
Allen George8b96bfb2016-11-02 08:01:08 -04001563 assert_success!(i_prot.read_field_end());
1564
1565 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001566 assert_eq!(
1567 read_ident_2,
1568 TFieldIdentifier {
1569 name: None,
1570 ..field_ident_2
1571 }
1572 );
Allen George8b96bfb2016-11-02 08:01:08 -04001573 assert_success!(i_prot.read_field_end());
1574
1575 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001576 assert_eq!(
1577 read_ident_3,
1578 TFieldIdentifier {
1579 name: None,
1580 ..field_ident_3
1581 }
1582 );
Allen George8b96bfb2016-11-02 08:01:08 -04001583 assert_success!(i_prot.read_field_end());
1584
1585 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001586 assert_eq!(
1587 read_ident_4,
1588 TFieldIdentifier {
1589 name: None,
1590 field_type: TType::Stop,
1591 id: None,
1592 }
1593 );
Allen George8b96bfb2016-11-02 08:01:08 -04001594
1595 assert_success!(i_prot.read_struct_end());
1596 }
1597
1598 #[test]
1599 fn must_write_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001600 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001601
1602 // no bytes should be written however
1603 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1604
1605 // write three fields with field ids that cannot be encoded as deltas
1606
1607 // since the delta is > 0 and < 15 it gets a delta write
1608 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1609 assert_success!(o_prot.write_field_end());
1610
1611 // since this delta > 0 and < 15 it gets a delta write
1612 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1613 assert_success!(o_prot.write_field_end());
1614
1615 // since this delta is > 15 it is encoded as a zig-zag varint
1616 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
1617 assert_success!(o_prot.write_field_end());
1618
1619 // since this delta is > 15 it is encoded as a zig-zag varint
1620 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
1621 assert_success!(o_prot.write_field_end());
1622
1623 // since this is only 3 up from the previous it is recorded as a delta
1624 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
1625 assert_success!(o_prot.write_field_end());
1626
1627 // now, finish the struct off
1628 assert_success!(o_prot.write_field_stop());
1629 assert_success!(o_prot.write_struct_end());
1630
Allen George7ddbcc02020-11-08 09:51:19 -05001631 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001632 let expected: [u8; 10] = [
1633 0x16, /* field delta (1) | field type */
1634 0x85, /* field delta (8) | field type */
1635 0x0A, /* field type */
1636 0xD0,
1637 0x0F, /* zig-zag varint field id */
1638 0x0A, /* field type */
1639 0xA2,
1640 0x1F, /* zig-zag varint field id */
1641 0x3A, /* field delta (3) | field type */
1642 0x00 /* field stop */,
1643 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001644
Allen George0e22c362017-01-30 07:15:00 -05001645 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001646 }
1647
Allen George7ddbcc02020-11-08 09:51:19 -05001648 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001649 #[test]
1650 fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001651 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001652
1653 // no bytes should be written however
1654 let struct_ident = TStructIdentifier::new("foo");
1655 assert_success!(o_prot.write_struct_begin(&struct_ident));
1656
1657 // write three fields with field ids that cannot be encoded as deltas
1658
1659 // since the delta is > 0 and < 15 it gets a delta write
1660 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1661 assert_success!(o_prot.write_field_begin(&field_ident_1));
1662 assert_success!(o_prot.write_field_end());
1663
1664 // since this delta > 0 and < 15 it gets a delta write
1665 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1666 assert_success!(o_prot.write_field_begin(&field_ident_2));
1667 assert_success!(o_prot.write_field_end());
1668
1669 // since this delta is > 15 it is encoded as a zig-zag varint
1670 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
1671 assert_success!(o_prot.write_field_begin(&field_ident_3));
1672 assert_success!(o_prot.write_field_end());
1673
1674 // since this delta is > 15 it is encoded as a zig-zag varint
1675 let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
1676 assert_success!(o_prot.write_field_begin(&field_ident_4));
1677 assert_success!(o_prot.write_field_end());
1678
1679 // since this is only 3 up from the previous it is recorded as a delta
1680 let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
1681 assert_success!(o_prot.write_field_begin(&field_ident_5));
1682 assert_success!(o_prot.write_field_end());
1683
1684 // now, finish the struct off
1685 assert_success!(o_prot.write_field_stop());
1686 assert_success!(o_prot.write_struct_end());
1687
Allen George0e22c362017-01-30 07:15:00 -05001688 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001689
1690 // read the struct back
1691 assert_success!(i_prot.read_struct_begin());
1692
1693 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001694 assert_eq!(
1695 read_ident_1,
1696 TFieldIdentifier {
1697 name: None,
1698 ..field_ident_1
1699 }
1700 );
Allen George8b96bfb2016-11-02 08:01:08 -04001701 assert_success!(i_prot.read_field_end());
1702
1703 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001704 assert_eq!(
1705 read_ident_2,
1706 TFieldIdentifier {
1707 name: None,
1708 ..field_ident_2
1709 }
1710 );
Allen George8b96bfb2016-11-02 08:01:08 -04001711 assert_success!(i_prot.read_field_end());
1712
1713 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001714 assert_eq!(
1715 read_ident_3,
1716 TFieldIdentifier {
1717 name: None,
1718 ..field_ident_3
1719 }
1720 );
Allen George8b96bfb2016-11-02 08:01:08 -04001721 assert_success!(i_prot.read_field_end());
1722
1723 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001724 assert_eq!(
1725 read_ident_4,
1726 TFieldIdentifier {
1727 name: None,
1728 ..field_ident_4
1729 }
1730 );
Allen George8b96bfb2016-11-02 08:01:08 -04001731 assert_success!(i_prot.read_field_end());
1732
1733 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001734 assert_eq!(
1735 read_ident_5,
1736 TFieldIdentifier {
1737 name: None,
1738 ..field_ident_5
1739 }
1740 );
Allen George8b96bfb2016-11-02 08:01:08 -04001741 assert_success!(i_prot.read_field_end());
1742
1743 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001744 assert_eq!(
1745 read_ident_6,
1746 TFieldIdentifier {
1747 name: None,
1748 field_type: TType::Stop,
1749 id: None,
1750 }
1751 );
Allen George8b96bfb2016-11-02 08:01:08 -04001752
1753 assert_success!(i_prot.read_struct_end());
1754 }
1755
1756 #[test]
1757 fn must_write_nested_structs_0() {
1758 // last field of the containing struct is a delta
1759 // first field of the the contained struct is a delta
1760
Allen George0e22c362017-01-30 07:15:00 -05001761 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001762
1763 // start containing struct
1764 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1765
1766 // containing struct
1767 // since the delta is > 0 and < 15 it gets a delta write
1768 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1769 assert_success!(o_prot.write_field_end());
1770
1771 // containing struct
1772 // since this delta > 0 and < 15 it gets a delta write
1773 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1774 assert_success!(o_prot.write_field_end());
1775
1776 // start contained struct
1777 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1778
1779 // contained struct
1780 // since the delta is > 0 and < 15 it gets a delta write
1781 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
1782 assert_success!(o_prot.write_field_end());
1783
1784 // contained struct
1785 // since this delta > 15 it gets a full write
1786 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1787 assert_success!(o_prot.write_field_end());
1788
1789 // end contained struct
1790 assert_success!(o_prot.write_field_stop());
1791 assert_success!(o_prot.write_struct_end());
1792
1793 // end containing struct
1794 assert_success!(o_prot.write_field_stop());
1795 assert_success!(o_prot.write_struct_end());
1796
Allen George7ddbcc02020-11-08 09:51:19 -05001797 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001798 let expected: [u8; 7] = [
1799 0x16, /* field delta (1) | field type */
1800 0x85, /* field delta (8) | field type */
1801 0x73, /* field delta (7) | field type */
1802 0x07, /* field type */
1803 0x30, /* zig-zag varint field id */
1804 0x00, /* field stop - contained */
1805 0x00 /* field stop - containing */,
1806 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001807
Allen George0e22c362017-01-30 07:15:00 -05001808 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001809 }
1810
Allen George7ddbcc02020-11-08 09:51:19 -05001811 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001812 #[test]
1813 fn must_round_trip_nested_structs_0() {
1814 // last field of the containing struct is a delta
1815 // first field of the the contained struct is a delta
1816
Allen George0e22c362017-01-30 07:15:00 -05001817 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001818
1819 // start containing struct
1820 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1821
1822 // containing struct
1823 // since the delta is > 0 and < 15 it gets a delta write
1824 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1825 assert_success!(o_prot.write_field_begin(&field_ident_1));
1826 assert_success!(o_prot.write_field_end());
1827
1828 // containing struct
1829 // since this delta > 0 and < 15 it gets a delta write
1830 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1831 assert_success!(o_prot.write_field_begin(&field_ident_2));
1832 assert_success!(o_prot.write_field_end());
1833
1834 // start contained struct
1835 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1836
1837 // contained struct
1838 // since the delta is > 0 and < 15 it gets a delta write
1839 let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
1840 assert_success!(o_prot.write_field_begin(&field_ident_3));
1841 assert_success!(o_prot.write_field_end());
1842
1843 // contained struct
1844 // since this delta > 15 it gets a full write
1845 let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
1846 assert_success!(o_prot.write_field_begin(&field_ident_4));
1847 assert_success!(o_prot.write_field_end());
1848
1849 // end contained struct
1850 assert_success!(o_prot.write_field_stop());
1851 assert_success!(o_prot.write_struct_end());
1852
1853 // end containing struct
1854 assert_success!(o_prot.write_field_stop());
1855 assert_success!(o_prot.write_struct_end());
1856
Allen George0e22c362017-01-30 07:15:00 -05001857 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001858
1859 // read containing struct back
1860 assert_success!(i_prot.read_struct_begin());
1861
1862 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001863 assert_eq!(
1864 read_ident_1,
1865 TFieldIdentifier {
1866 name: None,
1867 ..field_ident_1
1868 }
1869 );
Allen George8b96bfb2016-11-02 08:01:08 -04001870 assert_success!(i_prot.read_field_end());
1871
1872 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001873 assert_eq!(
1874 read_ident_2,
1875 TFieldIdentifier {
1876 name: None,
1877 ..field_ident_2
1878 }
1879 );
Allen George8b96bfb2016-11-02 08:01:08 -04001880 assert_success!(i_prot.read_field_end());
1881
1882 // read contained struct back
1883 assert_success!(i_prot.read_struct_begin());
1884
1885 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001886 assert_eq!(
1887 read_ident_3,
1888 TFieldIdentifier {
1889 name: None,
1890 ..field_ident_3
1891 }
1892 );
Allen George8b96bfb2016-11-02 08:01:08 -04001893 assert_success!(i_prot.read_field_end());
1894
1895 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001896 assert_eq!(
1897 read_ident_4,
1898 TFieldIdentifier {
1899 name: None,
1900 ..field_ident_4
1901 }
1902 );
Allen George8b96bfb2016-11-02 08:01:08 -04001903 assert_success!(i_prot.read_field_end());
1904
1905 // end contained struct
1906 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001907 assert_eq!(
1908 read_ident_6,
1909 TFieldIdentifier {
1910 name: None,
1911 field_type: TType::Stop,
1912 id: None,
1913 }
1914 );
Allen George8b96bfb2016-11-02 08:01:08 -04001915 assert_success!(i_prot.read_struct_end());
1916
1917 // end containing struct
1918 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001919 assert_eq!(
1920 read_ident_7,
1921 TFieldIdentifier {
1922 name: None,
1923 field_type: TType::Stop,
1924 id: None,
1925 }
1926 );
Allen George8b96bfb2016-11-02 08:01:08 -04001927 assert_success!(i_prot.read_struct_end());
1928 }
1929
1930 #[test]
1931 fn must_write_nested_structs_1() {
1932 // last field of the containing struct is a delta
1933 // first field of the the contained struct is a full write
1934
Allen George0e22c362017-01-30 07:15:00 -05001935 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001936
1937 // start containing struct
1938 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1939
1940 // containing struct
1941 // since the delta is > 0 and < 15 it gets a delta write
1942 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1943 assert_success!(o_prot.write_field_end());
1944
1945 // containing struct
1946 // since this delta > 0 and < 15 it gets a delta write
1947 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1948 assert_success!(o_prot.write_field_end());
1949
1950 // start contained struct
1951 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1952
1953 // contained struct
1954 // since this delta > 15 it gets a full write
1955 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1956 assert_success!(o_prot.write_field_end());
1957
1958 // contained struct
1959 // since the delta is > 0 and < 15 it gets a delta write
1960 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1961 assert_success!(o_prot.write_field_end());
1962
1963 // end contained struct
1964 assert_success!(o_prot.write_field_stop());
1965 assert_success!(o_prot.write_struct_end());
1966
1967 // end containing struct
1968 assert_success!(o_prot.write_field_stop());
1969 assert_success!(o_prot.write_struct_end());
1970
Allen George7ddbcc02020-11-08 09:51:19 -05001971 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001972 let expected: [u8; 7] = [
1973 0x16, /* field delta (1) | field type */
1974 0x85, /* field delta (8) | field type */
1975 0x07, /* field type */
1976 0x30, /* zig-zag varint field id */
1977 0x33, /* field delta (3) | field type */
1978 0x00, /* field stop - contained */
1979 0x00 /* field stop - containing */,
1980 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001981
Allen George0e22c362017-01-30 07:15:00 -05001982 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001983 }
1984
Allen George7ddbcc02020-11-08 09:51:19 -05001985 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001986 #[test]
1987 fn must_round_trip_nested_structs_1() {
1988 // last field of the containing struct is a delta
1989 // first field of the the contained struct is a full write
1990
Allen George0e22c362017-01-30 07:15:00 -05001991 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001992
1993 // start containing struct
1994 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1995
1996 // containing struct
1997 // since the delta is > 0 and < 15 it gets a delta write
1998 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1999 assert_success!(o_prot.write_field_begin(&field_ident_1));
2000 assert_success!(o_prot.write_field_end());
2001
2002 // containing struct
2003 // since this delta > 0 and < 15 it gets a delta write
2004 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
2005 assert_success!(o_prot.write_field_begin(&field_ident_2));
2006 assert_success!(o_prot.write_field_end());
2007
2008 // start contained struct
2009 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2010
2011 // contained struct
2012 // since this delta > 15 it gets a full write
2013 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
2014 assert_success!(o_prot.write_field_begin(&field_ident_3));
2015 assert_success!(o_prot.write_field_end());
2016
2017 // contained struct
2018 // since the delta is > 0 and < 15 it gets a delta write
2019 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2020 assert_success!(o_prot.write_field_begin(&field_ident_4));
2021 assert_success!(o_prot.write_field_end());
2022
2023 // end contained struct
2024 assert_success!(o_prot.write_field_stop());
2025 assert_success!(o_prot.write_struct_end());
2026
2027 // end containing struct
2028 assert_success!(o_prot.write_field_stop());
2029 assert_success!(o_prot.write_struct_end());
2030
Allen George0e22c362017-01-30 07:15:00 -05002031 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002032
2033 // read containing struct back
2034 assert_success!(i_prot.read_struct_begin());
2035
2036 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002037 assert_eq!(
2038 read_ident_1,
2039 TFieldIdentifier {
2040 name: None,
2041 ..field_ident_1
2042 }
2043 );
Allen George8b96bfb2016-11-02 08:01:08 -04002044 assert_success!(i_prot.read_field_end());
2045
2046 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002047 assert_eq!(
2048 read_ident_2,
2049 TFieldIdentifier {
2050 name: None,
2051 ..field_ident_2
2052 }
2053 );
Allen George8b96bfb2016-11-02 08:01:08 -04002054 assert_success!(i_prot.read_field_end());
2055
2056 // read contained struct back
2057 assert_success!(i_prot.read_struct_begin());
2058
2059 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002060 assert_eq!(
2061 read_ident_3,
2062 TFieldIdentifier {
2063 name: None,
2064 ..field_ident_3
2065 }
2066 );
Allen George8b96bfb2016-11-02 08:01:08 -04002067 assert_success!(i_prot.read_field_end());
2068
2069 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002070 assert_eq!(
2071 read_ident_4,
2072 TFieldIdentifier {
2073 name: None,
2074 ..field_ident_4
2075 }
2076 );
Allen George8b96bfb2016-11-02 08:01:08 -04002077 assert_success!(i_prot.read_field_end());
2078
2079 // end contained struct
2080 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002081 assert_eq!(
2082 read_ident_6,
2083 TFieldIdentifier {
2084 name: None,
2085 field_type: TType::Stop,
2086 id: None,
2087 }
2088 );
Allen George8b96bfb2016-11-02 08:01:08 -04002089 assert_success!(i_prot.read_struct_end());
2090
2091 // end containing struct
2092 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002093 assert_eq!(
2094 read_ident_7,
2095 TFieldIdentifier {
2096 name: None,
2097 field_type: TType::Stop,
2098 id: None,
2099 }
2100 );
Allen George8b96bfb2016-11-02 08:01:08 -04002101 assert_success!(i_prot.read_struct_end());
2102 }
2103
2104 #[test]
2105 fn must_write_nested_structs_2() {
2106 // last field of the containing struct is a full write
2107 // first field of the the contained struct is a delta write
2108
Allen George0e22c362017-01-30 07:15:00 -05002109 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002110
2111 // start containing struct
2112 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2113
2114 // containing struct
2115 // since the delta is > 0 and < 15 it gets a delta write
2116 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2117 assert_success!(o_prot.write_field_end());
2118
2119 // containing struct
2120 // since this delta > 15 it gets a full write
2121 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2122 assert_success!(o_prot.write_field_end());
2123
2124 // start contained struct
2125 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2126
2127 // contained struct
2128 // since this delta > 0 and < 15 it gets a delta write
2129 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
2130 assert_success!(o_prot.write_field_end());
2131
2132 // contained struct
2133 // since the delta is > 0 and < 15 it gets a delta write
2134 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
2135 assert_success!(o_prot.write_field_end());
2136
2137 // end contained struct
2138 assert_success!(o_prot.write_field_stop());
2139 assert_success!(o_prot.write_struct_end());
2140
2141 // end containing struct
2142 assert_success!(o_prot.write_field_stop());
2143 assert_success!(o_prot.write_struct_end());
2144
Allen George7ddbcc02020-11-08 09:51:19 -05002145 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002146 let expected: [u8; 7] = [
2147 0x16, /* field delta (1) | field type */
2148 0x08, /* field type */
2149 0x2A, /* zig-zag varint field id */
2150 0x77, /* field delta(7) | field type */
2151 0x33, /* field delta (3) | field type */
2152 0x00, /* field stop - contained */
2153 0x00 /* field stop - containing */,
2154 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002155
Allen George0e22c362017-01-30 07:15:00 -05002156 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002157 }
2158
Allen George7ddbcc02020-11-08 09:51:19 -05002159 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002160 #[test]
2161 fn must_round_trip_nested_structs_2() {
Allen George0e22c362017-01-30 07:15:00 -05002162 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002163
2164 // start containing struct
2165 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2166
2167 // containing struct
2168 // since the delta is > 0 and < 15 it gets a delta write
2169 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2170 assert_success!(o_prot.write_field_begin(&field_ident_1));
2171 assert_success!(o_prot.write_field_end());
2172
2173 // containing struct
2174 // since this delta > 15 it gets a full write
2175 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2176 assert_success!(o_prot.write_field_begin(&field_ident_2));
2177 assert_success!(o_prot.write_field_end());
2178
2179 // start contained struct
2180 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2181
2182 // contained struct
2183 // since this delta > 0 and < 15 it gets a delta write
2184 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
2185 assert_success!(o_prot.write_field_begin(&field_ident_3));
2186 assert_success!(o_prot.write_field_end());
2187
2188 // contained struct
2189 // since the delta is > 0 and < 15 it gets a delta write
2190 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
2191 assert_success!(o_prot.write_field_begin(&field_ident_4));
2192 assert_success!(o_prot.write_field_end());
2193
2194 // end contained struct
2195 assert_success!(o_prot.write_field_stop());
2196 assert_success!(o_prot.write_struct_end());
2197
2198 // end containing struct
2199 assert_success!(o_prot.write_field_stop());
2200 assert_success!(o_prot.write_struct_end());
2201
Allen George0e22c362017-01-30 07:15:00 -05002202 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002203
2204 // read containing struct back
2205 assert_success!(i_prot.read_struct_begin());
2206
2207 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002208 assert_eq!(
2209 read_ident_1,
2210 TFieldIdentifier {
2211 name: None,
2212 ..field_ident_1
2213 }
2214 );
Allen George8b96bfb2016-11-02 08:01:08 -04002215 assert_success!(i_prot.read_field_end());
2216
2217 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002218 assert_eq!(
2219 read_ident_2,
2220 TFieldIdentifier {
2221 name: None,
2222 ..field_ident_2
2223 }
2224 );
Allen George8b96bfb2016-11-02 08:01:08 -04002225 assert_success!(i_prot.read_field_end());
2226
2227 // read contained struct back
2228 assert_success!(i_prot.read_struct_begin());
2229
2230 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002231 assert_eq!(
2232 read_ident_3,
2233 TFieldIdentifier {
2234 name: None,
2235 ..field_ident_3
2236 }
2237 );
Allen George8b96bfb2016-11-02 08:01:08 -04002238 assert_success!(i_prot.read_field_end());
2239
2240 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002241 assert_eq!(
2242 read_ident_4,
2243 TFieldIdentifier {
2244 name: None,
2245 ..field_ident_4
2246 }
2247 );
Allen George8b96bfb2016-11-02 08:01:08 -04002248 assert_success!(i_prot.read_field_end());
2249
2250 // end contained struct
2251 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002252 assert_eq!(
2253 read_ident_6,
2254 TFieldIdentifier {
2255 name: None,
2256 field_type: TType::Stop,
2257 id: None,
2258 }
2259 );
Allen George8b96bfb2016-11-02 08:01:08 -04002260 assert_success!(i_prot.read_struct_end());
2261
2262 // end containing struct
2263 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002264 assert_eq!(
2265 read_ident_7,
2266 TFieldIdentifier {
2267 name: None,
2268 field_type: TType::Stop,
2269 id: None,
2270 }
2271 );
Allen George8b96bfb2016-11-02 08:01:08 -04002272 assert_success!(i_prot.read_struct_end());
2273 }
2274
2275 #[test]
2276 fn must_write_nested_structs_3() {
2277 // last field of the containing struct is a full write
2278 // first field of the the contained struct is a full write
2279
Allen George0e22c362017-01-30 07:15:00 -05002280 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002281
2282 // start containing struct
2283 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2284
2285 // containing struct
2286 // since the delta is > 0 and < 15 it gets a delta write
2287 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2288 assert_success!(o_prot.write_field_end());
2289
2290 // containing struct
2291 // since this delta > 15 it gets a full write
2292 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2293 assert_success!(o_prot.write_field_end());
2294
2295 // start contained struct
2296 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2297
2298 // contained struct
2299 // since this delta > 15 it gets a full write
2300 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
2301 assert_success!(o_prot.write_field_end());
2302
2303 // contained struct
2304 // since the delta is > 0 and < 15 it gets a delta write
2305 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
2306 assert_success!(o_prot.write_field_end());
2307
2308 // end contained struct
2309 assert_success!(o_prot.write_field_stop());
2310 assert_success!(o_prot.write_struct_end());
2311
2312 // end containing struct
2313 assert_success!(o_prot.write_field_stop());
2314 assert_success!(o_prot.write_struct_end());
2315
Allen George7ddbcc02020-11-08 09:51:19 -05002316 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002317 let expected: [u8; 8] = [
2318 0x16, /* field delta (1) | field type */
2319 0x08, /* field type */
2320 0x2A, /* zig-zag varint field id */
2321 0x07, /* field type */
2322 0x2A, /* zig-zag varint field id */
2323 0x63, /* field delta (6) | field type */
2324 0x00, /* field stop - contained */
2325 0x00 /* field stop - containing */,
2326 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002327
Allen George0e22c362017-01-30 07:15:00 -05002328 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002329 }
2330
Allen George7ddbcc02020-11-08 09:51:19 -05002331 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002332 #[test]
2333 fn must_round_trip_nested_structs_3() {
2334 // last field of the containing struct is a full write
2335 // first field of the the contained struct is a full write
2336
Allen George0e22c362017-01-30 07:15:00 -05002337 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002338
2339 // start containing struct
2340 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2341
2342 // containing struct
2343 // since the delta is > 0 and < 15 it gets a delta write
2344 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2345 assert_success!(o_prot.write_field_begin(&field_ident_1));
2346 assert_success!(o_prot.write_field_end());
2347
2348 // containing struct
2349 // since this delta > 15 it gets a full write
2350 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2351 assert_success!(o_prot.write_field_begin(&field_ident_2));
2352 assert_success!(o_prot.write_field_end());
2353
2354 // start contained struct
2355 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2356
2357 // contained struct
2358 // since this delta > 15 it gets a full write
2359 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
2360 assert_success!(o_prot.write_field_begin(&field_ident_3));
2361 assert_success!(o_prot.write_field_end());
2362
2363 // contained struct
2364 // since the delta is > 0 and < 15 it gets a delta write
2365 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2366 assert_success!(o_prot.write_field_begin(&field_ident_4));
2367 assert_success!(o_prot.write_field_end());
2368
2369 // end contained struct
2370 assert_success!(o_prot.write_field_stop());
2371 assert_success!(o_prot.write_struct_end());
2372
2373 // end containing struct
2374 assert_success!(o_prot.write_field_stop());
2375 assert_success!(o_prot.write_struct_end());
2376
Allen George0e22c362017-01-30 07:15:00 -05002377 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002378
2379 // read containing struct back
2380 assert_success!(i_prot.read_struct_begin());
2381
2382 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002383 assert_eq!(
2384 read_ident_1,
2385 TFieldIdentifier {
2386 name: None,
2387 ..field_ident_1
2388 }
2389 );
Allen George8b96bfb2016-11-02 08:01:08 -04002390 assert_success!(i_prot.read_field_end());
2391
2392 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002393 assert_eq!(
2394 read_ident_2,
2395 TFieldIdentifier {
2396 name: None,
2397 ..field_ident_2
2398 }
2399 );
Allen George8b96bfb2016-11-02 08:01:08 -04002400 assert_success!(i_prot.read_field_end());
2401
2402 // read contained struct back
2403 assert_success!(i_prot.read_struct_begin());
2404
2405 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002406 assert_eq!(
2407 read_ident_3,
2408 TFieldIdentifier {
2409 name: None,
2410 ..field_ident_3
2411 }
2412 );
Allen George8b96bfb2016-11-02 08:01:08 -04002413 assert_success!(i_prot.read_field_end());
2414
2415 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002416 assert_eq!(
2417 read_ident_4,
2418 TFieldIdentifier {
2419 name: None,
2420 ..field_ident_4
2421 }
2422 );
Allen George8b96bfb2016-11-02 08:01:08 -04002423 assert_success!(i_prot.read_field_end());
2424
2425 // end contained struct
2426 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002427 assert_eq!(
2428 read_ident_6,
2429 TFieldIdentifier {
2430 name: None,
2431 field_type: TType::Stop,
2432 id: None,
2433 }
2434 );
Allen George8b96bfb2016-11-02 08:01:08 -04002435 assert_success!(i_prot.read_struct_end());
2436
2437 // end containing struct
2438 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002439 assert_eq!(
2440 read_ident_7,
2441 TFieldIdentifier {
2442 name: None,
2443 field_type: TType::Stop,
2444 id: None,
2445 }
2446 );
Allen George8b96bfb2016-11-02 08:01:08 -04002447 assert_success!(i_prot.read_struct_end());
2448 }
2449
2450 #[test]
2451 fn must_write_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002452 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002453
2454 // no bytes should be written however
2455 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2456
2457 // write three fields with field ids that cannot be encoded as deltas
2458
2459 // since the delta is > 0 and < 16 it gets a delta write
2460 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2461 assert_success!(o_prot.write_bool(true));
2462 assert_success!(o_prot.write_field_end());
2463
2464 // since this delta > 0 and < 15 it gets a delta write
2465 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
2466 assert_success!(o_prot.write_bool(false));
2467 assert_success!(o_prot.write_field_end());
2468
2469 // since this delta > 15 it gets a full write
2470 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
2471 assert_success!(o_prot.write_bool(true));
2472 assert_success!(o_prot.write_field_end());
2473
2474 // since this delta > 15 it gets a full write
2475 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
2476 assert_success!(o_prot.write_bool(false));
2477 assert_success!(o_prot.write_field_end());
2478
2479 // now, finish the struct off
2480 assert_success!(o_prot.write_field_stop());
2481 assert_success!(o_prot.write_struct_end());
2482
Allen George7ddbcc02020-11-08 09:51:19 -05002483 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002484 let expected: [u8; 7] = [
2485 0x11, /* field delta (1) | true */
2486 0x82, /* field delta (8) | false */
2487 0x01, /* true */
2488 0x34, /* field id */
2489 0x02, /* false */
2490 0x5A, /* field id */
2491 0x00 /* stop field */,
2492 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002493
Allen George0e22c362017-01-30 07:15:00 -05002494 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002495 }
2496
Allen George7ddbcc02020-11-08 09:51:19 -05002497 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002498 #[test]
2499 fn must_round_trip_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002500 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002501
2502 // no bytes should be written however
2503 let struct_ident = TStructIdentifier::new("foo");
2504 assert_success!(o_prot.write_struct_begin(&struct_ident));
2505
2506 // write two fields
2507
2508 // since the delta is > 0 and < 16 it gets a delta write
2509 let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
2510 assert_success!(o_prot.write_field_begin(&field_ident_1));
2511 assert_success!(o_prot.write_bool(true));
2512 assert_success!(o_prot.write_field_end());
2513
2514 // since this delta > 0 and < 15 it gets a delta write
2515 let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
2516 assert_success!(o_prot.write_field_begin(&field_ident_2));
2517 assert_success!(o_prot.write_bool(false));
2518 assert_success!(o_prot.write_field_end());
2519
2520 // since this delta > 15 it gets a full write
2521 let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
2522 assert_success!(o_prot.write_field_begin(&field_ident_3));
2523 assert_success!(o_prot.write_bool(true));
2524 assert_success!(o_prot.write_field_end());
2525
2526 // since this delta > 15 it gets a full write
2527 let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
2528 assert_success!(o_prot.write_field_begin(&field_ident_4));
2529 assert_success!(o_prot.write_bool(false));
2530 assert_success!(o_prot.write_field_end());
2531
2532 // now, finish the struct off
2533 assert_success!(o_prot.write_field_stop());
2534 assert_success!(o_prot.write_struct_end());
2535
Allen George0e22c362017-01-30 07:15:00 -05002536 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002537
2538 // read the struct back
2539 assert_success!(i_prot.read_struct_begin());
2540
2541 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002542 assert_eq!(
2543 read_ident_1,
2544 TFieldIdentifier {
2545 name: None,
2546 ..field_ident_1
2547 }
2548 );
Allen George8b96bfb2016-11-02 08:01:08 -04002549 let read_value_1 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002550 assert!(read_value_1);
Allen George8b96bfb2016-11-02 08:01:08 -04002551 assert_success!(i_prot.read_field_end());
2552
2553 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002554 assert_eq!(
2555 read_ident_2,
2556 TFieldIdentifier {
2557 name: None,
2558 ..field_ident_2
2559 }
2560 );
Allen George8b96bfb2016-11-02 08:01:08 -04002561 let read_value_2 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002562 assert!(!read_value_2);
Allen George8b96bfb2016-11-02 08:01:08 -04002563 assert_success!(i_prot.read_field_end());
2564
2565 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002566 assert_eq!(
2567 read_ident_3,
2568 TFieldIdentifier {
2569 name: None,
2570 ..field_ident_3
2571 }
2572 );
Allen George8b96bfb2016-11-02 08:01:08 -04002573 let read_value_3 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002574 assert!(read_value_3);
Allen George8b96bfb2016-11-02 08:01:08 -04002575 assert_success!(i_prot.read_field_end());
2576
2577 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002578 assert_eq!(
2579 read_ident_4,
2580 TFieldIdentifier {
2581 name: None,
2582 ..field_ident_4
2583 }
2584 );
Allen George8b96bfb2016-11-02 08:01:08 -04002585 let read_value_4 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002586 assert!(!read_value_4);
Allen George8b96bfb2016-11-02 08:01:08 -04002587 assert_success!(i_prot.read_field_end());
2588
2589 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002590 assert_eq!(
2591 read_ident_5,
2592 TFieldIdentifier {
2593 name: None,
2594 field_type: TType::Stop,
2595 id: None,
2596 }
2597 );
Allen George8b96bfb2016-11-02 08:01:08 -04002598
2599 assert_success!(i_prot.read_struct_end());
2600 }
2601
2602 #[test]
2603 #[should_panic]
2604 fn must_fail_if_write_field_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002605 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002606 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2607 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2608 o_prot.write_field_end().unwrap();
2609 }
2610
2611 #[test]
2612 #[should_panic]
2613 fn must_fail_if_write_stop_field_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002614 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002615 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2616 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2617 o_prot.write_field_stop().unwrap();
2618 }
2619
2620 #[test]
2621 #[should_panic]
2622 fn must_fail_if_write_struct_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002623 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002624 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2625 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2626 o_prot.write_struct_end().unwrap();
2627 }
2628
2629 #[test]
2630 #[should_panic]
2631 fn must_fail_if_write_struct_end_without_any_fields() {
Allen George0e22c362017-01-30 07:15:00 -05002632 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002633 o_prot.write_struct_end().unwrap();
2634 }
2635
2636 #[test]
2637 fn must_write_field_end() {
2638 assert_no_write(|o| o.write_field_end());
2639 }
2640
2641 #[test]
2642 fn must_write_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002643 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002644
2645 assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
2646
2647 let expected: [u8; 1] = [0x46 /* size | elem_type */];
2648
Allen George0e22c362017-01-30 07:15:00 -05002649 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002650 }
2651
2652 #[test]
2653 fn must_round_trip_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002654 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002655
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002656 let ident = TListIdentifier::new(TType::I32, 3);
Allen George8b96bfb2016-11-02 08:01:08 -04002657 assert_success!(o_prot.write_list_begin(&ident));
2658
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002659 assert_success!(o_prot.write_i32(100));
2660 assert_success!(o_prot.write_i32(200));
2661 assert_success!(o_prot.write_i32(300));
2662
2663 assert_success!(o_prot.write_list_end());
2664
Allen George0e22c362017-01-30 07:15:00 -05002665 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002666
2667 let res = assert_success!(i_prot.read_list_begin());
2668 assert_eq!(&res, &ident);
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002669
2670 assert_eq!(i_prot.read_i32().unwrap(), 100);
2671 assert_eq!(i_prot.read_i32().unwrap(), 200);
2672 assert_eq!(i_prot.read_i32().unwrap(), 300);
2673
2674 assert_success!(i_prot.read_list_end());
Allen George8b96bfb2016-11-02 08:01:08 -04002675 }
2676
2677 #[test]
2678 fn must_write_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002679 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002680
2681 let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
2682 assert!(res.is_ok());
2683
Allen George0e22c362017-01-30 07:15:00 -05002684 let expected: [u8; 3] = [
2685 0xF9, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002686 0x8F, 0x4E, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002687 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002688
Allen George0e22c362017-01-30 07:15:00 -05002689 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002690 }
2691
2692 #[test]
2693 fn must_round_trip_large_sized_list_begin() {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002694 let (mut i_prot, mut o_prot) = test_objects_no_limits();
Allen George8b96bfb2016-11-02 08:01:08 -04002695
2696 let ident = TListIdentifier::new(TType::Set, 47381);
Allen George8b96bfb2016-11-02 08:01:08 -04002697 assert_success!(o_prot.write_list_begin(&ident));
2698
Allen George0e22c362017-01-30 07:15:00 -05002699 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002700
2701 let res = assert_success!(i_prot.read_list_begin());
2702 assert_eq!(&res, &ident);
2703 }
2704
2705 #[test]
2706 fn must_write_list_end() {
2707 assert_no_write(|o| o.write_list_end());
2708 }
2709
2710 #[test]
2711 fn must_write_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002712 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002713
2714 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
2715
2716 let expected: [u8; 1] = [0x2C /* size | elem_type */];
2717
Allen George0e22c362017-01-30 07:15:00 -05002718 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002719 }
2720
2721 #[test]
2722 fn must_round_trip_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002723 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002724
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002725 let ident = TSetIdentifier::new(TType::I16, 3);
Allen George8b96bfb2016-11-02 08:01:08 -04002726 assert_success!(o_prot.write_set_begin(&ident));
2727
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002728 assert_success!(o_prot.write_i16(111));
2729 assert_success!(o_prot.write_i16(222));
2730 assert_success!(o_prot.write_i16(333));
2731
2732 assert_success!(o_prot.write_set_end());
2733
Allen George0e22c362017-01-30 07:15:00 -05002734 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002735
2736 let res = assert_success!(i_prot.read_set_begin());
2737 assert_eq!(&res, &ident);
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002738
2739 assert_eq!(i_prot.read_i16().unwrap(), 111);
2740 assert_eq!(i_prot.read_i16().unwrap(), 222);
2741 assert_eq!(i_prot.read_i16().unwrap(), 333);
2742
2743 assert_success!(i_prot.read_set_end());
Allen George8b96bfb2016-11-02 08:01:08 -04002744 }
2745
2746 #[test]
2747 fn must_write_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002748 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002749
2750 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
2751
Allen George0e22c362017-01-30 07:15:00 -05002752 let expected: [u8; 4] = [
2753 0xF7, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002754 0xD3, 0xBA, 0x01, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002755 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002756
Allen George0e22c362017-01-30 07:15:00 -05002757 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002758 }
2759
2760 #[test]
2761 fn must_round_trip_large_sized_set_begin() {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002762 let (mut i_prot, mut o_prot) = test_objects_no_limits();
Allen George8b96bfb2016-11-02 08:01:08 -04002763
Allen George7ddbcc02020-11-08 09:51:19 -05002764 let ident = TSetIdentifier::new(TType::Map, 3_928_429);
Allen George8b96bfb2016-11-02 08:01:08 -04002765 assert_success!(o_prot.write_set_begin(&ident));
2766
Allen George0e22c362017-01-30 07:15:00 -05002767 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002768
2769 let res = assert_success!(i_prot.read_set_begin());
2770 assert_eq!(&res, &ident);
2771 }
2772
2773 #[test]
2774 fn must_write_set_end() {
2775 assert_no_write(|o| o.write_set_end());
2776 }
2777
2778 #[test]
2779 fn must_write_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002780 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002781
2782 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
2783
2784 let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything
2785
Allen George0e22c362017-01-30 07:15:00 -05002786 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002787 }
2788
2789 #[test]
2790 fn must_read_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002791 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002792
2793 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
2794
Allen George0e22c362017-01-30 07:15:00 -05002795 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002796
2797 let res = assert_success!(i_prot.read_map_begin());
Allen George0e22c362017-01-30 07:15:00 -05002798 assert_eq!(
2799 &res,
2800 &TMapIdentifier {
Allen Georgeef7a1892018-12-16 18:01:37 -05002801 key_type: None,
2802 value_type: None,
2803 size: 0,
2804 }
Allen George0e22c362017-01-30 07:15:00 -05002805 );
Allen George8b96bfb2016-11-02 08:01:08 -04002806 }
2807
2808 #[test]
2809 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002810 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002811
Allen Georgeef7a1892018-12-16 18:01:37 -05002812 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
2813 TType::Double,
2814 TType::String,
2815 238
2816 )));
Allen George8b96bfb2016-11-02 08:01:08 -04002817
Allen George0e22c362017-01-30 07:15:00 -05002818 let expected: [u8; 3] = [
Allen Georgeef7a1892018-12-16 18:01:37 -05002819 0xEE, 0x01, /* size as varint */
2820 0x78, /* key type | val type */
Allen George0e22c362017-01-30 07:15:00 -05002821 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002822
Allen George0e22c362017-01-30 07:15:00 -05002823 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002824 }
2825
2826 #[test]
2827 fn must_round_trip_map_begin() {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002828 let (mut i_prot, mut o_prot) = test_objects_no_limits();
Allen George8b96bfb2016-11-02 08:01:08 -04002829
Allen George7ddbcc02020-11-08 09:51:19 -05002830 let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349);
Allen George8b96bfb2016-11-02 08:01:08 -04002831 assert_success!(o_prot.write_map_begin(&ident));
2832
Allen George0e22c362017-01-30 07:15:00 -05002833 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002834
2835 let res = assert_success!(i_prot.read_map_begin());
2836 assert_eq!(&res, &ident);
2837 }
2838
2839 #[test]
2840 fn must_write_map_end() {
2841 assert_no_write(|o| o.write_map_end());
2842 }
2843
2844 #[test]
2845 fn must_write_map_with_bool_key_and_value() {
Allen George0e22c362017-01-30 07:15:00 -05002846 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002847
2848 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
2849 assert_success!(o_prot.write_bool(true));
2850 assert_success!(o_prot.write_bool(false));
2851 assert_success!(o_prot.write_map_end());
2852
Allen George0e22c362017-01-30 07:15:00 -05002853 let expected: [u8; 4] = [
2854 0x01, /* size as varint */
2855 0x11, /* key type | val type */
2856 0x01, /* key: true */
Allen Georgeef7a1892018-12-16 18:01:37 -05002857 0x02, /* val: false */
Allen George0e22c362017-01-30 07:15:00 -05002858 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002859
Allen George0e22c362017-01-30 07:15:00 -05002860 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002861 }
2862
2863 #[test]
2864 fn must_round_trip_map_with_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002865 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002866
2867 let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
2868 assert_success!(o_prot.write_map_begin(&map_ident));
2869 assert_success!(o_prot.write_bool(true));
2870 assert_success!(o_prot.write_bool(false));
2871 assert_success!(o_prot.write_bool(false));
2872 assert_success!(o_prot.write_bool(true));
2873 assert_success!(o_prot.write_map_end());
2874
Allen George0e22c362017-01-30 07:15:00 -05002875 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002876
2877 // map header
2878 let rcvd_ident = assert_success!(i_prot.read_map_begin());
2879 assert_eq!(&rcvd_ident, &map_ident);
2880 // key 1
2881 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002882 assert!(b);
Allen George8b96bfb2016-11-02 08:01:08 -04002883 // val 1
2884 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002885 assert!(!b);
Allen George8b96bfb2016-11-02 08:01:08 -04002886 // key 2
2887 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002888 assert!(!b);
Allen George8b96bfb2016-11-02 08:01:08 -04002889 // val 2
2890 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002891 assert!(b);
Allen George8b96bfb2016-11-02 08:01:08 -04002892 // map end
2893 assert_success!(i_prot.read_map_end());
2894 }
2895
2896 #[test]
2897 fn must_read_map_end() {
Allen George0e22c362017-01-30 07:15:00 -05002898 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002899 assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
2900 }
2901
Allen Georgeef7a1892018-12-16 18:01:37 -05002902 fn test_objects() -> (
2903 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2904 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2905 ) {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002906 let mem = TBufferChannel::with_capacity(200, 200);
Allen George8b96bfb2016-11-02 08:01:08 -04002907
Allen George0e22c362017-01-30 07:15:00 -05002908 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -04002909
Allen George0e22c362017-01-30 07:15:00 -05002910 let i_prot = TCompactInputProtocol::new(r_mem);
2911 let o_prot = TCompactOutputProtocol::new(w_mem);
Allen George8b96bfb2016-11-02 08:01:08 -04002912
Allen George0e22c362017-01-30 07:15:00 -05002913 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -04002914 }
2915
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002916 fn test_objects_no_limits() -> (
2917 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2918 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2919 ) {
2920 let mem = TBufferChannel::with_capacity(200, 200);
2921
2922 let (r_mem, w_mem) = mem.split().unwrap();
2923
2924 let i_prot = TCompactInputProtocol::with_config(r_mem, TConfiguration::no_limits());
2925 let o_prot = TCompactOutputProtocol::new(w_mem);
2926
2927 (i_prot, o_prot)
2928 }
2929
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002930 #[test]
2931 fn must_read_write_double() {
2932 let (mut i_prot, mut o_prot) = test_objects();
2933
Allen George7ddbcc02020-11-08 09:51:19 -05002934 #[allow(clippy::approx_constant)]
2935 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002936 o_prot.write_double(double).unwrap();
2937 copy_write_buffer_to_read_buffer!(o_prot);
2938
Allen George7ddbcc02020-11-08 09:51:19 -05002939 let read_double = i_prot.read_double().unwrap();
Cameron Martinda54fc82025-01-12 08:55:45 +00002940 assert!((read_double - double).abs() < f64::EPSILON);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002941 }
2942
2943 #[test]
2944 fn must_encode_double_as_other_langs() {
2945 let (_, mut o_prot) = test_objects();
2946 let expected = [24, 45, 68, 84, 251, 33, 9, 64];
2947
Allen George7ddbcc02020-11-08 09:51:19 -05002948 #[allow(clippy::approx_constant)]
2949 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002950 o_prot.write_double(double).unwrap();
2951
2952 assert_eq_written_bytes!(o_prot, expected);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002953 }
2954
Allen George0e22c362017-01-30 07:15:00 -05002955 fn assert_no_write<F>(mut write_fn: F)
2956 where
Allen Georgeb0d14132020-03-29 11:48:55 -04002957 F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> crate::Result<()>,
Allen George0e22c362017-01-30 07:15:00 -05002958 {
2959 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002960 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -05002961 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -04002962 }
Jörn Horstmann717bd792025-02-02 23:10:27 +01002963
2964 #[test]
2965 fn must_read_boolean_list() {
2966 let (mut i_prot, _) = test_objects();
2967
2968 let source_bytes: [u8; 3] = [0x21, 2, 1];
2969
2970 i_prot.transport.set_readable_bytes(&source_bytes);
2971
2972 let (ttype, element_count) = assert_success!(i_prot.read_list_set_begin());
2973
2974 assert_eq!(ttype, TType::Bool);
2975 assert_eq!(element_count, 2);
2976 assert_eq!(i_prot.read_bool().unwrap(), false);
2977 assert_eq!(i_prot.read_bool().unwrap(), true);
2978
2979 assert_success!(i_prot.read_list_end());
2980 }
2981
2982 #[test]
2983 fn must_read_boolean_list_alternative_encoding() {
2984 let (mut i_prot, _) = test_objects();
2985
2986 let source_bytes: [u8; 3] = [0x22, 0, 1];
2987
2988 i_prot.transport.set_readable_bytes(&source_bytes);
2989
2990 let (ttype, element_count) = assert_success!(i_prot.read_list_set_begin());
2991
2992 assert_eq!(ttype, TType::Bool);
2993 assert_eq!(element_count, 2);
2994 assert_eq!(i_prot.read_bool().unwrap(), false);
2995 assert_eq!(i_prot.read_bool().unwrap(), true);
2996
2997 assert_success!(i_prot.read_list_end());
2998 }
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07002999
3000 #[test]
3001 fn must_enforce_recursion_depth_limit() {
3002 let channel = TBufferChannel::with_capacity(100, 100);
3003
3004 // Create a configuration with a small recursion limit
3005 let config = TConfiguration::builder()
3006 .max_recursion_depth(Some(2))
3007 .build()
3008 .unwrap();
3009
3010 let mut protocol = TCompactInputProtocol::with_config(channel, config);
3011
3012 // First struct - should succeed
3013 assert!(protocol.read_struct_begin().is_ok());
3014
3015 // Second struct - should succeed (at limit)
3016 assert!(protocol.read_struct_begin().is_ok());
3017
3018 // Third struct - should fail (exceeds limit)
3019 let result = protocol.read_struct_begin();
3020 assert!(result.is_err());
3021 match result {
3022 Err(crate::Error::Protocol(e)) => {
3023 assert_eq!(e.kind, ProtocolErrorKind::DepthLimit);
3024 }
3025 _ => panic!("Expected protocol error with DepthLimit"),
3026 }
3027 }
3028
3029 #[test]
3030 fn must_check_container_size_overflow() {
3031 // Configure a small message size limit
3032 let config = TConfiguration::builder()
3033 .max_message_size(Some(1000))
3034 .max_frame_size(Some(1000))
3035 .build()
3036 .unwrap();
3037 let transport = TBufferChannel::with_capacity(100, 0);
3038 let mut i_prot = TCompactInputProtocol::with_config(transport, config);
3039
3040 // Write a list header that would require more memory than message size limit
3041 // List of 100 UUIDs (16 bytes each) = 1600 bytes > 1000 limit
3042 i_prot.transport.set_readable_bytes(&[
3043 0xFD, // element type UUID (0x0D) | count in next bytes (0xF0)
3044 0x64, // varint 100
3045 ]);
3046
3047 let result = i_prot.read_list_begin();
3048 assert!(result.is_err());
3049 match result {
3050 Err(crate::Error::Protocol(e)) => {
3051 assert_eq!(e.kind, ProtocolErrorKind::SizeLimit);
3052 assert!(e
3053 .message
3054 .contains("1600 bytes, exceeding message size limit of 1000"));
3055 }
3056 _ => panic!("Expected protocol error with SizeLimit"),
3057 }
3058 }
3059
3060 #[test]
3061 fn must_reject_negative_container_sizes() {
3062 let mut channel = TBufferChannel::with_capacity(100, 100);
3063
3064 let mut protocol = TCompactInputProtocol::new(channel.clone());
3065
3066 // Write header with negative size when decoded
3067 // In compact protocol, lists/sets use a header byte followed by size
3068 // We'll use 0x0F for element type and then a varint-encoded negative number
3069 channel.set_readable_bytes(&[
3070 0xF0, // Header: 15 in upper nibble (triggers varint read), List type in lower
3071 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, // Varint encoding of -1
3072 ]);
3073
3074 let result = protocol.read_list_begin();
3075 assert!(result.is_err());
3076 match result {
3077 Err(crate::Error::Protocol(e)) => {
3078 assert_eq!(e.kind, ProtocolErrorKind::NegativeSize);
3079 }
3080 _ => panic!("Expected protocol error with NegativeSize"),
3081 }
3082 }
3083
3084 #[test]
3085 fn must_enforce_container_size_limit() {
3086 let channel = TBufferChannel::with_capacity(100, 100);
3087 let (r_channel, mut w_channel) = channel.split().unwrap();
3088
3089 // Create protocol with explicit container size limit
3090 let config = TConfiguration::builder()
3091 .max_container_size(Some(1000))
3092 .build()
3093 .unwrap();
3094 let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3095
3096 // Write header with large size
3097 // Compact protocol: 0xF0 means size >= 15 is encoded as varint
3098 // Then we write a varint encoding 10000 (exceeds our limit of 1000)
3099 w_channel.set_readable_bytes(&[
3100 0xF0, // Header: 15 in upper nibble (triggers varint read), element type in lower
3101 0x90, 0x4E, // Varint encoding of 10000
3102 ]);
3103
3104 let result = protocol.read_list_begin();
3105 assert!(result.is_err());
3106 match result {
3107 Err(crate::Error::Protocol(e)) => {
3108 assert_eq!(e.kind, ProtocolErrorKind::SizeLimit);
3109 assert!(e.message.contains("exceeds maximum allowed size"));
3110 }
3111 _ => panic!("Expected protocol error with SizeLimit"),
3112 }
3113 }
3114
3115 #[test]
3116 fn must_handle_varint_size_overflow() {
3117 // Test that compact protocol properly handles varint-encoded sizes that would cause overflow
3118 let mut channel = TBufferChannel::with_capacity(100, 100);
3119
3120 let mut protocol = TCompactInputProtocol::new(channel.clone());
3121
3122 // Create input that encodes a very large size using varint encoding
3123 // 0xFA = list header with size >= 15 (so size follows as varint)
3124 // Then multiple 0xFF bytes which in varint encoding create a very large number
3125 channel.set_readable_bytes(&[
3126 0xFA, // List header: size >= 15, element type = 0x0A
3127 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, // Varint encoding of a huge number
3128 ]);
3129
3130 let result = protocol.read_list_begin();
3131 assert!(result.is_err());
3132 match result {
3133 Err(crate::Error::Protocol(e)) => {
3134 // The varint decoder might interpret this as negative, which is also fine
3135 assert!(
3136 e.kind == ProtocolErrorKind::SizeLimit
3137 || e.kind == ProtocolErrorKind::NegativeSize,
3138 "Expected SizeLimit or NegativeSize but got {:?}",
3139 e.kind
3140 );
3141 }
3142 _ => panic!("Expected protocol error"),
3143 }
3144 }
3145
3146 #[test]
3147 fn must_enforce_string_size_limit() {
3148 let channel = TBufferChannel::with_capacity(100, 100);
3149 let (r_channel, mut w_channel) = channel.split().unwrap();
3150
3151 // Create protocol with string limit of 100 bytes
3152 let config = TConfiguration::builder()
3153 .max_string_size(Some(100))
3154 .build()
3155 .unwrap();
3156 let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3157
3158 // Write a varint-encoded string size that exceeds the limit
3159 w_channel.set_readable_bytes(&[
3160 0xC8, 0x01, // Varint encoding of 200
3161 ]);
3162
3163 let result = protocol.read_string();
3164 assert!(result.is_err());
3165 match result {
3166 Err(crate::Error::Protocol(e)) => {
3167 assert_eq!(e.kind, ProtocolErrorKind::SizeLimit);
3168 assert!(e.message.contains("exceeds maximum allowed size"));
3169 }
3170 _ => panic!("Expected protocol error with SizeLimit"),
3171 }
3172 }
3173
3174 #[test]
3175 fn must_allow_no_limit_configuration() {
3176 let channel = TBufferChannel::with_capacity(40, 40);
3177
3178 let config = TConfiguration::no_limits();
3179 let mut protocol = TCompactInputProtocol::with_config(channel, config);
3180
3181 // Should be able to nest structs deeply without limit
3182 for _ in 0..100 {
3183 assert!(protocol.read_struct_begin().is_ok());
3184 }
3185
3186 for _ in 0..100 {
3187 assert!(protocol.read_struct_end().is_ok());
3188 }
3189 }
3190
3191 #[test]
3192 fn must_allow_containers_within_limit() {
3193 let channel = TBufferChannel::with_capacity(200, 200);
3194 let (r_channel, mut w_channel) = channel.split().unwrap();
3195
3196 // Create protocol with container limit of 100
3197 let config = TConfiguration::builder()
3198 .max_container_size(Some(100))
3199 .build()
3200 .unwrap();
3201 let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3202
3203 // Write a list with 5 i32 elements (well within limit of 100)
3204 // Compact protocol: size < 15 is encoded in header
3205 w_channel.set_readable_bytes(&[
3206 0x55, // Header: size=5, element type=5 (i32)
3207 // 5 varint-encoded i32 values
3208 0x0A, // 10
3209 0x14, // 20
3210 0x1E, // 30
3211 0x28, // 40
3212 0x32, // 50
3213 ]);
3214
3215 let result = protocol.read_list_begin();
3216 assert!(result.is_ok());
3217 let list_ident = result.unwrap();
3218 assert_eq!(list_ident.size, 5);
3219 assert_eq!(list_ident.element_type, TType::I32);
3220 }
3221
3222 #[test]
3223 fn must_allow_strings_within_limit() {
3224 let channel = TBufferChannel::with_capacity(100, 100);
3225 let (r_channel, mut w_channel) = channel.split().unwrap();
3226
3227 let config = TConfiguration::builder()
3228 .max_string_size(Some(1000))
3229 .build()
3230 .unwrap();
3231 let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3232
3233 // Write a string "hello" (5 bytes, well within limit)
3234 w_channel.set_readable_bytes(&[
3235 0x05, // Varint-encoded length: 5
3236 b'h', b'e', b'l', b'l', b'o',
3237 ]);
3238
3239 let result = protocol.read_string();
3240 assert!(result.is_ok());
3241 assert_eq!(result.unwrap(), "hello");
3242 }
Allen George8b96bfb2016-11-02 08:01:08 -04003243}