blob: 4dc45cac2fd9a6727234db6180f1d97601d724f6 [file] [log] [blame]
Allen George8b96bfb2016-11-02 08:01:08 -04001// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
Marcin Pajkowskib34680f2019-12-02 10:29:16 +010018use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
Allen George8b96bfb2016-11-02 08:01:08 -040019use integer_encoding::{VarIntReader, VarIntWriter};
Danny Browningddec4312019-03-08 14:20:41 -070020use std::convert::{From, TryFrom};
Vadim Chekand3355af2018-01-05 23:12:47 -050021use std::io;
Allen George8b96bfb2016-11-02 08:01:08 -040022
Allen Georgeef7a1892018-12-16 18:01:37 -050023use super::{
24 TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier, TMapIdentifier,
25 TMessageIdentifier, TMessageType,
26};
Allen George8b96bfb2016-11-02 08:01:08 -040027use super::{TOutputProtocol, TOutputProtocolFactory, TSetIdentifier, TStructIdentifier, TType};
Allen Georgeb0d14132020-03-29 11:48:55 -040028use crate::transport::{TReadTransport, TWriteTransport};
Allen George8b96bfb2016-11-02 08:01:08 -040029
30const COMPACT_PROTOCOL_ID: u8 = 0x82;
31const COMPACT_VERSION: u8 = 0x01;
32const COMPACT_VERSION_MASK: u8 = 0x1F;
33
34/// Read messages encoded in the Thrift compact protocol.
35///
36/// # Examples
37///
38/// Create and use a `TCompactInputProtocol`.
39///
40/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -040041/// use thrift::protocol::{TCompactInputProtocol, TInputProtocol};
Allen George0e22c362017-01-30 07:15:00 -050042/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -040043///
Allen George0e22c362017-01-30 07:15:00 -050044/// let mut channel = TTcpChannel::new();
45/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040046///
Allen George0e22c362017-01-30 07:15:00 -050047/// let mut protocol = TCompactInputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -040048///
Allen George0e22c362017-01-30 07:15:00 -050049/// let recvd_bool = protocol.read_bool().unwrap();
50/// let recvd_string = protocol.read_string().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040051/// ```
Allen George0e22c362017-01-30 07:15:00 -050052#[derive(Debug)]
53pub struct TCompactInputProtocol<T>
54where
55 T: TReadTransport,
56{
Allen George8b96bfb2016-11-02 08:01:08 -040057 // Identifier of the last field deserialized for a struct.
58 last_read_field_id: i16,
59 // Stack of the last read field ids (a new entry is added each time a nested struct is read).
60 read_field_id_stack: Vec<i16>,
61 // Boolean value for a field.
62 // Saved because boolean fields and their value are encoded in a single byte,
63 // and reading the field only occurs after the field id is read.
64 pending_read_bool_value: Option<bool>,
65 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -050066 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -040067}
68
Allen George0e22c362017-01-30 07:15:00 -050069impl<T> TCompactInputProtocol<T>
70where
71 T: TReadTransport,
72{
Allen George8b96bfb2016-11-02 08:01:08 -040073 /// Create a `TCompactInputProtocol` that reads bytes from `transport`.
Allen George0e22c362017-01-30 07:15:00 -050074 pub fn new(transport: T) -> TCompactInputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -040075 TCompactInputProtocol {
76 last_read_field_id: 0,
77 read_field_id_stack: Vec::new(),
78 pending_read_bool_value: None,
Allen George7ddbcc02020-11-08 09:51:19 -050079 transport,
Allen George8b96bfb2016-11-02 08:01:08 -040080 }
81 }
82
Allen Georgeb0d14132020-03-29 11:48:55 -040083 fn read_list_set_begin(&mut self) -> crate::Result<(TType, i32)> {
Allen George8b96bfb2016-11-02 08:01:08 -040084 let header = self.read_byte()?;
85 let element_type = collection_u8_to_type(header & 0x0F)?;
86
Allen George8b96bfb2016-11-02 08:01:08 -040087 let possible_element_count = (header & 0xF0) >> 4;
Tdxdxoz85d82bf2022-07-17 14:14:12 +020088 let element_count = if possible_element_count != 15 {
Allen George8b96bfb2016-11-02 08:01:08 -040089 // high bits set high if count and type encoded separately
Tdxdxoz85d82bf2022-07-17 14:14:12 +020090 possible_element_count as i32
Allen George8b96bfb2016-11-02 08:01:08 -040091 } else {
Tdxdxoz85d82bf2022-07-17 14:14:12 +020092 self.transport.read_varint::<u32>()? as i32
93 };
Allen George8b96bfb2016-11-02 08:01:08 -040094
95 Ok((element_type, element_count))
96 }
97}
98
Allen George0e22c362017-01-30 07:15:00 -050099impl<T> TInputProtocol for TCompactInputProtocol<T>
100where
101 T: TReadTransport,
102{
Allen Georgeb0d14132020-03-29 11:48:55 -0400103 fn read_message_begin(&mut self) -> crate::Result<TMessageIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400104 let compact_id = self.read_byte()?;
105 if compact_id != COMPACT_PROTOCOL_ID {
Allen Georgeb0d14132020-03-29 11:48:55 -0400106 Err(crate::Error::Protocol(crate::ProtocolError {
107 kind: crate::ProtocolErrorKind::BadVersion,
Allen Georgeef7a1892018-12-16 18:01:37 -0500108 message: format!("invalid compact protocol header {:?}", compact_id),
109 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400110 } else {
111 Ok(())
112 }?;
113
114 let type_and_byte = self.read_byte()?;
115 let received_version = type_and_byte & COMPACT_VERSION_MASK;
116 if received_version != COMPACT_VERSION {
Allen Georgeb0d14132020-03-29 11:48:55 -0400117 Err(crate::Error::Protocol(crate::ProtocolError {
118 kind: crate::ProtocolErrorKind::BadVersion,
Allen Georgeef7a1892018-12-16 18:01:37 -0500119 message: format!(
120 "cannot process compact protocol version {:?}",
121 received_version
Allen George0e22c362017-01-30 07:15:00 -0500122 ),
Allen Georgeef7a1892018-12-16 18:01:37 -0500123 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400124 } else {
125 Ok(())
126 }?;
127
128 // NOTE: unsigned right shift will pad with 0s
129 let message_type: TMessageType = TMessageType::try_from(type_and_byte >> 5)?;
Allen George48905102021-02-20 08:47:01 -0500130 // writing side wrote signed sequence number as u32 to avoid zigzag encoding
131 let sequence_number = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400132 let service_call_name = self.read_string()?;
133
134 self.last_read_field_id = 0;
135
Allen Georgeef7a1892018-12-16 18:01:37 -0500136 Ok(TMessageIdentifier::new(
137 service_call_name,
138 message_type,
139 sequence_number,
140 ))
Allen George8b96bfb2016-11-02 08:01:08 -0400141 }
142
Allen Georgeb0d14132020-03-29 11:48:55 -0400143 fn read_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400144 Ok(())
145 }
146
Allen Georgeb0d14132020-03-29 11:48:55 -0400147 fn read_struct_begin(&mut self) -> crate::Result<Option<TStructIdentifier>> {
Allen George8b96bfb2016-11-02 08:01:08 -0400148 self.read_field_id_stack.push(self.last_read_field_id);
149 self.last_read_field_id = 0;
150 Ok(None)
151 }
152
Allen Georgeb0d14132020-03-29 11:48:55 -0400153 fn read_struct_end(&mut self) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500154 self.last_read_field_id = self
155 .read_field_id_stack
Allen George8b96bfb2016-11-02 08:01:08 -0400156 .pop()
157 .expect("should have previous field ids");
158 Ok(())
159 }
160
Allen Georgeb0d14132020-03-29 11:48:55 -0400161 fn read_field_begin(&mut self) -> crate::Result<TFieldIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400162 // we can read at least one byte, which is:
163 // - the type
164 // - the field delta and the type
165 let field_type = self.read_byte()?;
166 let field_delta = (field_type & 0xF0) >> 4;
167 let field_type = match field_type & 0x0F {
168 0x01 => {
169 self.pending_read_bool_value = Some(true);
170 Ok(TType::Bool)
171 }
172 0x02 => {
173 self.pending_read_bool_value = Some(false);
174 Ok(TType::Bool)
175 }
176 ttu8 => u8_to_type(ttu8),
177 }?;
178
179 match field_type {
Allen Georgeef7a1892018-12-16 18:01:37 -0500180 TType::Stop => Ok(
181 TFieldIdentifier::new::<Option<String>, String, Option<i16>>(
182 None,
183 TType::Stop,
184 None,
185 ),
186 ),
Allen George8b96bfb2016-11-02 08:01:08 -0400187 _ => {
188 if field_delta != 0 {
189 self.last_read_field_id += field_delta as i16;
190 } else {
191 self.last_read_field_id = self.read_i16()?;
192 };
193
Allen Georgeef7a1892018-12-16 18:01:37 -0500194 Ok(TFieldIdentifier {
195 name: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500196 field_type,
Allen Georgeef7a1892018-12-16 18:01:37 -0500197 id: Some(self.last_read_field_id),
198 })
Allen George8b96bfb2016-11-02 08:01:08 -0400199 }
200 }
201 }
202
Allen Georgeb0d14132020-03-29 11:48:55 -0400203 fn read_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400204 Ok(())
205 }
206
Allen Georgeb0d14132020-03-29 11:48:55 -0400207 fn read_bool(&mut self) -> crate::Result<bool> {
Allen George8b96bfb2016-11-02 08:01:08 -0400208 match self.pending_read_bool_value.take() {
209 Some(b) => Ok(b),
210 None => {
211 let b = self.read_byte()?;
212 match b {
Jörn Horstmann717bd792025-02-02 23:10:27 +0100213 // Previous versions of the thrift compact protocol specification said to use 0
214 // and 1 inside collections, but that differed from existing implementations.
215 // The specification was updated in https://github.com/apache/thrift/commit/2c29c5665bc442e703480bb0ee60fe925ffe02e8.
216 0x00 => Ok(false),
Allen George8b96bfb2016-11-02 08:01:08 -0400217 0x01 => Ok(true),
218 0x02 => Ok(false),
Allen Georgeb0d14132020-03-29 11:48:55 -0400219 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
220 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500221 message: format!("cannot convert {} into bool", unkn),
222 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400223 }
224 }
225 }
226 }
227
Allen Georgeb0d14132020-03-29 11:48:55 -0400228 fn read_bytes(&mut self) -> crate::Result<Vec<u8>> {
Allen George0e22c362017-01-30 07:15:00 -0500229 let len = self.transport.read_varint::<u32>()?;
Allen George8b96bfb2016-11-02 08:01:08 -0400230 let mut buf = vec![0u8; len as usize];
Allen George0e22c362017-01-30 07:15:00 -0500231 self.transport
232 .read_exact(&mut buf)
233 .map_err(From::from)
234 .map(|_| buf)
Allen George8b96bfb2016-11-02 08:01:08 -0400235 }
236
Allen Georgeb0d14132020-03-29 11:48:55 -0400237 fn read_i8(&mut self) -> crate::Result<i8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400238 self.read_byte().map(|i| i as i8)
239 }
240
Allen Georgeb0d14132020-03-29 11:48:55 -0400241 fn read_i16(&mut self) -> crate::Result<i16> {
Allen George0e22c362017-01-30 07:15:00 -0500242 self.transport.read_varint::<i16>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400243 }
244
Allen Georgeb0d14132020-03-29 11:48:55 -0400245 fn read_i32(&mut self) -> crate::Result<i32> {
Allen George0e22c362017-01-30 07:15:00 -0500246 self.transport.read_varint::<i32>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400247 }
248
Allen Georgeb0d14132020-03-29 11:48:55 -0400249 fn read_i64(&mut self) -> crate::Result<i64> {
Allen George0e22c362017-01-30 07:15:00 -0500250 self.transport.read_varint::<i64>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400251 }
252
Allen Georgeb0d14132020-03-29 11:48:55 -0400253 fn read_double(&mut self) -> crate::Result<f64> {
Allen George8a1743d2020-12-05 01:19:27 -0500254 self.transport
255 .read_f64::<LittleEndian>()
256 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400257 }
258
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800259 fn read_uuid(&mut self) -> crate::Result<uuid::Uuid> {
260 uuid::Uuid::from_slice(&self.read_bytes()?).map_err(From::from)
261 }
262
Allen Georgeb0d14132020-03-29 11:48:55 -0400263 fn read_string(&mut self) -> crate::Result<String> {
Allen George8b96bfb2016-11-02 08:01:08 -0400264 let bytes = self.read_bytes()?;
265 String::from_utf8(bytes).map_err(From::from)
266 }
267
Allen Georgeb0d14132020-03-29 11:48:55 -0400268 fn read_list_begin(&mut self) -> crate::Result<TListIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400269 let (element_type, element_count) = self.read_list_set_begin()?;
270 Ok(TListIdentifier::new(element_type, element_count))
271 }
272
Allen Georgeb0d14132020-03-29 11:48:55 -0400273 fn read_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400274 Ok(())
275 }
276
Allen Georgeb0d14132020-03-29 11:48:55 -0400277 fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400278 let (element_type, element_count) = self.read_list_set_begin()?;
279 Ok(TSetIdentifier::new(element_type, element_count))
280 }
281
Allen Georgeb0d14132020-03-29 11:48:55 -0400282 fn read_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400283 Ok(())
284 }
285
Allen Georgeb0d14132020-03-29 11:48:55 -0400286 fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier> {
Allen George0e22c362017-01-30 07:15:00 -0500287 let element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400288 if element_count == 0 {
289 Ok(TMapIdentifier::new(None, None, 0))
290 } else {
291 let type_header = self.read_byte()?;
292 let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
293 let val_type = collection_u8_to_type(type_header & 0x0F)?;
294 Ok(TMapIdentifier::new(key_type, val_type, element_count))
295 }
296 }
297
Allen Georgeb0d14132020-03-29 11:48:55 -0400298 fn read_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400299 Ok(())
300 }
301
302 // utility
303 //
304
Allen Georgeb0d14132020-03-29 11:48:55 -0400305 fn read_byte(&mut self) -> crate::Result<u8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400306 let mut buf = [0u8; 1];
Allen George0e22c362017-01-30 07:15:00 -0500307 self.transport
308 .read_exact(&mut buf)
309 .map_err(From::from)
310 .map(|_| buf[0])
Allen George8b96bfb2016-11-02 08:01:08 -0400311 }
312}
313
Vadim Chekand3355af2018-01-05 23:12:47 -0500314impl<T> io::Seek for TCompactInputProtocol<T>
315where
316 T: io::Seek + TReadTransport,
317{
318 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
319 self.transport.seek(pos)
320 }
321}
322
Allen George8b96bfb2016-11-02 08:01:08 -0400323/// Factory for creating instances of `TCompactInputProtocol`.
324#[derive(Default)]
325pub struct TCompactInputProtocolFactory;
326
327impl TCompactInputProtocolFactory {
328 /// Create a `TCompactInputProtocolFactory`.
329 pub fn new() -> TCompactInputProtocolFactory {
330 TCompactInputProtocolFactory {}
331 }
332}
333
334impl TInputProtocolFactory for TCompactInputProtocolFactory {
Danny Browning77d96c12019-08-21 13:41:07 -0600335 fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500336 Box::new(TCompactInputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400337 }
338}
339
340/// Write messages using the Thrift compact protocol.
341///
342/// # Examples
343///
344/// Create and use a `TCompactOutputProtocol`.
345///
346/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -0400347/// use thrift::protocol::{TCompactOutputProtocol, TOutputProtocol};
Allen George0e22c362017-01-30 07:15:00 -0500348/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -0400349///
Allen George0e22c362017-01-30 07:15:00 -0500350/// let mut channel = TTcpChannel::new();
351/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400352///
Allen George0e22c362017-01-30 07:15:00 -0500353/// let mut protocol = TCompactOutputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -0400354///
Allen George0e22c362017-01-30 07:15:00 -0500355/// protocol.write_bool(true).unwrap();
356/// protocol.write_string("test_string").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400357/// ```
Allen George0e22c362017-01-30 07:15:00 -0500358#[derive(Debug)]
359pub struct TCompactOutputProtocol<T>
360where
361 T: TWriteTransport,
362{
Allen George8b96bfb2016-11-02 08:01:08 -0400363 // Identifier of the last field serialized for a struct.
364 last_write_field_id: i16,
Allen George0e22c362017-01-30 07:15:00 -0500365 // Stack of the last written field ids (new entry added each time a nested struct is written).
Allen George8b96bfb2016-11-02 08:01:08 -0400366 write_field_id_stack: Vec<i16>,
367 // Field identifier of the boolean field to be written.
368 // Saved because boolean fields and their value are encoded in a single byte
369 pending_write_bool_field_identifier: Option<TFieldIdentifier>,
370 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -0500371 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -0400372}
373
Allen George0e22c362017-01-30 07:15:00 -0500374impl<T> TCompactOutputProtocol<T>
375where
376 T: TWriteTransport,
377{
Allen George8b96bfb2016-11-02 08:01:08 -0400378 /// Create a `TCompactOutputProtocol` that writes bytes to `transport`.
Allen George0e22c362017-01-30 07:15:00 -0500379 pub fn new(transport: T) -> TCompactOutputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -0400380 TCompactOutputProtocol {
381 last_write_field_id: 0,
382 write_field_id_stack: Vec::new(),
383 pending_write_bool_field_identifier: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500384 transport,
Allen George8b96bfb2016-11-02 08:01:08 -0400385 }
386 }
387
388 // FIXME: field_type as unconstrained u8 is bad
Allen Georgeb0d14132020-03-29 11:48:55 -0400389 fn write_field_header(&mut self, field_type: u8, field_id: i16) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400390 let field_delta = field_id - self.last_write_field_id;
391 if field_delta > 0 && field_delta < 15 {
392 self.write_byte(((field_delta as u8) << 4) | field_type)?;
393 } else {
394 self.write_byte(field_type)?;
395 self.write_i16(field_id)?;
396 }
397 self.last_write_field_id = field_id;
398 Ok(())
399 }
400
Allen George8a1743d2020-12-05 01:19:27 -0500401 fn write_list_set_begin(
402 &mut self,
403 element_type: TType,
404 element_count: i32,
405 ) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400406 let elem_identifier = collection_type_to_u8(element_type);
407 if element_count <= 14 {
408 let header = (element_count as u8) << 4 | elem_identifier;
409 self.write_byte(header)
410 } else {
411 let header = 0xF0 | elem_identifier;
412 self.write_byte(header)?;
Allen George48905102021-02-20 08:47:01 -0500413 // element count is strictly positive as per the spec, so
414 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George8b96bfb2016-11-02 08:01:08 -0400415 self.transport
Allen George8b96bfb2016-11-02 08:01:08 -0400416 .write_varint(element_count as u32)
417 .map_err(From::from)
418 .map(|_| ())
419 }
420 }
421
422 fn assert_no_pending_bool_write(&self) {
423 if let Some(ref f) = self.pending_write_bool_field_identifier {
424 panic!("pending bool field {:?} not written", f)
425 }
426 }
427}
428
Allen George0e22c362017-01-30 07:15:00 -0500429impl<T> TOutputProtocol for TCompactOutputProtocol<T>
430where
431 T: TWriteTransport,
432{
Allen Georgeb0d14132020-03-29 11:48:55 -0400433 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400434 self.write_byte(COMPACT_PROTOCOL_ID)?;
435 self.write_byte((u8::from(identifier.message_type) << 5) | COMPACT_VERSION)?;
Allen George48905102021-02-20 08:47:01 -0500436 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George55c3e4c2021-03-01 23:19:52 -0500437 self.transport
438 .write_varint(identifier.sequence_number as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400439 self.write_string(&identifier.name)?;
440 Ok(())
441 }
442
Allen Georgeb0d14132020-03-29 11:48:55 -0400443 fn write_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400444 self.assert_no_pending_bool_write();
445 Ok(())
446 }
447
Allen Georgeb0d14132020-03-29 11:48:55 -0400448 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400449 self.write_field_id_stack.push(self.last_write_field_id);
450 self.last_write_field_id = 0;
451 Ok(())
452 }
453
Allen Georgeb0d14132020-03-29 11:48:55 -0400454 fn write_struct_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400455 self.assert_no_pending_bool_write();
Allen Georgeef7a1892018-12-16 18:01:37 -0500456 self.last_write_field_id = self
457 .write_field_id_stack
Allen George0e22c362017-01-30 07:15:00 -0500458 .pop()
459 .expect("should have previous field ids");
Allen George8b96bfb2016-11-02 08:01:08 -0400460 Ok(())
461 }
462
Allen Georgeb0d14132020-03-29 11:48:55 -0400463 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400464 match identifier.field_type {
465 TType::Bool => {
466 if self.pending_write_bool_field_identifier.is_some() {
Allen George0e22c362017-01-30 07:15:00 -0500467 panic!(
468 "should not have a pending bool while writing another bool with id: \
Allen Georgeef7a1892018-12-16 18:01:37 -0500469 {:?}",
Allen George0e22c362017-01-30 07:15:00 -0500470 identifier
471 )
Allen George8b96bfb2016-11-02 08:01:08 -0400472 }
473 self.pending_write_bool_field_identifier = Some(identifier.clone());
474 Ok(())
475 }
476 _ => {
477 let field_type = type_to_u8(identifier.field_type);
Allen Georgeef7a1892018-12-16 18:01:37 -0500478 let field_id = identifier.id.expect("non-stop field should have field id");
Allen George8b96bfb2016-11-02 08:01:08 -0400479 self.write_field_header(field_type, field_id)
480 }
481 }
482 }
483
Allen Georgeb0d14132020-03-29 11:48:55 -0400484 fn write_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400485 self.assert_no_pending_bool_write();
486 Ok(())
487 }
488
Allen Georgeb0d14132020-03-29 11:48:55 -0400489 fn write_field_stop(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400490 self.assert_no_pending_bool_write();
491 self.write_byte(type_to_u8(TType::Stop))
492 }
493
Allen Georgeb0d14132020-03-29 11:48:55 -0400494 fn write_bool(&mut self, b: bool) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400495 match self.pending_write_bool_field_identifier.take() {
496 Some(pending) => {
497 let field_id = pending.id.expect("bool field should have a field id");
498 let field_type_as_u8 = if b { 0x01 } else { 0x02 };
499 self.write_field_header(field_type_as_u8, field_id)
500 }
501 None => {
502 if b {
503 self.write_byte(0x01)
504 } else {
505 self.write_byte(0x02)
506 }
507 }
508 }
509 }
510
Allen Georgeb0d14132020-03-29 11:48:55 -0400511 fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> {
Allen George48905102021-02-20 08:47:01 -0500512 // length is strictly positive as per the spec, so
513 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500514 self.transport.write_varint(b.len() as u32)?;
515 self.transport.write_all(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400516 }
517
Allen Georgeb0d14132020-03-29 11:48:55 -0400518 fn write_i8(&mut self, i: i8) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400519 self.write_byte(i as u8)
520 }
521
Allen Georgeb0d14132020-03-29 11:48:55 -0400522 fn write_i16(&mut self, i: i16) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500523 self.transport
Allen George48905102021-02-20 08:47:01 -0500524 .write_varint(i)
Allen George0e22c362017-01-30 07:15:00 -0500525 .map_err(From::from)
526 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400527 }
528
Allen Georgeb0d14132020-03-29 11:48:55 -0400529 fn write_i32(&mut self, i: i32) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500530 self.transport
531 .write_varint(i)
532 .map_err(From::from)
533 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400534 }
535
Allen Georgeb0d14132020-03-29 11:48:55 -0400536 fn write_i64(&mut self, i: i64) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500537 self.transport
538 .write_varint(i)
539 .map_err(From::from)
540 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400541 }
542
Allen Georgeb0d14132020-03-29 11:48:55 -0400543 fn write_double(&mut self, d: f64) -> crate::Result<()> {
Allen George8a1743d2020-12-05 01:19:27 -0500544 self.transport
545 .write_f64::<LittleEndian>(d)
546 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400547 }
548
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800549 fn write_uuid(&mut self, uuid: &uuid::Uuid) -> crate::Result<()> {
550 self.write_bytes(uuid.as_bytes())
551 }
552
Allen Georgeb0d14132020-03-29 11:48:55 -0400553 fn write_string(&mut self, s: &str) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400554 self.write_bytes(s.as_bytes())
555 }
556
Allen Georgeb0d14132020-03-29 11:48:55 -0400557 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400558 self.write_list_set_begin(identifier.element_type, identifier.size)
559 }
560
Allen Georgeb0d14132020-03-29 11:48:55 -0400561 fn write_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400562 Ok(())
563 }
564
Allen Georgeb0d14132020-03-29 11:48:55 -0400565 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400566 self.write_list_set_begin(identifier.element_type, identifier.size)
567 }
568
Allen Georgeb0d14132020-03-29 11:48:55 -0400569 fn write_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400570 Ok(())
571 }
572
Allen Georgeb0d14132020-03-29 11:48:55 -0400573 fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400574 if identifier.size == 0 {
575 self.write_byte(0)
576 } else {
Allen George48905102021-02-20 08:47:01 -0500577 // element count is strictly positive as per the spec, so
578 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500579 self.transport.write_varint(identifier.size as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400580
Allen George0e22c362017-01-30 07:15:00 -0500581 let key_type = identifier
582 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400583 .expect("map identifier to write should contain key type");
584 let key_type_byte = collection_type_to_u8(key_type) << 4;
585
Allen George0e22c362017-01-30 07:15:00 -0500586 let val_type = identifier
587 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400588 .expect("map identifier to write should contain value type");
589 let val_type_byte = collection_type_to_u8(val_type);
590
591 let map_type_header = key_type_byte | val_type_byte;
592 self.write_byte(map_type_header)
593 }
594 }
595
Allen Georgeb0d14132020-03-29 11:48:55 -0400596 fn write_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400597 Ok(())
598 }
599
Allen Georgeb0d14132020-03-29 11:48:55 -0400600 fn flush(&mut self) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500601 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400602 }
603
604 // utility
605 //
606
Allen Georgeb0d14132020-03-29 11:48:55 -0400607 fn write_byte(&mut self, b: u8) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500608 self.transport.write(&[b]).map_err(From::from).map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400609 }
610}
611
612/// Factory for creating instances of `TCompactOutputProtocol`.
613#[derive(Default)]
614pub struct TCompactOutputProtocolFactory;
615
616impl TCompactOutputProtocolFactory {
617 /// Create a `TCompactOutputProtocolFactory`.
618 pub fn new() -> TCompactOutputProtocolFactory {
619 TCompactOutputProtocolFactory {}
620 }
621}
622
623impl TOutputProtocolFactory for TCompactOutputProtocolFactory {
Allen George8a1743d2020-12-05 01:19:27 -0500624 fn create(
625 &self,
626 transport: Box<dyn TWriteTransport + Send>,
627 ) -> Box<dyn TOutputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500628 Box::new(TCompactOutputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400629 }
630}
631
632fn collection_type_to_u8(field_type: TType) -> u8 {
633 match field_type {
634 TType::Bool => 0x01,
635 f => type_to_u8(f),
636 }
637}
638
639fn type_to_u8(field_type: TType) -> u8 {
640 match field_type {
641 TType::Stop => 0x00,
642 TType::I08 => 0x03, // equivalent to TType::Byte
643 TType::I16 => 0x04,
644 TType::I32 => 0x05,
645 TType::I64 => 0x06,
646 TType::Double => 0x07,
647 TType::String => 0x08,
648 TType::List => 0x09,
649 TType::Set => 0x0A,
650 TType::Map => 0x0B,
651 TType::Struct => 0x0C,
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800652 TType::Uuid => 0x0D,
Allen George2b691ee2021-10-14 22:25:07 -0400653 _ => panic!("should not have attempted to convert {} to u8", field_type),
Allen George8b96bfb2016-11-02 08:01:08 -0400654 }
655}
656
Allen Georgeb0d14132020-03-29 11:48:55 -0400657fn collection_u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400658 match b {
Jörn Horstmann717bd792025-02-02 23:10:27 +0100659 // For historical and compatibility reasons, a reader should be capable to deal with both cases.
660 // The only valid value in the original spec was 2, but due to a widespread implementation bug
661 // the defacto standard across large parts of the library became 1 instead.
662 // As a result, both values are now allowed.
663 0x01 | 0x02 => Ok(TType::Bool),
Allen George8b96bfb2016-11-02 08:01:08 -0400664 o => u8_to_type(o),
665 }
666}
667
Allen Georgeb0d14132020-03-29 11:48:55 -0400668fn u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400669 match b {
670 0x00 => Ok(TType::Stop),
671 0x03 => Ok(TType::I08), // equivalent to TType::Byte
672 0x04 => Ok(TType::I16),
673 0x05 => Ok(TType::I32),
674 0x06 => Ok(TType::I64),
675 0x07 => Ok(TType::Double),
676 0x08 => Ok(TType::String),
677 0x09 => Ok(TType::List),
678 0x0A => Ok(TType::Set),
679 0x0B => Ok(TType::Map),
680 0x0C => Ok(TType::Struct),
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800681 0x0D => Ok(TType::Uuid),
Allen Georgeb0d14132020-03-29 11:48:55 -0400682 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
683 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500684 message: format!("cannot convert {} into TType", unkn),
685 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400686 }
687}
688
689#[cfg(test)]
690mod tests {
691
Allen Georgeb0d14132020-03-29 11:48:55 -0400692 use crate::protocol::{
Allen Georgeef7a1892018-12-16 18:01:37 -0500693 TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
694 TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
695 };
Allen Georgeb0d14132020-03-29 11:48:55 -0400696 use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400697
698 use super::*;
699
700 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500701 fn must_write_message_begin_largest_maximum_positive_sequence_number() {
702 let (_, mut o_prot) = test_objects();
703
704 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
705 "bar",
706 TMessageType::Reply,
707 i32::MAX
708 )));
709
710 #[rustfmt::skip]
711 let expected: [u8; 11] = [
712 0x82, /* protocol ID */
713 0x41, /* message type | protocol version */
714 0xFF,
715 0xFF,
716 0xFF,
717 0xFF,
718 0x07, /* non-zig-zag varint sequence number */
719 0x03, /* message-name length */
720 0x62,
721 0x61,
722 0x72 /* "bar" */,
723 ];
724
725 assert_eq_written_bytes!(o_prot, expected);
726 }
727
728 #[test]
729 fn must_read_message_begin_largest_maximum_positive_sequence_number() {
730 let (mut i_prot, _) = test_objects();
731
732 #[rustfmt::skip]
733 let source_bytes: [u8; 11] = [
734 0x82, /* protocol ID */
735 0x41, /* message type | protocol version */
736 0xFF,
737 0xFF,
738 0xFF,
739 0xFF,
740 0x07, /* non-zig-zag varint sequence number */
741 0x03, /* message-name length */
742 0x62,
743 0x61,
744 0x72 /* "bar" */,
745 ];
746
747 i_prot.transport.set_readable_bytes(&source_bytes);
748
749 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MAX);
750 let res = assert_success!(i_prot.read_message_begin());
751
752 assert_eq!(&expected, &res);
753 }
754
755 #[test]
756 fn must_write_message_begin_positive_sequence_number_0() {
Allen George0e22c362017-01-30 07:15:00 -0500757 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400758
Allen Georgeef7a1892018-12-16 18:01:37 -0500759 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
760 "foo",
761 TMessageType::Call,
762 431
763 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400764
Allen George7ddbcc02020-11-08 09:51:19 -0500765 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500766 let expected: [u8; 8] = [
767 0x82, /* protocol ID */
768 0x21, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500769 0xAF,
770 0x03, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500771 0x03, /* message-name length */
772 0x66,
773 0x6F,
774 0x6F /* "foo" */,
775 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400776
Allen George0e22c362017-01-30 07:15:00 -0500777 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400778 }
779
780 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500781 fn must_read_message_begin_positive_sequence_number_0() {
782 let (mut i_prot, _) = test_objects();
783
784 #[rustfmt::skip]
785 let source_bytes: [u8; 8] = [
786 0x82, /* protocol ID */
787 0x21, /* message type | protocol version */
788 0xAF,
789 0x03, /* non-zig-zag varint sequence number */
790 0x03, /* message-name length */
791 0x66,
792 0x6F,
793 0x6F /* "foo" */,
794 ];
795
796 i_prot.transport.set_readable_bytes(&source_bytes);
797
798 let expected = TMessageIdentifier::new("foo", TMessageType::Call, 431);
799 let res = assert_success!(i_prot.read_message_begin());
800
801 assert_eq!(&expected, &res);
802 }
803
804 #[test]
805 fn must_write_message_begin_positive_sequence_number_1() {
Allen George0e22c362017-01-30 07:15:00 -0500806 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400807
Allen Georgeef7a1892018-12-16 18:01:37 -0500808 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
809 "bar",
810 TMessageType::Reply,
Allen George7ddbcc02020-11-08 09:51:19 -0500811 991_828
Allen Georgeef7a1892018-12-16 18:01:37 -0500812 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400813
Allen George7ddbcc02020-11-08 09:51:19 -0500814 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500815 let expected: [u8; 9] = [
816 0x82, /* protocol ID */
817 0x41, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500818 0xD4,
819 0xC4,
820 0x3C, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500821 0x03, /* message-name length */
822 0x62,
823 0x61,
824 0x72 /* "bar" */,
825 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400826
Allen George0e22c362017-01-30 07:15:00 -0500827 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400828 }
829
830 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500831 fn must_read_message_begin_positive_sequence_number_1() {
832 let (mut i_prot, _) = test_objects();
833
834 #[rustfmt::skip]
835 let source_bytes: [u8; 9] = [
836 0x82, /* protocol ID */
837 0x41, /* message type | protocol version */
838 0xD4,
839 0xC4,
840 0x3C, /* non-zig-zag varint sequence number */
841 0x03, /* message-name length */
842 0x62,
843 0x61,
844 0x72 /* "bar" */,
845 ];
846
847 i_prot.transport.set_readable_bytes(&source_bytes);
848
849 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 991_828);
850 let res = assert_success!(i_prot.read_message_begin());
851
852 assert_eq!(&expected, &res);
853 }
854
855 #[test]
856 fn must_write_message_begin_zero_sequence_number() {
857 let (_, mut o_prot) = test_objects();
858
859 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
860 "bar",
861 TMessageType::Reply,
862 0
863 )));
864
865 #[rustfmt::skip]
866 let expected: [u8; 7] = [
867 0x82, /* protocol ID */
868 0x41, /* message type | protocol version */
869 0x00, /* non-zig-zag varint sequence number */
870 0x03, /* message-name length */
871 0x62,
872 0x61,
873 0x72 /* "bar" */,
874 ];
875
876 assert_eq_written_bytes!(o_prot, expected);
877 }
878
879 #[test]
880 fn must_read_message_begin_zero_sequence_number() {
881 let (mut i_prot, _) = test_objects();
882
883 #[rustfmt::skip]
884 let source_bytes: [u8; 7] = [
885 0x82, /* protocol ID */
886 0x41, /* message type | protocol version */
887 0x00, /* non-zig-zag varint sequence number */
888 0x03, /* message-name length */
889 0x62,
890 0x61,
891 0x72 /* "bar" */,
892 ];
893
894 i_prot.transport.set_readable_bytes(&source_bytes);
895
896 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 0);
897 let res = assert_success!(i_prot.read_message_begin());
898
899 assert_eq!(&expected, &res);
900 }
901
902 #[test]
903 fn must_write_message_begin_largest_minimum_negative_sequence_number() {
904 let (_, mut o_prot) = test_objects();
905
906 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
907 "bar",
908 TMessageType::Reply,
909 i32::MIN
910 )));
911
912 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
913 #[rustfmt::skip]
914 let expected: [u8; 11] = [
915 0x82, /* protocol ID */
916 0x41, /* message type | protocol version */
917 0x80,
918 0x80,
919 0x80,
920 0x80,
921 0x08, /* non-zig-zag varint sequence number */
922 0x03, /* message-name length */
923 0x62,
924 0x61,
925 0x72 /* "bar" */,
926 ];
927
928 assert_eq_written_bytes!(o_prot, expected);
929 }
930
931 #[test]
932 fn must_read_message_begin_largest_minimum_negative_sequence_number() {
933 let (mut i_prot, _) = test_objects();
934
935 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
936 #[rustfmt::skip]
937 let source_bytes: [u8; 11] = [
938 0x82, /* protocol ID */
939 0x41, /* message type | protocol version */
940 0x80,
941 0x80,
942 0x80,
943 0x80,
944 0x08, /* non-zig-zag varint sequence number */
945 0x03, /* message-name length */
946 0x62,
947 0x61,
948 0x72 /* "bar" */,
949 ];
950
951 i_prot.transport.set_readable_bytes(&source_bytes);
952
953 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MIN);
954 let res = assert_success!(i_prot.read_message_begin());
955
956 assert_eq!(&expected, &res);
957 }
958
959 #[test]
960 fn must_write_message_begin_negative_sequence_number_0() {
961 let (_, mut o_prot) = test_objects();
962
963 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
964 "foo",
965 TMessageType::Call,
966 -431
967 )));
968
969 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
970 #[rustfmt::skip]
971 let expected: [u8; 11] = [
972 0x82, /* protocol ID */
973 0x21, /* message type | protocol version */
974 0xD1,
975 0xFC,
976 0xFF,
977 0xFF,
978 0x0F, /* non-zig-zag varint sequence number */
979 0x03, /* message-name length */
980 0x66,
981 0x6F,
982 0x6F /* "foo" */,
983 ];
984
985 assert_eq_written_bytes!(o_prot, expected);
986 }
987
988 #[test]
989 fn must_read_message_begin_negative_sequence_number_0() {
990 let (mut i_prot, _) = test_objects();
991
992 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
993 #[rustfmt::skip]
994 let source_bytes: [u8; 11] = [
995 0x82, /* protocol ID */
996 0x21, /* message type | protocol version */
997 0xD1,
998 0xFC,
999 0xFF,
1000 0xFF,
1001 0x0F, /* non-zig-zag varint sequence number */
1002 0x03, /* message-name length */
1003 0x66,
1004 0x6F,
1005 0x6F /* "foo" */,
1006 ];
1007
1008 i_prot.transport.set_readable_bytes(&source_bytes);
1009
1010 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -431);
1011 let res = assert_success!(i_prot.read_message_begin());
1012
1013 assert_eq!(&expected, &res);
1014 }
1015
1016 #[test]
1017 fn must_write_message_begin_negative_sequence_number_1() {
1018 let (_, mut o_prot) = test_objects();
1019
1020 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1021 "foo",
1022 TMessageType::Call,
1023 -73_184_125
1024 )));
1025
1026 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1027 #[rustfmt::skip]
1028 let expected: [u8; 11] = [
1029 0x82, /* protocol ID */
1030 0x21, /* message type | protocol version */
1031 0x83,
1032 0x99,
1033 0x8D,
1034 0xDD,
1035 0x0F, /* non-zig-zag varint sequence number */
1036 0x03, /* message-name length */
1037 0x66,
1038 0x6F,
1039 0x6F /* "foo" */,
1040 ];
1041
1042 assert_eq_written_bytes!(o_prot, expected);
1043 }
1044
1045 #[test]
1046 fn must_read_message_begin_negative_sequence_number_1() {
1047 let (mut i_prot, _) = test_objects();
1048
1049 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1050 #[rustfmt::skip]
1051 let source_bytes: [u8; 11] = [
1052 0x82, /* protocol ID */
1053 0x21, /* message type | protocol version */
1054 0x83,
1055 0x99,
1056 0x8D,
1057 0xDD,
1058 0x0F, /* non-zig-zag varint sequence number */
1059 0x03, /* message-name length */
1060 0x66,
1061 0x6F,
1062 0x6F /* "foo" */,
1063 ];
1064
1065 i_prot.transport.set_readable_bytes(&source_bytes);
1066
1067 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -73_184_125);
1068 let res = assert_success!(i_prot.read_message_begin());
1069
1070 assert_eq!(&expected, &res);
1071 }
1072
1073 #[test]
1074 fn must_write_message_begin_negative_sequence_number_2() {
1075 let (_, mut o_prot) = test_objects();
1076
1077 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1078 "foo",
1079 TMessageType::Call,
1080 -1_073_741_823
1081 )));
1082
1083 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
1084 #[rustfmt::skip]
1085 let expected: [u8; 11] = [
1086 0x82, /* protocol ID */
1087 0x21, /* message type | protocol version */
1088 0x81,
1089 0x80,
1090 0x80,
1091 0x80,
1092 0x0C, /* non-zig-zag varint sequence number */
1093 0x03, /* message-name length */
1094 0x66,
1095 0x6F,
1096 0x6F /* "foo" */,
1097 ];
1098
1099 assert_eq_written_bytes!(o_prot, expected);
1100 }
1101
1102 #[test]
1103 fn must_read_message_begin_negative_sequence_number_2() {
1104 let (mut i_prot, _) = test_objects();
1105
1106 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
Allen George55c3e4c2021-03-01 23:19:52 -05001107 #[rustfmt::skip]
Allen George8a1743d2020-12-05 01:19:27 -05001108 let source_bytes: [u8; 11] = [
1109 0x82, /* protocol ID */
1110 0x21, /* message type | protocol version */
1111 0x81,
1112 0x80,
1113 0x80,
1114 0x80,
1115 0x0C, /* non-zig-zag varint sequence number */
1116 0x03, /* message-name length */
1117 0x66,
1118 0x6F,
Allen George55c3e4c2021-03-01 23:19:52 -05001119 0x6F, /* "foo" */
Allen George8a1743d2020-12-05 01:19:27 -05001120 ];
1121
1122 i_prot.transport.set_readable_bytes(&source_bytes);
1123
1124 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -1_073_741_823);
1125 let res = assert_success!(i_prot.read_message_begin());
1126
1127 assert_eq!(&expected, &res);
1128 }
1129
1130 #[test]
Nik Claytone7917602020-03-05 11:51:15 +01001131 fn must_round_trip_upto_i64_maxvalue() {
1132 // See https://issues.apache.org/jira/browse/THRIFT-5131
1133 for i in 0..64 {
1134 let (mut i_prot, mut o_prot) = test_objects();
1135 let val: i64 = ((1u64 << i) - 1) as i64;
1136
1137 o_prot
Allen George8a1743d2020-12-05 01:19:27 -05001138 .write_field_begin(&TFieldIdentifier::new("val", TType::I64, 1))
Nik Claytone7917602020-03-05 11:51:15 +01001139 .unwrap();
1140 o_prot.write_i64(val).unwrap();
1141 o_prot.write_field_end().unwrap();
1142 o_prot.flush().unwrap();
1143
1144 copy_write_buffer_to_read_buffer!(o_prot);
1145
1146 i_prot.read_field_begin().unwrap();
1147 assert_eq!(val, i_prot.read_i64().unwrap());
1148 }
1149 }
1150
1151 #[test]
Allen George8b96bfb2016-11-02 08:01:08 -04001152 fn must_round_trip_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -05001153 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001154
Allen George7ddbcc02020-11-08 09:51:19 -05001155 let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948);
Allen George8b96bfb2016-11-02 08:01:08 -04001156
1157 assert_success!(o_prot.write_message_begin(&ident));
1158
Allen George0e22c362017-01-30 07:15:00 -05001159 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001160
1161 let res = assert_success!(i_prot.read_message_begin());
1162 assert_eq!(&res, &ident);
1163 }
1164
1165 #[test]
1166 fn must_write_message_end() {
1167 assert_no_write(|o| o.write_message_end());
1168 }
1169
1170 // NOTE: structs and fields are tested together
1171 //
1172
1173 #[test]
1174 fn must_write_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001175 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001176
1177 // no bytes should be written however
1178 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1179
1180 // write three fields with tiny field ids
1181 // since they're small the field ids will be encoded as deltas
1182
1183 // since this is the first field (and it's zero) it gets the full varint write
1184 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
1185 assert_success!(o_prot.write_field_end());
1186
1187 // since this delta > 0 and < 15 it can be encoded as a delta
1188 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
1189 assert_success!(o_prot.write_field_end());
1190
1191 // since this delta > 0 and < 15 it can be encoded as a delta
1192 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
1193 assert_success!(o_prot.write_field_end());
1194
1195 // now, finish the struct off
1196 assert_success!(o_prot.write_field_stop());
1197 assert_success!(o_prot.write_struct_end());
1198
Allen George7ddbcc02020-11-08 09:51:19 -05001199 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001200 let expected: [u8; 5] = [
1201 0x03, /* field type */
1202 0x00, /* first field id */
1203 0x44, /* field delta (4) | field type */
1204 0x59, /* field delta (5) | field type */
1205 0x00 /* field stop */,
1206 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001207
Allen George0e22c362017-01-30 07:15:00 -05001208 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001209 }
1210
1211 #[test]
1212 fn must_round_trip_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001213 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001214
1215 // no bytes should be written however
1216 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1217
1218 // write three fields with tiny field ids
1219 // since they're small the field ids will be encoded as deltas
1220
1221 // since this is the first field (and it's zero) it gets the full varint write
1222 let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
1223 assert_success!(o_prot.write_field_begin(&field_ident_1));
1224 assert_success!(o_prot.write_field_end());
1225
1226 // since this delta > 0 and < 15 it can be encoded as a delta
1227 let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
1228 assert_success!(o_prot.write_field_begin(&field_ident_2));
1229 assert_success!(o_prot.write_field_end());
1230
1231 // since this delta > 0 and < 15 it can be encoded as a delta
1232 let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
1233 assert_success!(o_prot.write_field_begin(&field_ident_3));
1234 assert_success!(o_prot.write_field_end());
1235
1236 // now, finish the struct off
1237 assert_success!(o_prot.write_field_stop());
1238 assert_success!(o_prot.write_struct_end());
1239
Allen George0e22c362017-01-30 07:15:00 -05001240 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001241
1242 // read the struct back
1243 assert_success!(i_prot.read_struct_begin());
1244
1245 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001246 assert_eq!(
1247 read_ident_1,
1248 TFieldIdentifier {
1249 name: None,
1250 ..field_ident_1
1251 }
1252 );
Allen George8b96bfb2016-11-02 08:01:08 -04001253 assert_success!(i_prot.read_field_end());
1254
1255 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001256 assert_eq!(
1257 read_ident_2,
1258 TFieldIdentifier {
1259 name: None,
1260 ..field_ident_2
1261 }
1262 );
Allen George8b96bfb2016-11-02 08:01:08 -04001263 assert_success!(i_prot.read_field_end());
1264
1265 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001266 assert_eq!(
1267 read_ident_3,
1268 TFieldIdentifier {
1269 name: None,
1270 ..field_ident_3
1271 }
1272 );
Allen George8b96bfb2016-11-02 08:01:08 -04001273 assert_success!(i_prot.read_field_end());
1274
1275 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001276 assert_eq!(
1277 read_ident_4,
1278 TFieldIdentifier {
1279 name: None,
1280 field_type: TType::Stop,
1281 id: None,
1282 }
1283 );
Allen George8b96bfb2016-11-02 08:01:08 -04001284
1285 assert_success!(i_prot.read_struct_end());
1286 }
1287
1288 #[test]
1289 fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001290 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001291
1292 // no bytes should be written however
1293 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1294
1295 // write three fields with tiny field ids
1296 // since they're small the field ids will be encoded as deltas
1297
1298 // gets a delta write
1299 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
1300 assert_success!(o_prot.write_field_end());
1301
1302 // since this delta > 0 and < 15 it can be encoded as a delta
1303 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
1304 assert_success!(o_prot.write_field_end());
1305
1306 // since this delta > 0 and < 15 it can be encoded as a delta
1307 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
1308 assert_success!(o_prot.write_field_end());
1309
1310 // now, finish the struct off
1311 assert_success!(o_prot.write_field_stop());
1312 assert_success!(o_prot.write_struct_end());
1313
Allen George7ddbcc02020-11-08 09:51:19 -05001314 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001315 let expected: [u8; 4] = [
1316 0x15, /* field delta (1) | field type */
1317 0x1A, /* field delta (1) | field type */
1318 0x48, /* field delta (4) | field type */
1319 0x00 /* field stop */,
1320 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001321
Allen George0e22c362017-01-30 07:15:00 -05001322 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001323 }
1324
1325 #[test]
1326 fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001327 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001328
1329 // no bytes should be written however
1330 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1331
1332 // write three fields with tiny field ids
1333 // since they're small the field ids will be encoded as deltas
1334
1335 // gets a delta write
1336 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
1337 assert_success!(o_prot.write_field_begin(&field_ident_1));
1338 assert_success!(o_prot.write_field_end());
1339
1340 // since this delta > 0 and < 15 it can be encoded as a delta
1341 let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
1342 assert_success!(o_prot.write_field_begin(&field_ident_2));
1343 assert_success!(o_prot.write_field_end());
1344
1345 // since this delta > 0 and < 15 it can be encoded as a delta
1346 let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
1347 assert_success!(o_prot.write_field_begin(&field_ident_3));
1348 assert_success!(o_prot.write_field_end());
1349
1350 // now, finish the struct off
1351 assert_success!(o_prot.write_field_stop());
1352 assert_success!(o_prot.write_struct_end());
1353
Allen George0e22c362017-01-30 07:15:00 -05001354 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001355
1356 // read the struct back
1357 assert_success!(i_prot.read_struct_begin());
1358
1359 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001360 assert_eq!(
1361 read_ident_1,
1362 TFieldIdentifier {
1363 name: None,
1364 ..field_ident_1
1365 }
1366 );
Allen George8b96bfb2016-11-02 08:01:08 -04001367 assert_success!(i_prot.read_field_end());
1368
1369 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001370 assert_eq!(
1371 read_ident_2,
1372 TFieldIdentifier {
1373 name: None,
1374 ..field_ident_2
1375 }
1376 );
Allen George8b96bfb2016-11-02 08:01:08 -04001377 assert_success!(i_prot.read_field_end());
1378
1379 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001380 assert_eq!(
1381 read_ident_3,
1382 TFieldIdentifier {
1383 name: None,
1384 ..field_ident_3
1385 }
1386 );
Allen George8b96bfb2016-11-02 08:01:08 -04001387 assert_success!(i_prot.read_field_end());
1388
1389 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001390 assert_eq!(
1391 read_ident_4,
1392 TFieldIdentifier {
1393 name: None,
1394 field_type: TType::Stop,
1395 id: None,
1396 }
1397 );
Allen George8b96bfb2016-11-02 08:01:08 -04001398
1399 assert_success!(i_prot.read_struct_end());
1400 }
1401
1402 #[test]
1403 fn must_write_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001404 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001405
1406 // no bytes should be written however
1407 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1408
1409 // write three fields with field ids that cannot be encoded as deltas
1410
1411 // since this is the first field (and it's zero) it gets the full varint write
1412 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
1413 assert_success!(o_prot.write_field_end());
1414
1415 // since this delta is > 15 it is encoded as a zig-zag varint
1416 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
1417 assert_success!(o_prot.write_field_end());
1418
1419 // since this delta is > 15 it is encoded as a zig-zag varint
1420 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
1421 assert_success!(o_prot.write_field_end());
1422
1423 // now, finish the struct off
1424 assert_success!(o_prot.write_field_stop());
1425 assert_success!(o_prot.write_struct_end());
1426
Allen George7ddbcc02020-11-08 09:51:19 -05001427 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001428 let expected: [u8; 8] = [
1429 0x05, /* field type */
1430 0x00, /* first field id */
1431 0x06, /* field type */
1432 0x20, /* zig-zag varint field id */
1433 0x0A, /* field type */
1434 0xC6,
1435 0x01, /* zig-zag varint field id */
1436 0x00 /* field stop */,
1437 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001438
Allen George0e22c362017-01-30 07:15:00 -05001439 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001440 }
1441
1442 #[test]
1443 fn must_round_trip_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001444 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001445
1446 // no bytes should be written however
1447 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1448
1449 // write three fields with field ids that cannot be encoded as deltas
1450
1451 // since this is the first field (and it's zero) it gets the full varint write
1452 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
1453 assert_success!(o_prot.write_field_begin(&field_ident_1));
1454 assert_success!(o_prot.write_field_end());
1455
1456 // since this delta is > 15 it is encoded as a zig-zag varint
1457 let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
1458 assert_success!(o_prot.write_field_begin(&field_ident_2));
1459 assert_success!(o_prot.write_field_end());
1460
1461 // since this delta is > 15 it is encoded as a zig-zag varint
1462 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
1463 assert_success!(o_prot.write_field_begin(&field_ident_3));
1464 assert_success!(o_prot.write_field_end());
1465
1466 // now, finish the struct off
1467 assert_success!(o_prot.write_field_stop());
1468 assert_success!(o_prot.write_struct_end());
1469
Allen George0e22c362017-01-30 07:15:00 -05001470 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001471
1472 // read the struct back
1473 assert_success!(i_prot.read_struct_begin());
1474
1475 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001476 assert_eq!(
1477 read_ident_1,
1478 TFieldIdentifier {
1479 name: None,
1480 ..field_ident_1
1481 }
1482 );
Allen George8b96bfb2016-11-02 08:01:08 -04001483 assert_success!(i_prot.read_field_end());
1484
1485 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001486 assert_eq!(
1487 read_ident_2,
1488 TFieldIdentifier {
1489 name: None,
1490 ..field_ident_2
1491 }
1492 );
Allen George8b96bfb2016-11-02 08:01:08 -04001493 assert_success!(i_prot.read_field_end());
1494
1495 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001496 assert_eq!(
1497 read_ident_3,
1498 TFieldIdentifier {
1499 name: None,
1500 ..field_ident_3
1501 }
1502 );
Allen George8b96bfb2016-11-02 08:01:08 -04001503 assert_success!(i_prot.read_field_end());
1504
1505 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001506 assert_eq!(
1507 read_ident_4,
1508 TFieldIdentifier {
1509 name: None,
1510 field_type: TType::Stop,
1511 id: None,
1512 }
1513 );
Allen George8b96bfb2016-11-02 08:01:08 -04001514
1515 assert_success!(i_prot.read_struct_end());
1516 }
1517
1518 #[test]
1519 fn must_write_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001520 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001521
1522 // no bytes should be written however
1523 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1524
1525 // write three fields with field ids that cannot be encoded as deltas
1526
1527 // since the delta is > 0 and < 15 it gets a delta write
1528 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1529 assert_success!(o_prot.write_field_end());
1530
1531 // since this delta > 0 and < 15 it gets a delta write
1532 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1533 assert_success!(o_prot.write_field_end());
1534
1535 // since this delta is > 15 it is encoded as a zig-zag varint
1536 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
1537 assert_success!(o_prot.write_field_end());
1538
1539 // since this delta is > 15 it is encoded as a zig-zag varint
1540 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
1541 assert_success!(o_prot.write_field_end());
1542
1543 // since this is only 3 up from the previous it is recorded as a delta
1544 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
1545 assert_success!(o_prot.write_field_end());
1546
1547 // now, finish the struct off
1548 assert_success!(o_prot.write_field_stop());
1549 assert_success!(o_prot.write_struct_end());
1550
Allen George7ddbcc02020-11-08 09:51:19 -05001551 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001552 let expected: [u8; 10] = [
1553 0x16, /* field delta (1) | field type */
1554 0x85, /* field delta (8) | field type */
1555 0x0A, /* field type */
1556 0xD0,
1557 0x0F, /* zig-zag varint field id */
1558 0x0A, /* field type */
1559 0xA2,
1560 0x1F, /* zig-zag varint field id */
1561 0x3A, /* field delta (3) | field type */
1562 0x00 /* field stop */,
1563 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001564
Allen George0e22c362017-01-30 07:15:00 -05001565 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001566 }
1567
Allen George7ddbcc02020-11-08 09:51:19 -05001568 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001569 #[test]
1570 fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001571 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001572
1573 // no bytes should be written however
1574 let struct_ident = TStructIdentifier::new("foo");
1575 assert_success!(o_prot.write_struct_begin(&struct_ident));
1576
1577 // write three fields with field ids that cannot be encoded as deltas
1578
1579 // since the delta is > 0 and < 15 it gets a delta write
1580 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1581 assert_success!(o_prot.write_field_begin(&field_ident_1));
1582 assert_success!(o_prot.write_field_end());
1583
1584 // since this delta > 0 and < 15 it gets a delta write
1585 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1586 assert_success!(o_prot.write_field_begin(&field_ident_2));
1587 assert_success!(o_prot.write_field_end());
1588
1589 // since this delta is > 15 it is encoded as a zig-zag varint
1590 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
1591 assert_success!(o_prot.write_field_begin(&field_ident_3));
1592 assert_success!(o_prot.write_field_end());
1593
1594 // since this delta is > 15 it is encoded as a zig-zag varint
1595 let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
1596 assert_success!(o_prot.write_field_begin(&field_ident_4));
1597 assert_success!(o_prot.write_field_end());
1598
1599 // since this is only 3 up from the previous it is recorded as a delta
1600 let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
1601 assert_success!(o_prot.write_field_begin(&field_ident_5));
1602 assert_success!(o_prot.write_field_end());
1603
1604 // now, finish the struct off
1605 assert_success!(o_prot.write_field_stop());
1606 assert_success!(o_prot.write_struct_end());
1607
Allen George0e22c362017-01-30 07:15:00 -05001608 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001609
1610 // read the struct back
1611 assert_success!(i_prot.read_struct_begin());
1612
1613 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001614 assert_eq!(
1615 read_ident_1,
1616 TFieldIdentifier {
1617 name: None,
1618 ..field_ident_1
1619 }
1620 );
Allen George8b96bfb2016-11-02 08:01:08 -04001621 assert_success!(i_prot.read_field_end());
1622
1623 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001624 assert_eq!(
1625 read_ident_2,
1626 TFieldIdentifier {
1627 name: None,
1628 ..field_ident_2
1629 }
1630 );
Allen George8b96bfb2016-11-02 08:01:08 -04001631 assert_success!(i_prot.read_field_end());
1632
1633 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001634 assert_eq!(
1635 read_ident_3,
1636 TFieldIdentifier {
1637 name: None,
1638 ..field_ident_3
1639 }
1640 );
Allen George8b96bfb2016-11-02 08:01:08 -04001641 assert_success!(i_prot.read_field_end());
1642
1643 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001644 assert_eq!(
1645 read_ident_4,
1646 TFieldIdentifier {
1647 name: None,
1648 ..field_ident_4
1649 }
1650 );
Allen George8b96bfb2016-11-02 08:01:08 -04001651 assert_success!(i_prot.read_field_end());
1652
1653 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001654 assert_eq!(
1655 read_ident_5,
1656 TFieldIdentifier {
1657 name: None,
1658 ..field_ident_5
1659 }
1660 );
Allen George8b96bfb2016-11-02 08:01:08 -04001661 assert_success!(i_prot.read_field_end());
1662
1663 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001664 assert_eq!(
1665 read_ident_6,
1666 TFieldIdentifier {
1667 name: None,
1668 field_type: TType::Stop,
1669 id: None,
1670 }
1671 );
Allen George8b96bfb2016-11-02 08:01:08 -04001672
1673 assert_success!(i_prot.read_struct_end());
1674 }
1675
1676 #[test]
1677 fn must_write_nested_structs_0() {
1678 // last field of the containing struct is a delta
1679 // first field of the the contained struct is a delta
1680
Allen George0e22c362017-01-30 07:15:00 -05001681 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001682
1683 // start containing struct
1684 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1685
1686 // containing struct
1687 // since the delta is > 0 and < 15 it gets a delta write
1688 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1689 assert_success!(o_prot.write_field_end());
1690
1691 // containing struct
1692 // since this delta > 0 and < 15 it gets a delta write
1693 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1694 assert_success!(o_prot.write_field_end());
1695
1696 // start contained struct
1697 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1698
1699 // contained struct
1700 // since the delta is > 0 and < 15 it gets a delta write
1701 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
1702 assert_success!(o_prot.write_field_end());
1703
1704 // contained struct
1705 // since this delta > 15 it gets a full write
1706 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1707 assert_success!(o_prot.write_field_end());
1708
1709 // end contained struct
1710 assert_success!(o_prot.write_field_stop());
1711 assert_success!(o_prot.write_struct_end());
1712
1713 // end containing struct
1714 assert_success!(o_prot.write_field_stop());
1715 assert_success!(o_prot.write_struct_end());
1716
Allen George7ddbcc02020-11-08 09:51:19 -05001717 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001718 let expected: [u8; 7] = [
1719 0x16, /* field delta (1) | field type */
1720 0x85, /* field delta (8) | field type */
1721 0x73, /* field delta (7) | field type */
1722 0x07, /* field type */
1723 0x30, /* zig-zag varint field id */
1724 0x00, /* field stop - contained */
1725 0x00 /* field stop - containing */,
1726 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001727
Allen George0e22c362017-01-30 07:15:00 -05001728 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001729 }
1730
Allen George7ddbcc02020-11-08 09:51:19 -05001731 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001732 #[test]
1733 fn must_round_trip_nested_structs_0() {
1734 // last field of the containing struct is a delta
1735 // first field of the the contained struct is a delta
1736
Allen George0e22c362017-01-30 07:15:00 -05001737 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001738
1739 // start containing struct
1740 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1741
1742 // containing struct
1743 // since the delta is > 0 and < 15 it gets a delta write
1744 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1745 assert_success!(o_prot.write_field_begin(&field_ident_1));
1746 assert_success!(o_prot.write_field_end());
1747
1748 // containing struct
1749 // since this delta > 0 and < 15 it gets a delta write
1750 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1751 assert_success!(o_prot.write_field_begin(&field_ident_2));
1752 assert_success!(o_prot.write_field_end());
1753
1754 // start contained struct
1755 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1756
1757 // contained struct
1758 // since the delta is > 0 and < 15 it gets a delta write
1759 let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
1760 assert_success!(o_prot.write_field_begin(&field_ident_3));
1761 assert_success!(o_prot.write_field_end());
1762
1763 // contained struct
1764 // since this delta > 15 it gets a full write
1765 let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
1766 assert_success!(o_prot.write_field_begin(&field_ident_4));
1767 assert_success!(o_prot.write_field_end());
1768
1769 // end contained struct
1770 assert_success!(o_prot.write_field_stop());
1771 assert_success!(o_prot.write_struct_end());
1772
1773 // end containing struct
1774 assert_success!(o_prot.write_field_stop());
1775 assert_success!(o_prot.write_struct_end());
1776
Allen George0e22c362017-01-30 07:15:00 -05001777 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001778
1779 // read containing struct back
1780 assert_success!(i_prot.read_struct_begin());
1781
1782 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001783 assert_eq!(
1784 read_ident_1,
1785 TFieldIdentifier {
1786 name: None,
1787 ..field_ident_1
1788 }
1789 );
Allen George8b96bfb2016-11-02 08:01:08 -04001790 assert_success!(i_prot.read_field_end());
1791
1792 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001793 assert_eq!(
1794 read_ident_2,
1795 TFieldIdentifier {
1796 name: None,
1797 ..field_ident_2
1798 }
1799 );
Allen George8b96bfb2016-11-02 08:01:08 -04001800 assert_success!(i_prot.read_field_end());
1801
1802 // read contained struct back
1803 assert_success!(i_prot.read_struct_begin());
1804
1805 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001806 assert_eq!(
1807 read_ident_3,
1808 TFieldIdentifier {
1809 name: None,
1810 ..field_ident_3
1811 }
1812 );
Allen George8b96bfb2016-11-02 08:01:08 -04001813 assert_success!(i_prot.read_field_end());
1814
1815 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001816 assert_eq!(
1817 read_ident_4,
1818 TFieldIdentifier {
1819 name: None,
1820 ..field_ident_4
1821 }
1822 );
Allen George8b96bfb2016-11-02 08:01:08 -04001823 assert_success!(i_prot.read_field_end());
1824
1825 // end contained struct
1826 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001827 assert_eq!(
1828 read_ident_6,
1829 TFieldIdentifier {
1830 name: None,
1831 field_type: TType::Stop,
1832 id: None,
1833 }
1834 );
Allen George8b96bfb2016-11-02 08:01:08 -04001835 assert_success!(i_prot.read_struct_end());
1836
1837 // end containing struct
1838 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001839 assert_eq!(
1840 read_ident_7,
1841 TFieldIdentifier {
1842 name: None,
1843 field_type: TType::Stop,
1844 id: None,
1845 }
1846 );
Allen George8b96bfb2016-11-02 08:01:08 -04001847 assert_success!(i_prot.read_struct_end());
1848 }
1849
1850 #[test]
1851 fn must_write_nested_structs_1() {
1852 // last field of the containing struct is a delta
1853 // first field of the the contained struct is a full write
1854
Allen George0e22c362017-01-30 07:15:00 -05001855 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001856
1857 // start containing struct
1858 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1859
1860 // containing struct
1861 // since the delta is > 0 and < 15 it gets a delta write
1862 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1863 assert_success!(o_prot.write_field_end());
1864
1865 // containing struct
1866 // since this delta > 0 and < 15 it gets a delta write
1867 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1868 assert_success!(o_prot.write_field_end());
1869
1870 // start contained struct
1871 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1872
1873 // contained struct
1874 // since this delta > 15 it gets a full write
1875 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1876 assert_success!(o_prot.write_field_end());
1877
1878 // contained struct
1879 // since the delta is > 0 and < 15 it gets a delta write
1880 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1881 assert_success!(o_prot.write_field_end());
1882
1883 // end contained struct
1884 assert_success!(o_prot.write_field_stop());
1885 assert_success!(o_prot.write_struct_end());
1886
1887 // end containing struct
1888 assert_success!(o_prot.write_field_stop());
1889 assert_success!(o_prot.write_struct_end());
1890
Allen George7ddbcc02020-11-08 09:51:19 -05001891 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001892 let expected: [u8; 7] = [
1893 0x16, /* field delta (1) | field type */
1894 0x85, /* field delta (8) | field type */
1895 0x07, /* field type */
1896 0x30, /* zig-zag varint field id */
1897 0x33, /* field delta (3) | field type */
1898 0x00, /* field stop - contained */
1899 0x00 /* field stop - containing */,
1900 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001901
Allen George0e22c362017-01-30 07:15:00 -05001902 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001903 }
1904
Allen George7ddbcc02020-11-08 09:51:19 -05001905 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001906 #[test]
1907 fn must_round_trip_nested_structs_1() {
1908 // last field of the containing struct is a delta
1909 // first field of the the contained struct is a full write
1910
Allen George0e22c362017-01-30 07:15:00 -05001911 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001912
1913 // start containing struct
1914 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1915
1916 // containing struct
1917 // since the delta is > 0 and < 15 it gets a delta write
1918 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1919 assert_success!(o_prot.write_field_begin(&field_ident_1));
1920 assert_success!(o_prot.write_field_end());
1921
1922 // containing struct
1923 // since this delta > 0 and < 15 it gets a delta write
1924 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1925 assert_success!(o_prot.write_field_begin(&field_ident_2));
1926 assert_success!(o_prot.write_field_end());
1927
1928 // start contained struct
1929 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1930
1931 // contained struct
1932 // since this delta > 15 it gets a full write
1933 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
1934 assert_success!(o_prot.write_field_begin(&field_ident_3));
1935 assert_success!(o_prot.write_field_end());
1936
1937 // contained struct
1938 // since the delta is > 0 and < 15 it gets a delta write
1939 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
1940 assert_success!(o_prot.write_field_begin(&field_ident_4));
1941 assert_success!(o_prot.write_field_end());
1942
1943 // end contained struct
1944 assert_success!(o_prot.write_field_stop());
1945 assert_success!(o_prot.write_struct_end());
1946
1947 // end containing struct
1948 assert_success!(o_prot.write_field_stop());
1949 assert_success!(o_prot.write_struct_end());
1950
Allen George0e22c362017-01-30 07:15:00 -05001951 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001952
1953 // read containing struct back
1954 assert_success!(i_prot.read_struct_begin());
1955
1956 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001957 assert_eq!(
1958 read_ident_1,
1959 TFieldIdentifier {
1960 name: None,
1961 ..field_ident_1
1962 }
1963 );
Allen George8b96bfb2016-11-02 08:01:08 -04001964 assert_success!(i_prot.read_field_end());
1965
1966 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001967 assert_eq!(
1968 read_ident_2,
1969 TFieldIdentifier {
1970 name: None,
1971 ..field_ident_2
1972 }
1973 );
Allen George8b96bfb2016-11-02 08:01:08 -04001974 assert_success!(i_prot.read_field_end());
1975
1976 // read contained struct back
1977 assert_success!(i_prot.read_struct_begin());
1978
1979 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001980 assert_eq!(
1981 read_ident_3,
1982 TFieldIdentifier {
1983 name: None,
1984 ..field_ident_3
1985 }
1986 );
Allen George8b96bfb2016-11-02 08:01:08 -04001987 assert_success!(i_prot.read_field_end());
1988
1989 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001990 assert_eq!(
1991 read_ident_4,
1992 TFieldIdentifier {
1993 name: None,
1994 ..field_ident_4
1995 }
1996 );
Allen George8b96bfb2016-11-02 08:01:08 -04001997 assert_success!(i_prot.read_field_end());
1998
1999 // end contained struct
2000 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002001 assert_eq!(
2002 read_ident_6,
2003 TFieldIdentifier {
2004 name: None,
2005 field_type: TType::Stop,
2006 id: None,
2007 }
2008 );
Allen George8b96bfb2016-11-02 08:01:08 -04002009 assert_success!(i_prot.read_struct_end());
2010
2011 // end containing struct
2012 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002013 assert_eq!(
2014 read_ident_7,
2015 TFieldIdentifier {
2016 name: None,
2017 field_type: TType::Stop,
2018 id: None,
2019 }
2020 );
Allen George8b96bfb2016-11-02 08:01:08 -04002021 assert_success!(i_prot.read_struct_end());
2022 }
2023
2024 #[test]
2025 fn must_write_nested_structs_2() {
2026 // last field of the containing struct is a full write
2027 // first field of the the contained struct is a delta write
2028
Allen George0e22c362017-01-30 07:15:00 -05002029 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002030
2031 // start containing struct
2032 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2033
2034 // containing struct
2035 // since the delta is > 0 and < 15 it gets a delta write
2036 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2037 assert_success!(o_prot.write_field_end());
2038
2039 // containing struct
2040 // since this delta > 15 it gets a full write
2041 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2042 assert_success!(o_prot.write_field_end());
2043
2044 // start contained struct
2045 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2046
2047 // contained struct
2048 // since this delta > 0 and < 15 it gets a delta write
2049 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
2050 assert_success!(o_prot.write_field_end());
2051
2052 // contained struct
2053 // since the delta is > 0 and < 15 it gets a delta write
2054 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
2055 assert_success!(o_prot.write_field_end());
2056
2057 // end contained struct
2058 assert_success!(o_prot.write_field_stop());
2059 assert_success!(o_prot.write_struct_end());
2060
2061 // end containing struct
2062 assert_success!(o_prot.write_field_stop());
2063 assert_success!(o_prot.write_struct_end());
2064
Allen George7ddbcc02020-11-08 09:51:19 -05002065 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002066 let expected: [u8; 7] = [
2067 0x16, /* field delta (1) | field type */
2068 0x08, /* field type */
2069 0x2A, /* zig-zag varint field id */
2070 0x77, /* field delta(7) | field type */
2071 0x33, /* field delta (3) | field type */
2072 0x00, /* field stop - contained */
2073 0x00 /* field stop - containing */,
2074 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002075
Allen George0e22c362017-01-30 07:15:00 -05002076 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002077 }
2078
Allen George7ddbcc02020-11-08 09:51:19 -05002079 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002080 #[test]
2081 fn must_round_trip_nested_structs_2() {
Allen George0e22c362017-01-30 07:15:00 -05002082 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002083
2084 // start containing struct
2085 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2086
2087 // containing struct
2088 // since the delta is > 0 and < 15 it gets a delta write
2089 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2090 assert_success!(o_prot.write_field_begin(&field_ident_1));
2091 assert_success!(o_prot.write_field_end());
2092
2093 // containing struct
2094 // since this delta > 15 it gets a full write
2095 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2096 assert_success!(o_prot.write_field_begin(&field_ident_2));
2097 assert_success!(o_prot.write_field_end());
2098
2099 // start contained struct
2100 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2101
2102 // contained struct
2103 // since this delta > 0 and < 15 it gets a delta write
2104 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
2105 assert_success!(o_prot.write_field_begin(&field_ident_3));
2106 assert_success!(o_prot.write_field_end());
2107
2108 // contained struct
2109 // since the delta is > 0 and < 15 it gets a delta write
2110 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
2111 assert_success!(o_prot.write_field_begin(&field_ident_4));
2112 assert_success!(o_prot.write_field_end());
2113
2114 // end contained struct
2115 assert_success!(o_prot.write_field_stop());
2116 assert_success!(o_prot.write_struct_end());
2117
2118 // end containing struct
2119 assert_success!(o_prot.write_field_stop());
2120 assert_success!(o_prot.write_struct_end());
2121
Allen George0e22c362017-01-30 07:15:00 -05002122 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002123
2124 // read containing struct back
2125 assert_success!(i_prot.read_struct_begin());
2126
2127 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002128 assert_eq!(
2129 read_ident_1,
2130 TFieldIdentifier {
2131 name: None,
2132 ..field_ident_1
2133 }
2134 );
Allen George8b96bfb2016-11-02 08:01:08 -04002135 assert_success!(i_prot.read_field_end());
2136
2137 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002138 assert_eq!(
2139 read_ident_2,
2140 TFieldIdentifier {
2141 name: None,
2142 ..field_ident_2
2143 }
2144 );
Allen George8b96bfb2016-11-02 08:01:08 -04002145 assert_success!(i_prot.read_field_end());
2146
2147 // read contained struct back
2148 assert_success!(i_prot.read_struct_begin());
2149
2150 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002151 assert_eq!(
2152 read_ident_3,
2153 TFieldIdentifier {
2154 name: None,
2155 ..field_ident_3
2156 }
2157 );
Allen George8b96bfb2016-11-02 08:01:08 -04002158 assert_success!(i_prot.read_field_end());
2159
2160 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002161 assert_eq!(
2162 read_ident_4,
2163 TFieldIdentifier {
2164 name: None,
2165 ..field_ident_4
2166 }
2167 );
Allen George8b96bfb2016-11-02 08:01:08 -04002168 assert_success!(i_prot.read_field_end());
2169
2170 // end contained struct
2171 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002172 assert_eq!(
2173 read_ident_6,
2174 TFieldIdentifier {
2175 name: None,
2176 field_type: TType::Stop,
2177 id: None,
2178 }
2179 );
Allen George8b96bfb2016-11-02 08:01:08 -04002180 assert_success!(i_prot.read_struct_end());
2181
2182 // end containing struct
2183 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002184 assert_eq!(
2185 read_ident_7,
2186 TFieldIdentifier {
2187 name: None,
2188 field_type: TType::Stop,
2189 id: None,
2190 }
2191 );
Allen George8b96bfb2016-11-02 08:01:08 -04002192 assert_success!(i_prot.read_struct_end());
2193 }
2194
2195 #[test]
2196 fn must_write_nested_structs_3() {
2197 // last field of the containing struct is a full write
2198 // first field of the the contained struct is a full write
2199
Allen George0e22c362017-01-30 07:15:00 -05002200 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002201
2202 // start containing struct
2203 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2204
2205 // containing struct
2206 // since the delta is > 0 and < 15 it gets a delta write
2207 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2208 assert_success!(o_prot.write_field_end());
2209
2210 // containing struct
2211 // since this delta > 15 it gets a full write
2212 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2213 assert_success!(o_prot.write_field_end());
2214
2215 // start contained struct
2216 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2217
2218 // contained struct
2219 // since this delta > 15 it gets a full write
2220 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
2221 assert_success!(o_prot.write_field_end());
2222
2223 // contained struct
2224 // since the delta is > 0 and < 15 it gets a delta write
2225 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
2226 assert_success!(o_prot.write_field_end());
2227
2228 // end contained struct
2229 assert_success!(o_prot.write_field_stop());
2230 assert_success!(o_prot.write_struct_end());
2231
2232 // end containing struct
2233 assert_success!(o_prot.write_field_stop());
2234 assert_success!(o_prot.write_struct_end());
2235
Allen George7ddbcc02020-11-08 09:51:19 -05002236 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002237 let expected: [u8; 8] = [
2238 0x16, /* field delta (1) | field type */
2239 0x08, /* field type */
2240 0x2A, /* zig-zag varint field id */
2241 0x07, /* field type */
2242 0x2A, /* zig-zag varint field id */
2243 0x63, /* field delta (6) | field type */
2244 0x00, /* field stop - contained */
2245 0x00 /* field stop - containing */,
2246 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002247
Allen George0e22c362017-01-30 07:15:00 -05002248 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002249 }
2250
Allen George7ddbcc02020-11-08 09:51:19 -05002251 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002252 #[test]
2253 fn must_round_trip_nested_structs_3() {
2254 // last field of the containing struct is a full write
2255 // first field of the the contained struct is a full write
2256
Allen George0e22c362017-01-30 07:15:00 -05002257 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002258
2259 // start containing struct
2260 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2261
2262 // containing struct
2263 // since the delta is > 0 and < 15 it gets a delta write
2264 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2265 assert_success!(o_prot.write_field_begin(&field_ident_1));
2266 assert_success!(o_prot.write_field_end());
2267
2268 // containing struct
2269 // since this delta > 15 it gets a full write
2270 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2271 assert_success!(o_prot.write_field_begin(&field_ident_2));
2272 assert_success!(o_prot.write_field_end());
2273
2274 // start contained struct
2275 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2276
2277 // contained struct
2278 // since this delta > 15 it gets a full write
2279 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
2280 assert_success!(o_prot.write_field_begin(&field_ident_3));
2281 assert_success!(o_prot.write_field_end());
2282
2283 // contained struct
2284 // since the delta is > 0 and < 15 it gets a delta write
2285 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2286 assert_success!(o_prot.write_field_begin(&field_ident_4));
2287 assert_success!(o_prot.write_field_end());
2288
2289 // end contained struct
2290 assert_success!(o_prot.write_field_stop());
2291 assert_success!(o_prot.write_struct_end());
2292
2293 // end containing struct
2294 assert_success!(o_prot.write_field_stop());
2295 assert_success!(o_prot.write_struct_end());
2296
Allen George0e22c362017-01-30 07:15:00 -05002297 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002298
2299 // read containing struct back
2300 assert_success!(i_prot.read_struct_begin());
2301
2302 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002303 assert_eq!(
2304 read_ident_1,
2305 TFieldIdentifier {
2306 name: None,
2307 ..field_ident_1
2308 }
2309 );
Allen George8b96bfb2016-11-02 08:01:08 -04002310 assert_success!(i_prot.read_field_end());
2311
2312 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002313 assert_eq!(
2314 read_ident_2,
2315 TFieldIdentifier {
2316 name: None,
2317 ..field_ident_2
2318 }
2319 );
Allen George8b96bfb2016-11-02 08:01:08 -04002320 assert_success!(i_prot.read_field_end());
2321
2322 // read contained struct back
2323 assert_success!(i_prot.read_struct_begin());
2324
2325 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002326 assert_eq!(
2327 read_ident_3,
2328 TFieldIdentifier {
2329 name: None,
2330 ..field_ident_3
2331 }
2332 );
Allen George8b96bfb2016-11-02 08:01:08 -04002333 assert_success!(i_prot.read_field_end());
2334
2335 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002336 assert_eq!(
2337 read_ident_4,
2338 TFieldIdentifier {
2339 name: None,
2340 ..field_ident_4
2341 }
2342 );
Allen George8b96bfb2016-11-02 08:01:08 -04002343 assert_success!(i_prot.read_field_end());
2344
2345 // end contained struct
2346 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002347 assert_eq!(
2348 read_ident_6,
2349 TFieldIdentifier {
2350 name: None,
2351 field_type: TType::Stop,
2352 id: None,
2353 }
2354 );
Allen George8b96bfb2016-11-02 08:01:08 -04002355 assert_success!(i_prot.read_struct_end());
2356
2357 // end containing struct
2358 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002359 assert_eq!(
2360 read_ident_7,
2361 TFieldIdentifier {
2362 name: None,
2363 field_type: TType::Stop,
2364 id: None,
2365 }
2366 );
Allen George8b96bfb2016-11-02 08:01:08 -04002367 assert_success!(i_prot.read_struct_end());
2368 }
2369
2370 #[test]
2371 fn must_write_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002372 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002373
2374 // no bytes should be written however
2375 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2376
2377 // write three fields with field ids that cannot be encoded as deltas
2378
2379 // since the delta is > 0 and < 16 it gets a delta write
2380 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2381 assert_success!(o_prot.write_bool(true));
2382 assert_success!(o_prot.write_field_end());
2383
2384 // since this delta > 0 and < 15 it gets a delta write
2385 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
2386 assert_success!(o_prot.write_bool(false));
2387 assert_success!(o_prot.write_field_end());
2388
2389 // since this delta > 15 it gets a full write
2390 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
2391 assert_success!(o_prot.write_bool(true));
2392 assert_success!(o_prot.write_field_end());
2393
2394 // since this delta > 15 it gets a full write
2395 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
2396 assert_success!(o_prot.write_bool(false));
2397 assert_success!(o_prot.write_field_end());
2398
2399 // now, finish the struct off
2400 assert_success!(o_prot.write_field_stop());
2401 assert_success!(o_prot.write_struct_end());
2402
Allen George7ddbcc02020-11-08 09:51:19 -05002403 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002404 let expected: [u8; 7] = [
2405 0x11, /* field delta (1) | true */
2406 0x82, /* field delta (8) | false */
2407 0x01, /* true */
2408 0x34, /* field id */
2409 0x02, /* false */
2410 0x5A, /* field id */
2411 0x00 /* stop field */,
2412 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002413
Allen George0e22c362017-01-30 07:15:00 -05002414 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002415 }
2416
Allen George7ddbcc02020-11-08 09:51:19 -05002417 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002418 #[test]
2419 fn must_round_trip_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002420 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002421
2422 // no bytes should be written however
2423 let struct_ident = TStructIdentifier::new("foo");
2424 assert_success!(o_prot.write_struct_begin(&struct_ident));
2425
2426 // write two fields
2427
2428 // since the delta is > 0 and < 16 it gets a delta write
2429 let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
2430 assert_success!(o_prot.write_field_begin(&field_ident_1));
2431 assert_success!(o_prot.write_bool(true));
2432 assert_success!(o_prot.write_field_end());
2433
2434 // since this delta > 0 and < 15 it gets a delta write
2435 let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
2436 assert_success!(o_prot.write_field_begin(&field_ident_2));
2437 assert_success!(o_prot.write_bool(false));
2438 assert_success!(o_prot.write_field_end());
2439
2440 // since this delta > 15 it gets a full write
2441 let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
2442 assert_success!(o_prot.write_field_begin(&field_ident_3));
2443 assert_success!(o_prot.write_bool(true));
2444 assert_success!(o_prot.write_field_end());
2445
2446 // since this delta > 15 it gets a full write
2447 let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
2448 assert_success!(o_prot.write_field_begin(&field_ident_4));
2449 assert_success!(o_prot.write_bool(false));
2450 assert_success!(o_prot.write_field_end());
2451
2452 // now, finish the struct off
2453 assert_success!(o_prot.write_field_stop());
2454 assert_success!(o_prot.write_struct_end());
2455
Allen George0e22c362017-01-30 07:15:00 -05002456 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002457
2458 // read the struct back
2459 assert_success!(i_prot.read_struct_begin());
2460
2461 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002462 assert_eq!(
2463 read_ident_1,
2464 TFieldIdentifier {
2465 name: None,
2466 ..field_ident_1
2467 }
2468 );
Allen George8b96bfb2016-11-02 08:01:08 -04002469 let read_value_1 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002470 assert!(read_value_1);
Allen George8b96bfb2016-11-02 08:01:08 -04002471 assert_success!(i_prot.read_field_end());
2472
2473 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002474 assert_eq!(
2475 read_ident_2,
2476 TFieldIdentifier {
2477 name: None,
2478 ..field_ident_2
2479 }
2480 );
Allen George8b96bfb2016-11-02 08:01:08 -04002481 let read_value_2 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002482 assert!(!read_value_2);
Allen George8b96bfb2016-11-02 08:01:08 -04002483 assert_success!(i_prot.read_field_end());
2484
2485 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002486 assert_eq!(
2487 read_ident_3,
2488 TFieldIdentifier {
2489 name: None,
2490 ..field_ident_3
2491 }
2492 );
Allen George8b96bfb2016-11-02 08:01:08 -04002493 let read_value_3 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002494 assert!(read_value_3);
Allen George8b96bfb2016-11-02 08:01:08 -04002495 assert_success!(i_prot.read_field_end());
2496
2497 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002498 assert_eq!(
2499 read_ident_4,
2500 TFieldIdentifier {
2501 name: None,
2502 ..field_ident_4
2503 }
2504 );
Allen George8b96bfb2016-11-02 08:01:08 -04002505 let read_value_4 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002506 assert!(!read_value_4);
Allen George8b96bfb2016-11-02 08:01:08 -04002507 assert_success!(i_prot.read_field_end());
2508
2509 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002510 assert_eq!(
2511 read_ident_5,
2512 TFieldIdentifier {
2513 name: None,
2514 field_type: TType::Stop,
2515 id: None,
2516 }
2517 );
Allen George8b96bfb2016-11-02 08:01:08 -04002518
2519 assert_success!(i_prot.read_struct_end());
2520 }
2521
2522 #[test]
2523 #[should_panic]
2524 fn must_fail_if_write_field_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002525 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002526 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2527 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2528 o_prot.write_field_end().unwrap();
2529 }
2530
2531 #[test]
2532 #[should_panic]
2533 fn must_fail_if_write_stop_field_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002534 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002535 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2536 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2537 o_prot.write_field_stop().unwrap();
2538 }
2539
2540 #[test]
2541 #[should_panic]
2542 fn must_fail_if_write_struct_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002543 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002544 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2545 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2546 o_prot.write_struct_end().unwrap();
2547 }
2548
2549 #[test]
2550 #[should_panic]
2551 fn must_fail_if_write_struct_end_without_any_fields() {
Allen George0e22c362017-01-30 07:15:00 -05002552 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002553 o_prot.write_struct_end().unwrap();
2554 }
2555
2556 #[test]
2557 fn must_write_field_end() {
2558 assert_no_write(|o| o.write_field_end());
2559 }
2560
2561 #[test]
2562 fn must_write_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002563 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002564
2565 assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
2566
2567 let expected: [u8; 1] = [0x46 /* size | elem_type */];
2568
Allen George0e22c362017-01-30 07:15:00 -05002569 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002570 }
2571
2572 #[test]
2573 fn must_round_trip_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002574 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002575
2576 let ident = TListIdentifier::new(TType::I08, 10);
2577
2578 assert_success!(o_prot.write_list_begin(&ident));
2579
Allen George0e22c362017-01-30 07:15:00 -05002580 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002581
2582 let res = assert_success!(i_prot.read_list_begin());
2583 assert_eq!(&res, &ident);
2584 }
2585
2586 #[test]
2587 fn must_write_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002588 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002589
2590 let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
2591 assert!(res.is_ok());
2592
Allen George0e22c362017-01-30 07:15:00 -05002593 let expected: [u8; 3] = [
2594 0xF9, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002595 0x8F, 0x4E, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002596 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002597
Allen George0e22c362017-01-30 07:15:00 -05002598 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002599 }
2600
2601 #[test]
2602 fn must_round_trip_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002603 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002604
2605 let ident = TListIdentifier::new(TType::Set, 47381);
2606
2607 assert_success!(o_prot.write_list_begin(&ident));
2608
Allen George0e22c362017-01-30 07:15:00 -05002609 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002610
2611 let res = assert_success!(i_prot.read_list_begin());
2612 assert_eq!(&res, &ident);
2613 }
2614
2615 #[test]
2616 fn must_write_list_end() {
2617 assert_no_write(|o| o.write_list_end());
2618 }
2619
2620 #[test]
2621 fn must_write_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002622 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002623
2624 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
2625
2626 let expected: [u8; 1] = [0x2C /* size | elem_type */];
2627
Allen George0e22c362017-01-30 07:15:00 -05002628 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002629 }
2630
2631 #[test]
2632 fn must_round_trip_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002633 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002634
2635 let ident = TSetIdentifier::new(TType::I16, 7);
2636
2637 assert_success!(o_prot.write_set_begin(&ident));
2638
Allen George0e22c362017-01-30 07:15:00 -05002639 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002640
2641 let res = assert_success!(i_prot.read_set_begin());
2642 assert_eq!(&res, &ident);
2643 }
2644
2645 #[test]
2646 fn must_write_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002647 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002648
2649 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
2650
Allen George0e22c362017-01-30 07:15:00 -05002651 let expected: [u8; 4] = [
2652 0xF7, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002653 0xD3, 0xBA, 0x01, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002654 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002655
Allen George0e22c362017-01-30 07:15:00 -05002656 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002657 }
2658
2659 #[test]
2660 fn must_round_trip_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002661 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002662
Allen George7ddbcc02020-11-08 09:51:19 -05002663 let ident = TSetIdentifier::new(TType::Map, 3_928_429);
Allen George8b96bfb2016-11-02 08:01:08 -04002664
2665 assert_success!(o_prot.write_set_begin(&ident));
2666
Allen George0e22c362017-01-30 07:15:00 -05002667 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002668
2669 let res = assert_success!(i_prot.read_set_begin());
2670 assert_eq!(&res, &ident);
2671 }
2672
2673 #[test]
2674 fn must_write_set_end() {
2675 assert_no_write(|o| o.write_set_end());
2676 }
2677
2678 #[test]
2679 fn must_write_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002680 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002681
2682 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
2683
2684 let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything
2685
Allen George0e22c362017-01-30 07:15:00 -05002686 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002687 }
2688
2689 #[test]
2690 fn must_read_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002691 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002692
2693 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
2694
Allen George0e22c362017-01-30 07:15:00 -05002695 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002696
2697 let res = assert_success!(i_prot.read_map_begin());
Allen George0e22c362017-01-30 07:15:00 -05002698 assert_eq!(
2699 &res,
2700 &TMapIdentifier {
Allen Georgeef7a1892018-12-16 18:01:37 -05002701 key_type: None,
2702 value_type: None,
2703 size: 0,
2704 }
Allen George0e22c362017-01-30 07:15:00 -05002705 );
Allen George8b96bfb2016-11-02 08:01:08 -04002706 }
2707
2708 #[test]
2709 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002710 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002711
Allen Georgeef7a1892018-12-16 18:01:37 -05002712 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
2713 TType::Double,
2714 TType::String,
2715 238
2716 )));
Allen George8b96bfb2016-11-02 08:01:08 -04002717
Allen George0e22c362017-01-30 07:15:00 -05002718 let expected: [u8; 3] = [
Allen Georgeef7a1892018-12-16 18:01:37 -05002719 0xEE, 0x01, /* size as varint */
2720 0x78, /* key type | val type */
Allen George0e22c362017-01-30 07:15:00 -05002721 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002722
Allen George0e22c362017-01-30 07:15:00 -05002723 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002724 }
2725
2726 #[test]
2727 fn must_round_trip_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002728 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002729
Allen George7ddbcc02020-11-08 09:51:19 -05002730 let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349);
Allen George8b96bfb2016-11-02 08:01:08 -04002731
2732 assert_success!(o_prot.write_map_begin(&ident));
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_map_begin());
2737 assert_eq!(&res, &ident);
2738 }
2739
2740 #[test]
2741 fn must_write_map_end() {
2742 assert_no_write(|o| o.write_map_end());
2743 }
2744
2745 #[test]
2746 fn must_write_map_with_bool_key_and_value() {
Allen George0e22c362017-01-30 07:15:00 -05002747 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002748
2749 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
2750 assert_success!(o_prot.write_bool(true));
2751 assert_success!(o_prot.write_bool(false));
2752 assert_success!(o_prot.write_map_end());
2753
Allen George0e22c362017-01-30 07:15:00 -05002754 let expected: [u8; 4] = [
2755 0x01, /* size as varint */
2756 0x11, /* key type | val type */
2757 0x01, /* key: true */
Allen Georgeef7a1892018-12-16 18:01:37 -05002758 0x02, /* val: false */
Allen George0e22c362017-01-30 07:15:00 -05002759 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002760
Allen George0e22c362017-01-30 07:15:00 -05002761 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002762 }
2763
2764 #[test]
2765 fn must_round_trip_map_with_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002766 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002767
2768 let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
2769 assert_success!(o_prot.write_map_begin(&map_ident));
2770 assert_success!(o_prot.write_bool(true));
2771 assert_success!(o_prot.write_bool(false));
2772 assert_success!(o_prot.write_bool(false));
2773 assert_success!(o_prot.write_bool(true));
2774 assert_success!(o_prot.write_map_end());
2775
Allen George0e22c362017-01-30 07:15:00 -05002776 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002777
2778 // map header
2779 let rcvd_ident = assert_success!(i_prot.read_map_begin());
2780 assert_eq!(&rcvd_ident, &map_ident);
2781 // key 1
2782 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002783 assert!(b);
Allen George8b96bfb2016-11-02 08:01:08 -04002784 // val 1
2785 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002786 assert!(!b);
Allen George8b96bfb2016-11-02 08:01:08 -04002787 // key 2
2788 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002789 assert!(!b);
Allen George8b96bfb2016-11-02 08:01:08 -04002790 // val 2
2791 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002792 assert!(b);
Allen George8b96bfb2016-11-02 08:01:08 -04002793 // map end
2794 assert_success!(i_prot.read_map_end());
2795 }
2796
2797 #[test]
2798 fn must_read_map_end() {
Allen George0e22c362017-01-30 07:15:00 -05002799 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002800 assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
2801 }
2802
Allen Georgeef7a1892018-12-16 18:01:37 -05002803 fn test_objects() -> (
2804 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2805 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2806 ) {
Allen George0e22c362017-01-30 07:15:00 -05002807 let mem = TBufferChannel::with_capacity(80, 80);
Allen George8b96bfb2016-11-02 08:01:08 -04002808
Allen George0e22c362017-01-30 07:15:00 -05002809 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -04002810
Allen George0e22c362017-01-30 07:15:00 -05002811 let i_prot = TCompactInputProtocol::new(r_mem);
2812 let o_prot = TCompactOutputProtocol::new(w_mem);
Allen George8b96bfb2016-11-02 08:01:08 -04002813
Allen George0e22c362017-01-30 07:15:00 -05002814 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -04002815 }
2816
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002817 #[test]
2818 fn must_read_write_double() {
2819 let (mut i_prot, mut o_prot) = test_objects();
2820
Allen George7ddbcc02020-11-08 09:51:19 -05002821 #[allow(clippy::approx_constant)]
2822 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002823 o_prot.write_double(double).unwrap();
2824 copy_write_buffer_to_read_buffer!(o_prot);
2825
Allen George7ddbcc02020-11-08 09:51:19 -05002826 let read_double = i_prot.read_double().unwrap();
Cameron Martinda54fc82025-01-12 08:55:45 +00002827 assert!((read_double - double).abs() < f64::EPSILON);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002828 }
2829
2830 #[test]
2831 fn must_encode_double_as_other_langs() {
2832 let (_, mut o_prot) = test_objects();
2833 let expected = [24, 45, 68, 84, 251, 33, 9, 64];
2834
Allen George7ddbcc02020-11-08 09:51:19 -05002835 #[allow(clippy::approx_constant)]
2836 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002837 o_prot.write_double(double).unwrap();
2838
2839 assert_eq_written_bytes!(o_prot, expected);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002840 }
2841
Allen George0e22c362017-01-30 07:15:00 -05002842 fn assert_no_write<F>(mut write_fn: F)
2843 where
Allen Georgeb0d14132020-03-29 11:48:55 -04002844 F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> crate::Result<()>,
Allen George0e22c362017-01-30 07:15:00 -05002845 {
2846 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002847 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -05002848 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -04002849 }
Jörn Horstmann717bd792025-02-02 23:10:27 +01002850
2851 #[test]
2852 fn must_read_boolean_list() {
2853 let (mut i_prot, _) = test_objects();
2854
2855 let source_bytes: [u8; 3] = [0x21, 2, 1];
2856
2857 i_prot.transport.set_readable_bytes(&source_bytes);
2858
2859 let (ttype, element_count) = assert_success!(i_prot.read_list_set_begin());
2860
2861 assert_eq!(ttype, TType::Bool);
2862 assert_eq!(element_count, 2);
2863 assert_eq!(i_prot.read_bool().unwrap(), false);
2864 assert_eq!(i_prot.read_bool().unwrap(), true);
2865
2866 assert_success!(i_prot.read_list_end());
2867 }
2868
2869 #[test]
2870 fn must_read_boolean_list_alternative_encoding() {
2871 let (mut i_prot, _) = test_objects();
2872
2873 let source_bytes: [u8; 3] = [0x22, 0, 1];
2874
2875 i_prot.transport.set_readable_bytes(&source_bytes);
2876
2877 let (ttype, element_count) = assert_success!(i_prot.read_list_set_begin());
2878
2879 assert_eq!(ttype, TType::Bool);
2880 assert_eq!(element_count, 2);
2881 assert_eq!(i_prot.read_bool().unwrap(), false);
2882 assert_eq!(i_prot.read_bool().unwrap(), true);
2883
2884 assert_success!(i_prot.read_list_end());
2885 }
Allen George8b96bfb2016-11-02 08:01:08 -04002886}