blob: 8ed4e0635e4431339653a517ca24e53c2373f991 [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 {
213 0x01 => Ok(true),
214 0x02 => Ok(false),
Allen Georgeb0d14132020-03-29 11:48:55 -0400215 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
216 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500217 message: format!("cannot convert {} into bool", unkn),
218 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400219 }
220 }
221 }
222 }
223
Allen Georgeb0d14132020-03-29 11:48:55 -0400224 fn read_bytes(&mut self) -> crate::Result<Vec<u8>> {
Allen George0e22c362017-01-30 07:15:00 -0500225 let len = self.transport.read_varint::<u32>()?;
Allen George8b96bfb2016-11-02 08:01:08 -0400226 let mut buf = vec![0u8; len as usize];
Allen George0e22c362017-01-30 07:15:00 -0500227 self.transport
228 .read_exact(&mut buf)
229 .map_err(From::from)
230 .map(|_| buf)
Allen George8b96bfb2016-11-02 08:01:08 -0400231 }
232
Allen Georgeb0d14132020-03-29 11:48:55 -0400233 fn read_i8(&mut self) -> crate::Result<i8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400234 self.read_byte().map(|i| i as i8)
235 }
236
Allen Georgeb0d14132020-03-29 11:48:55 -0400237 fn read_i16(&mut self) -> crate::Result<i16> {
Allen George0e22c362017-01-30 07:15:00 -0500238 self.transport.read_varint::<i16>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400239 }
240
Allen Georgeb0d14132020-03-29 11:48:55 -0400241 fn read_i32(&mut self) -> crate::Result<i32> {
Allen George0e22c362017-01-30 07:15:00 -0500242 self.transport.read_varint::<i32>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400243 }
244
Allen Georgeb0d14132020-03-29 11:48:55 -0400245 fn read_i64(&mut self) -> crate::Result<i64> {
Allen George0e22c362017-01-30 07:15:00 -0500246 self.transport.read_varint::<i64>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400247 }
248
Allen Georgeb0d14132020-03-29 11:48:55 -0400249 fn read_double(&mut self) -> crate::Result<f64> {
Allen George8a1743d2020-12-05 01:19:27 -0500250 self.transport
251 .read_f64::<LittleEndian>()
252 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400253 }
254
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800255 fn read_uuid(&mut self) -> crate::Result<uuid::Uuid> {
256 uuid::Uuid::from_slice(&self.read_bytes()?).map_err(From::from)
257 }
258
Allen Georgeb0d14132020-03-29 11:48:55 -0400259 fn read_string(&mut self) -> crate::Result<String> {
Allen George8b96bfb2016-11-02 08:01:08 -0400260 let bytes = self.read_bytes()?;
261 String::from_utf8(bytes).map_err(From::from)
262 }
263
Allen Georgeb0d14132020-03-29 11:48:55 -0400264 fn read_list_begin(&mut self) -> crate::Result<TListIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400265 let (element_type, element_count) = self.read_list_set_begin()?;
266 Ok(TListIdentifier::new(element_type, element_count))
267 }
268
Allen Georgeb0d14132020-03-29 11:48:55 -0400269 fn read_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400270 Ok(())
271 }
272
Allen Georgeb0d14132020-03-29 11:48:55 -0400273 fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400274 let (element_type, element_count) = self.read_list_set_begin()?;
275 Ok(TSetIdentifier::new(element_type, element_count))
276 }
277
Allen Georgeb0d14132020-03-29 11:48:55 -0400278 fn read_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400279 Ok(())
280 }
281
Allen Georgeb0d14132020-03-29 11:48:55 -0400282 fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier> {
Allen George0e22c362017-01-30 07:15:00 -0500283 let element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400284 if element_count == 0 {
285 Ok(TMapIdentifier::new(None, None, 0))
286 } else {
287 let type_header = self.read_byte()?;
288 let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
289 let val_type = collection_u8_to_type(type_header & 0x0F)?;
290 Ok(TMapIdentifier::new(key_type, val_type, element_count))
291 }
292 }
293
Allen Georgeb0d14132020-03-29 11:48:55 -0400294 fn read_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400295 Ok(())
296 }
297
298 // utility
299 //
300
Allen Georgeb0d14132020-03-29 11:48:55 -0400301 fn read_byte(&mut self) -> crate::Result<u8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400302 let mut buf = [0u8; 1];
Allen George0e22c362017-01-30 07:15:00 -0500303 self.transport
304 .read_exact(&mut buf)
305 .map_err(From::from)
306 .map(|_| buf[0])
Allen George8b96bfb2016-11-02 08:01:08 -0400307 }
308}
309
Vadim Chekand3355af2018-01-05 23:12:47 -0500310impl<T> io::Seek for TCompactInputProtocol<T>
311where
312 T: io::Seek + TReadTransport,
313{
314 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
315 self.transport.seek(pos)
316 }
317}
318
Allen George8b96bfb2016-11-02 08:01:08 -0400319/// Factory for creating instances of `TCompactInputProtocol`.
320#[derive(Default)]
321pub struct TCompactInputProtocolFactory;
322
323impl TCompactInputProtocolFactory {
324 /// Create a `TCompactInputProtocolFactory`.
325 pub fn new() -> TCompactInputProtocolFactory {
326 TCompactInputProtocolFactory {}
327 }
328}
329
330impl TInputProtocolFactory for TCompactInputProtocolFactory {
Danny Browning77d96c12019-08-21 13:41:07 -0600331 fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500332 Box::new(TCompactInputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400333 }
334}
335
336/// Write messages using the Thrift compact protocol.
337///
338/// # Examples
339///
340/// Create and use a `TCompactOutputProtocol`.
341///
342/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -0400343/// use thrift::protocol::{TCompactOutputProtocol, TOutputProtocol};
Allen George0e22c362017-01-30 07:15:00 -0500344/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -0400345///
Allen George0e22c362017-01-30 07:15:00 -0500346/// let mut channel = TTcpChannel::new();
347/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400348///
Allen George0e22c362017-01-30 07:15:00 -0500349/// let mut protocol = TCompactOutputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -0400350///
Allen George0e22c362017-01-30 07:15:00 -0500351/// protocol.write_bool(true).unwrap();
352/// protocol.write_string("test_string").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400353/// ```
Allen George0e22c362017-01-30 07:15:00 -0500354#[derive(Debug)]
355pub struct TCompactOutputProtocol<T>
356where
357 T: TWriteTransport,
358{
Allen George8b96bfb2016-11-02 08:01:08 -0400359 // Identifier of the last field serialized for a struct.
360 last_write_field_id: i16,
Allen George0e22c362017-01-30 07:15:00 -0500361 // Stack of the last written field ids (new entry added each time a nested struct is written).
Allen George8b96bfb2016-11-02 08:01:08 -0400362 write_field_id_stack: Vec<i16>,
363 // Field identifier of the boolean field to be written.
364 // Saved because boolean fields and their value are encoded in a single byte
365 pending_write_bool_field_identifier: Option<TFieldIdentifier>,
366 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -0500367 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -0400368}
369
Allen George0e22c362017-01-30 07:15:00 -0500370impl<T> TCompactOutputProtocol<T>
371where
372 T: TWriteTransport,
373{
Allen George8b96bfb2016-11-02 08:01:08 -0400374 /// Create a `TCompactOutputProtocol` that writes bytes to `transport`.
Allen George0e22c362017-01-30 07:15:00 -0500375 pub fn new(transport: T) -> TCompactOutputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -0400376 TCompactOutputProtocol {
377 last_write_field_id: 0,
378 write_field_id_stack: Vec::new(),
379 pending_write_bool_field_identifier: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500380 transport,
Allen George8b96bfb2016-11-02 08:01:08 -0400381 }
382 }
383
384 // FIXME: field_type as unconstrained u8 is bad
Allen Georgeb0d14132020-03-29 11:48:55 -0400385 fn write_field_header(&mut self, field_type: u8, field_id: i16) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400386 let field_delta = field_id - self.last_write_field_id;
387 if field_delta > 0 && field_delta < 15 {
388 self.write_byte(((field_delta as u8) << 4) | field_type)?;
389 } else {
390 self.write_byte(field_type)?;
391 self.write_i16(field_id)?;
392 }
393 self.last_write_field_id = field_id;
394 Ok(())
395 }
396
Allen George8a1743d2020-12-05 01:19:27 -0500397 fn write_list_set_begin(
398 &mut self,
399 element_type: TType,
400 element_count: i32,
401 ) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400402 let elem_identifier = collection_type_to_u8(element_type);
403 if element_count <= 14 {
404 let header = (element_count as u8) << 4 | elem_identifier;
405 self.write_byte(header)
406 } else {
407 let header = 0xF0 | elem_identifier;
408 self.write_byte(header)?;
Allen George48905102021-02-20 08:47:01 -0500409 // element count is strictly positive as per the spec, so
410 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George8b96bfb2016-11-02 08:01:08 -0400411 self.transport
Allen George8b96bfb2016-11-02 08:01:08 -0400412 .write_varint(element_count as u32)
413 .map_err(From::from)
414 .map(|_| ())
415 }
416 }
417
418 fn assert_no_pending_bool_write(&self) {
419 if let Some(ref f) = self.pending_write_bool_field_identifier {
420 panic!("pending bool field {:?} not written", f)
421 }
422 }
423}
424
Allen George0e22c362017-01-30 07:15:00 -0500425impl<T> TOutputProtocol for TCompactOutputProtocol<T>
426where
427 T: TWriteTransport,
428{
Allen Georgeb0d14132020-03-29 11:48:55 -0400429 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400430 self.write_byte(COMPACT_PROTOCOL_ID)?;
431 self.write_byte((u8::from(identifier.message_type) << 5) | COMPACT_VERSION)?;
Allen George48905102021-02-20 08:47:01 -0500432 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George55c3e4c2021-03-01 23:19:52 -0500433 self.transport
434 .write_varint(identifier.sequence_number as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400435 self.write_string(&identifier.name)?;
436 Ok(())
437 }
438
Allen Georgeb0d14132020-03-29 11:48:55 -0400439 fn write_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400440 self.assert_no_pending_bool_write();
441 Ok(())
442 }
443
Allen Georgeb0d14132020-03-29 11:48:55 -0400444 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400445 self.write_field_id_stack.push(self.last_write_field_id);
446 self.last_write_field_id = 0;
447 Ok(())
448 }
449
Allen Georgeb0d14132020-03-29 11:48:55 -0400450 fn write_struct_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400451 self.assert_no_pending_bool_write();
Allen Georgeef7a1892018-12-16 18:01:37 -0500452 self.last_write_field_id = self
453 .write_field_id_stack
Allen George0e22c362017-01-30 07:15:00 -0500454 .pop()
455 .expect("should have previous field ids");
Allen George8b96bfb2016-11-02 08:01:08 -0400456 Ok(())
457 }
458
Allen Georgeb0d14132020-03-29 11:48:55 -0400459 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400460 match identifier.field_type {
461 TType::Bool => {
462 if self.pending_write_bool_field_identifier.is_some() {
Allen George0e22c362017-01-30 07:15:00 -0500463 panic!(
464 "should not have a pending bool while writing another bool with id: \
Allen Georgeef7a1892018-12-16 18:01:37 -0500465 {:?}",
Allen George0e22c362017-01-30 07:15:00 -0500466 identifier
467 )
Allen George8b96bfb2016-11-02 08:01:08 -0400468 }
469 self.pending_write_bool_field_identifier = Some(identifier.clone());
470 Ok(())
471 }
472 _ => {
473 let field_type = type_to_u8(identifier.field_type);
Allen Georgeef7a1892018-12-16 18:01:37 -0500474 let field_id = identifier.id.expect("non-stop field should have field id");
Allen George8b96bfb2016-11-02 08:01:08 -0400475 self.write_field_header(field_type, field_id)
476 }
477 }
478 }
479
Allen Georgeb0d14132020-03-29 11:48:55 -0400480 fn write_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400481 self.assert_no_pending_bool_write();
482 Ok(())
483 }
484
Allen Georgeb0d14132020-03-29 11:48:55 -0400485 fn write_field_stop(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400486 self.assert_no_pending_bool_write();
487 self.write_byte(type_to_u8(TType::Stop))
488 }
489
Allen Georgeb0d14132020-03-29 11:48:55 -0400490 fn write_bool(&mut self, b: bool) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400491 match self.pending_write_bool_field_identifier.take() {
492 Some(pending) => {
493 let field_id = pending.id.expect("bool field should have a field id");
494 let field_type_as_u8 = if b { 0x01 } else { 0x02 };
495 self.write_field_header(field_type_as_u8, field_id)
496 }
497 None => {
498 if b {
499 self.write_byte(0x01)
500 } else {
501 self.write_byte(0x02)
502 }
503 }
504 }
505 }
506
Allen Georgeb0d14132020-03-29 11:48:55 -0400507 fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> {
Allen George48905102021-02-20 08:47:01 -0500508 // length is strictly positive as per the spec, so
509 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500510 self.transport.write_varint(b.len() as u32)?;
511 self.transport.write_all(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400512 }
513
Allen Georgeb0d14132020-03-29 11:48:55 -0400514 fn write_i8(&mut self, i: i8) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400515 self.write_byte(i as u8)
516 }
517
Allen Georgeb0d14132020-03-29 11:48:55 -0400518 fn write_i16(&mut self, i: i16) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500519 self.transport
Allen George48905102021-02-20 08:47:01 -0500520 .write_varint(i)
Allen George0e22c362017-01-30 07:15:00 -0500521 .map_err(From::from)
522 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400523 }
524
Allen Georgeb0d14132020-03-29 11:48:55 -0400525 fn write_i32(&mut self, i: i32) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500526 self.transport
527 .write_varint(i)
528 .map_err(From::from)
529 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400530 }
531
Allen Georgeb0d14132020-03-29 11:48:55 -0400532 fn write_i64(&mut self, i: i64) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500533 self.transport
534 .write_varint(i)
535 .map_err(From::from)
536 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400537 }
538
Allen Georgeb0d14132020-03-29 11:48:55 -0400539 fn write_double(&mut self, d: f64) -> crate::Result<()> {
Allen George8a1743d2020-12-05 01:19:27 -0500540 self.transport
541 .write_f64::<LittleEndian>(d)
542 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400543 }
544
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800545 fn write_uuid(&mut self, uuid: &uuid::Uuid) -> crate::Result<()> {
546 self.write_bytes(uuid.as_bytes())
547 }
548
Allen Georgeb0d14132020-03-29 11:48:55 -0400549 fn write_string(&mut self, s: &str) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400550 self.write_bytes(s.as_bytes())
551 }
552
Allen Georgeb0d14132020-03-29 11:48:55 -0400553 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400554 self.write_list_set_begin(identifier.element_type, identifier.size)
555 }
556
Allen Georgeb0d14132020-03-29 11:48:55 -0400557 fn write_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400558 Ok(())
559 }
560
Allen Georgeb0d14132020-03-29 11:48:55 -0400561 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400562 self.write_list_set_begin(identifier.element_type, identifier.size)
563 }
564
Allen Georgeb0d14132020-03-29 11:48:55 -0400565 fn write_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400566 Ok(())
567 }
568
Allen Georgeb0d14132020-03-29 11:48:55 -0400569 fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400570 if identifier.size == 0 {
571 self.write_byte(0)
572 } else {
Allen George48905102021-02-20 08:47:01 -0500573 // element count is strictly positive as per the spec, so
574 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500575 self.transport.write_varint(identifier.size as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400576
Allen George0e22c362017-01-30 07:15:00 -0500577 let key_type = identifier
578 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400579 .expect("map identifier to write should contain key type");
580 let key_type_byte = collection_type_to_u8(key_type) << 4;
581
Allen George0e22c362017-01-30 07:15:00 -0500582 let val_type = identifier
583 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400584 .expect("map identifier to write should contain value type");
585 let val_type_byte = collection_type_to_u8(val_type);
586
587 let map_type_header = key_type_byte | val_type_byte;
588 self.write_byte(map_type_header)
589 }
590 }
591
Allen Georgeb0d14132020-03-29 11:48:55 -0400592 fn write_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400593 Ok(())
594 }
595
Allen Georgeb0d14132020-03-29 11:48:55 -0400596 fn flush(&mut self) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500597 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400598 }
599
600 // utility
601 //
602
Allen Georgeb0d14132020-03-29 11:48:55 -0400603 fn write_byte(&mut self, b: u8) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500604 self.transport.write(&[b]).map_err(From::from).map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400605 }
606}
607
608/// Factory for creating instances of `TCompactOutputProtocol`.
609#[derive(Default)]
610pub struct TCompactOutputProtocolFactory;
611
612impl TCompactOutputProtocolFactory {
613 /// Create a `TCompactOutputProtocolFactory`.
614 pub fn new() -> TCompactOutputProtocolFactory {
615 TCompactOutputProtocolFactory {}
616 }
617}
618
619impl TOutputProtocolFactory for TCompactOutputProtocolFactory {
Allen George8a1743d2020-12-05 01:19:27 -0500620 fn create(
621 &self,
622 transport: Box<dyn TWriteTransport + Send>,
623 ) -> Box<dyn TOutputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500624 Box::new(TCompactOutputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400625 }
626}
627
628fn collection_type_to_u8(field_type: TType) -> u8 {
629 match field_type {
630 TType::Bool => 0x01,
631 f => type_to_u8(f),
632 }
633}
634
635fn type_to_u8(field_type: TType) -> u8 {
636 match field_type {
637 TType::Stop => 0x00,
638 TType::I08 => 0x03, // equivalent to TType::Byte
639 TType::I16 => 0x04,
640 TType::I32 => 0x05,
641 TType::I64 => 0x06,
642 TType::Double => 0x07,
643 TType::String => 0x08,
644 TType::List => 0x09,
645 TType::Set => 0x0A,
646 TType::Map => 0x0B,
647 TType::Struct => 0x0C,
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800648 TType::Uuid => 0x0D,
Allen George2b691ee2021-10-14 22:25:07 -0400649 _ => panic!("should not have attempted to convert {} to u8", field_type),
Allen George8b96bfb2016-11-02 08:01:08 -0400650 }
651}
652
Allen Georgeb0d14132020-03-29 11:48:55 -0400653fn collection_u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400654 match b {
655 0x01 => Ok(TType::Bool),
656 o => u8_to_type(o),
657 }
658}
659
Allen Georgeb0d14132020-03-29 11:48:55 -0400660fn u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400661 match b {
662 0x00 => Ok(TType::Stop),
663 0x03 => Ok(TType::I08), // equivalent to TType::Byte
664 0x04 => Ok(TType::I16),
665 0x05 => Ok(TType::I32),
666 0x06 => Ok(TType::I64),
667 0x07 => Ok(TType::Double),
668 0x08 => Ok(TType::String),
669 0x09 => Ok(TType::List),
670 0x0A => Ok(TType::Set),
671 0x0B => Ok(TType::Map),
672 0x0C => Ok(TType::Struct),
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800673 0x0D => Ok(TType::Uuid),
Allen Georgeb0d14132020-03-29 11:48:55 -0400674 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
675 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500676 message: format!("cannot convert {} into TType", unkn),
677 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400678 }
679}
680
681#[cfg(test)]
682mod tests {
683
Allen Georgeb0d14132020-03-29 11:48:55 -0400684 use crate::protocol::{
Allen Georgeef7a1892018-12-16 18:01:37 -0500685 TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
686 TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
687 };
Allen Georgeb0d14132020-03-29 11:48:55 -0400688 use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400689
690 use super::*;
691
692 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500693 fn must_write_message_begin_largest_maximum_positive_sequence_number() {
694 let (_, mut o_prot) = test_objects();
695
696 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
697 "bar",
698 TMessageType::Reply,
699 i32::MAX
700 )));
701
702 #[rustfmt::skip]
703 let expected: [u8; 11] = [
704 0x82, /* protocol ID */
705 0x41, /* message type | protocol version */
706 0xFF,
707 0xFF,
708 0xFF,
709 0xFF,
710 0x07, /* non-zig-zag varint sequence number */
711 0x03, /* message-name length */
712 0x62,
713 0x61,
714 0x72 /* "bar" */,
715 ];
716
717 assert_eq_written_bytes!(o_prot, expected);
718 }
719
720 #[test]
721 fn must_read_message_begin_largest_maximum_positive_sequence_number() {
722 let (mut i_prot, _) = test_objects();
723
724 #[rustfmt::skip]
725 let source_bytes: [u8; 11] = [
726 0x82, /* protocol ID */
727 0x41, /* message type | protocol version */
728 0xFF,
729 0xFF,
730 0xFF,
731 0xFF,
732 0x07, /* non-zig-zag varint sequence number */
733 0x03, /* message-name length */
734 0x62,
735 0x61,
736 0x72 /* "bar" */,
737 ];
738
739 i_prot.transport.set_readable_bytes(&source_bytes);
740
741 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MAX);
742 let res = assert_success!(i_prot.read_message_begin());
743
744 assert_eq!(&expected, &res);
745 }
746
747 #[test]
748 fn must_write_message_begin_positive_sequence_number_0() {
Allen George0e22c362017-01-30 07:15:00 -0500749 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400750
Allen Georgeef7a1892018-12-16 18:01:37 -0500751 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
752 "foo",
753 TMessageType::Call,
754 431
755 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400756
Allen George7ddbcc02020-11-08 09:51:19 -0500757 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500758 let expected: [u8; 8] = [
759 0x82, /* protocol ID */
760 0x21, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500761 0xAF,
762 0x03, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500763 0x03, /* message-name length */
764 0x66,
765 0x6F,
766 0x6F /* "foo" */,
767 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400768
Allen George0e22c362017-01-30 07:15:00 -0500769 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400770 }
771
772 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500773 fn must_read_message_begin_positive_sequence_number_0() {
774 let (mut i_prot, _) = test_objects();
775
776 #[rustfmt::skip]
777 let source_bytes: [u8; 8] = [
778 0x82, /* protocol ID */
779 0x21, /* message type | protocol version */
780 0xAF,
781 0x03, /* non-zig-zag varint sequence number */
782 0x03, /* message-name length */
783 0x66,
784 0x6F,
785 0x6F /* "foo" */,
786 ];
787
788 i_prot.transport.set_readable_bytes(&source_bytes);
789
790 let expected = TMessageIdentifier::new("foo", TMessageType::Call, 431);
791 let res = assert_success!(i_prot.read_message_begin());
792
793 assert_eq!(&expected, &res);
794 }
795
796 #[test]
797 fn must_write_message_begin_positive_sequence_number_1() {
Allen George0e22c362017-01-30 07:15:00 -0500798 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400799
Allen Georgeef7a1892018-12-16 18:01:37 -0500800 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
801 "bar",
802 TMessageType::Reply,
Allen George7ddbcc02020-11-08 09:51:19 -0500803 991_828
Allen Georgeef7a1892018-12-16 18:01:37 -0500804 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400805
Allen George7ddbcc02020-11-08 09:51:19 -0500806 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500807 let expected: [u8; 9] = [
808 0x82, /* protocol ID */
809 0x41, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500810 0xD4,
811 0xC4,
812 0x3C, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500813 0x03, /* message-name length */
814 0x62,
815 0x61,
816 0x72 /* "bar" */,
817 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400818
Allen George0e22c362017-01-30 07:15:00 -0500819 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400820 }
821
822 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500823 fn must_read_message_begin_positive_sequence_number_1() {
824 let (mut i_prot, _) = test_objects();
825
826 #[rustfmt::skip]
827 let source_bytes: [u8; 9] = [
828 0x82, /* protocol ID */
829 0x41, /* message type | protocol version */
830 0xD4,
831 0xC4,
832 0x3C, /* non-zig-zag varint sequence number */
833 0x03, /* message-name length */
834 0x62,
835 0x61,
836 0x72 /* "bar" */,
837 ];
838
839 i_prot.transport.set_readable_bytes(&source_bytes);
840
841 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 991_828);
842 let res = assert_success!(i_prot.read_message_begin());
843
844 assert_eq!(&expected, &res);
845 }
846
847 #[test]
848 fn must_write_message_begin_zero_sequence_number() {
849 let (_, mut o_prot) = test_objects();
850
851 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
852 "bar",
853 TMessageType::Reply,
854 0
855 )));
856
857 #[rustfmt::skip]
858 let expected: [u8; 7] = [
859 0x82, /* protocol ID */
860 0x41, /* message type | protocol version */
861 0x00, /* non-zig-zag varint sequence number */
862 0x03, /* message-name length */
863 0x62,
864 0x61,
865 0x72 /* "bar" */,
866 ];
867
868 assert_eq_written_bytes!(o_prot, expected);
869 }
870
871 #[test]
872 fn must_read_message_begin_zero_sequence_number() {
873 let (mut i_prot, _) = test_objects();
874
875 #[rustfmt::skip]
876 let source_bytes: [u8; 7] = [
877 0x82, /* protocol ID */
878 0x41, /* message type | protocol version */
879 0x00, /* non-zig-zag varint sequence number */
880 0x03, /* message-name length */
881 0x62,
882 0x61,
883 0x72 /* "bar" */,
884 ];
885
886 i_prot.transport.set_readable_bytes(&source_bytes);
887
888 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 0);
889 let res = assert_success!(i_prot.read_message_begin());
890
891 assert_eq!(&expected, &res);
892 }
893
894 #[test]
895 fn must_write_message_begin_largest_minimum_negative_sequence_number() {
896 let (_, mut o_prot) = test_objects();
897
898 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
899 "bar",
900 TMessageType::Reply,
901 i32::MIN
902 )));
903
904 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
905 #[rustfmt::skip]
906 let expected: [u8; 11] = [
907 0x82, /* protocol ID */
908 0x41, /* message type | protocol version */
909 0x80,
910 0x80,
911 0x80,
912 0x80,
913 0x08, /* non-zig-zag varint sequence number */
914 0x03, /* message-name length */
915 0x62,
916 0x61,
917 0x72 /* "bar" */,
918 ];
919
920 assert_eq_written_bytes!(o_prot, expected);
921 }
922
923 #[test]
924 fn must_read_message_begin_largest_minimum_negative_sequence_number() {
925 let (mut i_prot, _) = test_objects();
926
927 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
928 #[rustfmt::skip]
929 let source_bytes: [u8; 11] = [
930 0x82, /* protocol ID */
931 0x41, /* message type | protocol version */
932 0x80,
933 0x80,
934 0x80,
935 0x80,
936 0x08, /* non-zig-zag varint sequence number */
937 0x03, /* message-name length */
938 0x62,
939 0x61,
940 0x72 /* "bar" */,
941 ];
942
943 i_prot.transport.set_readable_bytes(&source_bytes);
944
945 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MIN);
946 let res = assert_success!(i_prot.read_message_begin());
947
948 assert_eq!(&expected, &res);
949 }
950
951 #[test]
952 fn must_write_message_begin_negative_sequence_number_0() {
953 let (_, mut o_prot) = test_objects();
954
955 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
956 "foo",
957 TMessageType::Call,
958 -431
959 )));
960
961 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
962 #[rustfmt::skip]
963 let expected: [u8; 11] = [
964 0x82, /* protocol ID */
965 0x21, /* message type | protocol version */
966 0xD1,
967 0xFC,
968 0xFF,
969 0xFF,
970 0x0F, /* non-zig-zag varint sequence number */
971 0x03, /* message-name length */
972 0x66,
973 0x6F,
974 0x6F /* "foo" */,
975 ];
976
977 assert_eq_written_bytes!(o_prot, expected);
978 }
979
980 #[test]
981 fn must_read_message_begin_negative_sequence_number_0() {
982 let (mut i_prot, _) = test_objects();
983
984 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
985 #[rustfmt::skip]
986 let source_bytes: [u8; 11] = [
987 0x82, /* protocol ID */
988 0x21, /* message type | protocol version */
989 0xD1,
990 0xFC,
991 0xFF,
992 0xFF,
993 0x0F, /* non-zig-zag varint sequence number */
994 0x03, /* message-name length */
995 0x66,
996 0x6F,
997 0x6F /* "foo" */,
998 ];
999
1000 i_prot.transport.set_readable_bytes(&source_bytes);
1001
1002 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -431);
1003 let res = assert_success!(i_prot.read_message_begin());
1004
1005 assert_eq!(&expected, &res);
1006 }
1007
1008 #[test]
1009 fn must_write_message_begin_negative_sequence_number_1() {
1010 let (_, mut o_prot) = test_objects();
1011
1012 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1013 "foo",
1014 TMessageType::Call,
1015 -73_184_125
1016 )));
1017
1018 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1019 #[rustfmt::skip]
1020 let expected: [u8; 11] = [
1021 0x82, /* protocol ID */
1022 0x21, /* message type | protocol version */
1023 0x83,
1024 0x99,
1025 0x8D,
1026 0xDD,
1027 0x0F, /* non-zig-zag varint sequence number */
1028 0x03, /* message-name length */
1029 0x66,
1030 0x6F,
1031 0x6F /* "foo" */,
1032 ];
1033
1034 assert_eq_written_bytes!(o_prot, expected);
1035 }
1036
1037 #[test]
1038 fn must_read_message_begin_negative_sequence_number_1() {
1039 let (mut i_prot, _) = test_objects();
1040
1041 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1042 #[rustfmt::skip]
1043 let source_bytes: [u8; 11] = [
1044 0x82, /* protocol ID */
1045 0x21, /* message type | protocol version */
1046 0x83,
1047 0x99,
1048 0x8D,
1049 0xDD,
1050 0x0F, /* non-zig-zag varint sequence number */
1051 0x03, /* message-name length */
1052 0x66,
1053 0x6F,
1054 0x6F /* "foo" */,
1055 ];
1056
1057 i_prot.transport.set_readable_bytes(&source_bytes);
1058
1059 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -73_184_125);
1060 let res = assert_success!(i_prot.read_message_begin());
1061
1062 assert_eq!(&expected, &res);
1063 }
1064
1065 #[test]
1066 fn must_write_message_begin_negative_sequence_number_2() {
1067 let (_, mut o_prot) = test_objects();
1068
1069 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1070 "foo",
1071 TMessageType::Call,
1072 -1_073_741_823
1073 )));
1074
1075 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
1076 #[rustfmt::skip]
1077 let expected: [u8; 11] = [
1078 0x82, /* protocol ID */
1079 0x21, /* message type | protocol version */
1080 0x81,
1081 0x80,
1082 0x80,
1083 0x80,
1084 0x0C, /* non-zig-zag varint sequence number */
1085 0x03, /* message-name length */
1086 0x66,
1087 0x6F,
1088 0x6F /* "foo" */,
1089 ];
1090
1091 assert_eq_written_bytes!(o_prot, expected);
1092 }
1093
1094 #[test]
1095 fn must_read_message_begin_negative_sequence_number_2() {
1096 let (mut i_prot, _) = test_objects();
1097
1098 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
Allen George55c3e4c2021-03-01 23:19:52 -05001099 #[rustfmt::skip]
Allen George8a1743d2020-12-05 01:19:27 -05001100 let source_bytes: [u8; 11] = [
1101 0x82, /* protocol ID */
1102 0x21, /* message type | protocol version */
1103 0x81,
1104 0x80,
1105 0x80,
1106 0x80,
1107 0x0C, /* non-zig-zag varint sequence number */
1108 0x03, /* message-name length */
1109 0x66,
1110 0x6F,
Allen George55c3e4c2021-03-01 23:19:52 -05001111 0x6F, /* "foo" */
Allen George8a1743d2020-12-05 01:19:27 -05001112 ];
1113
1114 i_prot.transport.set_readable_bytes(&source_bytes);
1115
1116 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -1_073_741_823);
1117 let res = assert_success!(i_prot.read_message_begin());
1118
1119 assert_eq!(&expected, &res);
1120 }
1121
1122 #[test]
Nik Claytone7917602020-03-05 11:51:15 +01001123 fn must_round_trip_upto_i64_maxvalue() {
1124 // See https://issues.apache.org/jira/browse/THRIFT-5131
1125 for i in 0..64 {
1126 let (mut i_prot, mut o_prot) = test_objects();
1127 let val: i64 = ((1u64 << i) - 1) as i64;
1128
1129 o_prot
Allen George8a1743d2020-12-05 01:19:27 -05001130 .write_field_begin(&TFieldIdentifier::new("val", TType::I64, 1))
Nik Claytone7917602020-03-05 11:51:15 +01001131 .unwrap();
1132 o_prot.write_i64(val).unwrap();
1133 o_prot.write_field_end().unwrap();
1134 o_prot.flush().unwrap();
1135
1136 copy_write_buffer_to_read_buffer!(o_prot);
1137
1138 i_prot.read_field_begin().unwrap();
1139 assert_eq!(val, i_prot.read_i64().unwrap());
1140 }
1141 }
1142
1143 #[test]
Allen George8b96bfb2016-11-02 08:01:08 -04001144 fn must_round_trip_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -05001145 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001146
Allen George7ddbcc02020-11-08 09:51:19 -05001147 let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948);
Allen George8b96bfb2016-11-02 08:01:08 -04001148
1149 assert_success!(o_prot.write_message_begin(&ident));
1150
Allen George0e22c362017-01-30 07:15:00 -05001151 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001152
1153 let res = assert_success!(i_prot.read_message_begin());
1154 assert_eq!(&res, &ident);
1155 }
1156
1157 #[test]
1158 fn must_write_message_end() {
1159 assert_no_write(|o| o.write_message_end());
1160 }
1161
1162 // NOTE: structs and fields are tested together
1163 //
1164
1165 #[test]
1166 fn must_write_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001167 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001168
1169 // no bytes should be written however
1170 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1171
1172 // write three fields with tiny field ids
1173 // since they're small the field ids will be encoded as deltas
1174
1175 // since this is the first field (and it's zero) it gets the full varint write
1176 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
1177 assert_success!(o_prot.write_field_end());
1178
1179 // since this delta > 0 and < 15 it can be encoded as a delta
1180 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
1181 assert_success!(o_prot.write_field_end());
1182
1183 // since this delta > 0 and < 15 it can be encoded as a delta
1184 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
1185 assert_success!(o_prot.write_field_end());
1186
1187 // now, finish the struct off
1188 assert_success!(o_prot.write_field_stop());
1189 assert_success!(o_prot.write_struct_end());
1190
Allen George7ddbcc02020-11-08 09:51:19 -05001191 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001192 let expected: [u8; 5] = [
1193 0x03, /* field type */
1194 0x00, /* first field id */
1195 0x44, /* field delta (4) | field type */
1196 0x59, /* field delta (5) | field type */
1197 0x00 /* field stop */,
1198 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001199
Allen George0e22c362017-01-30 07:15:00 -05001200 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001201 }
1202
1203 #[test]
1204 fn must_round_trip_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001205 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001206
1207 // no bytes should be written however
1208 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1209
1210 // write three fields with tiny field ids
1211 // since they're small the field ids will be encoded as deltas
1212
1213 // since this is the first field (and it's zero) it gets the full varint write
1214 let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
1215 assert_success!(o_prot.write_field_begin(&field_ident_1));
1216 assert_success!(o_prot.write_field_end());
1217
1218 // since this delta > 0 and < 15 it can be encoded as a delta
1219 let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
1220 assert_success!(o_prot.write_field_begin(&field_ident_2));
1221 assert_success!(o_prot.write_field_end());
1222
1223 // since this delta > 0 and < 15 it can be encoded as a delta
1224 let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
1225 assert_success!(o_prot.write_field_begin(&field_ident_3));
1226 assert_success!(o_prot.write_field_end());
1227
1228 // now, finish the struct off
1229 assert_success!(o_prot.write_field_stop());
1230 assert_success!(o_prot.write_struct_end());
1231
Allen George0e22c362017-01-30 07:15:00 -05001232 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001233
1234 // read the struct back
1235 assert_success!(i_prot.read_struct_begin());
1236
1237 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001238 assert_eq!(
1239 read_ident_1,
1240 TFieldIdentifier {
1241 name: None,
1242 ..field_ident_1
1243 }
1244 );
Allen George8b96bfb2016-11-02 08:01:08 -04001245 assert_success!(i_prot.read_field_end());
1246
1247 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001248 assert_eq!(
1249 read_ident_2,
1250 TFieldIdentifier {
1251 name: None,
1252 ..field_ident_2
1253 }
1254 );
Allen George8b96bfb2016-11-02 08:01:08 -04001255 assert_success!(i_prot.read_field_end());
1256
1257 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001258 assert_eq!(
1259 read_ident_3,
1260 TFieldIdentifier {
1261 name: None,
1262 ..field_ident_3
1263 }
1264 );
Allen George8b96bfb2016-11-02 08:01:08 -04001265 assert_success!(i_prot.read_field_end());
1266
1267 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001268 assert_eq!(
1269 read_ident_4,
1270 TFieldIdentifier {
1271 name: None,
1272 field_type: TType::Stop,
1273 id: None,
1274 }
1275 );
Allen George8b96bfb2016-11-02 08:01:08 -04001276
1277 assert_success!(i_prot.read_struct_end());
1278 }
1279
1280 #[test]
1281 fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001282 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001283
1284 // no bytes should be written however
1285 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1286
1287 // write three fields with tiny field ids
1288 // since they're small the field ids will be encoded as deltas
1289
1290 // gets a delta write
1291 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
1292 assert_success!(o_prot.write_field_end());
1293
1294 // since this delta > 0 and < 15 it can be encoded as a delta
1295 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
1296 assert_success!(o_prot.write_field_end());
1297
1298 // since this delta > 0 and < 15 it can be encoded as a delta
1299 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
1300 assert_success!(o_prot.write_field_end());
1301
1302 // now, finish the struct off
1303 assert_success!(o_prot.write_field_stop());
1304 assert_success!(o_prot.write_struct_end());
1305
Allen George7ddbcc02020-11-08 09:51:19 -05001306 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001307 let expected: [u8; 4] = [
1308 0x15, /* field delta (1) | field type */
1309 0x1A, /* field delta (1) | field type */
1310 0x48, /* field delta (4) | field type */
1311 0x00 /* field stop */,
1312 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001313
Allen George0e22c362017-01-30 07:15:00 -05001314 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001315 }
1316
1317 #[test]
1318 fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001319 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001320
1321 // no bytes should be written however
1322 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1323
1324 // write three fields with tiny field ids
1325 // since they're small the field ids will be encoded as deltas
1326
1327 // gets a delta write
1328 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
1329 assert_success!(o_prot.write_field_begin(&field_ident_1));
1330 assert_success!(o_prot.write_field_end());
1331
1332 // since this delta > 0 and < 15 it can be encoded as a delta
1333 let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
1334 assert_success!(o_prot.write_field_begin(&field_ident_2));
1335 assert_success!(o_prot.write_field_end());
1336
1337 // since this delta > 0 and < 15 it can be encoded as a delta
1338 let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
1339 assert_success!(o_prot.write_field_begin(&field_ident_3));
1340 assert_success!(o_prot.write_field_end());
1341
1342 // now, finish the struct off
1343 assert_success!(o_prot.write_field_stop());
1344 assert_success!(o_prot.write_struct_end());
1345
Allen George0e22c362017-01-30 07:15:00 -05001346 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001347
1348 // read the struct back
1349 assert_success!(i_prot.read_struct_begin());
1350
1351 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001352 assert_eq!(
1353 read_ident_1,
1354 TFieldIdentifier {
1355 name: None,
1356 ..field_ident_1
1357 }
1358 );
Allen George8b96bfb2016-11-02 08:01:08 -04001359 assert_success!(i_prot.read_field_end());
1360
1361 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001362 assert_eq!(
1363 read_ident_2,
1364 TFieldIdentifier {
1365 name: None,
1366 ..field_ident_2
1367 }
1368 );
Allen George8b96bfb2016-11-02 08:01:08 -04001369 assert_success!(i_prot.read_field_end());
1370
1371 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001372 assert_eq!(
1373 read_ident_3,
1374 TFieldIdentifier {
1375 name: None,
1376 ..field_ident_3
1377 }
1378 );
Allen George8b96bfb2016-11-02 08:01:08 -04001379 assert_success!(i_prot.read_field_end());
1380
1381 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001382 assert_eq!(
1383 read_ident_4,
1384 TFieldIdentifier {
1385 name: None,
1386 field_type: TType::Stop,
1387 id: None,
1388 }
1389 );
Allen George8b96bfb2016-11-02 08:01:08 -04001390
1391 assert_success!(i_prot.read_struct_end());
1392 }
1393
1394 #[test]
1395 fn must_write_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001396 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001397
1398 // no bytes should be written however
1399 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1400
1401 // write three fields with field ids that cannot be encoded as deltas
1402
1403 // since this is the first field (and it's zero) it gets the full varint write
1404 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
1405 assert_success!(o_prot.write_field_end());
1406
1407 // since this delta is > 15 it is encoded as a zig-zag varint
1408 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
1409 assert_success!(o_prot.write_field_end());
1410
1411 // since this delta is > 15 it is encoded as a zig-zag varint
1412 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
1413 assert_success!(o_prot.write_field_end());
1414
1415 // now, finish the struct off
1416 assert_success!(o_prot.write_field_stop());
1417 assert_success!(o_prot.write_struct_end());
1418
Allen George7ddbcc02020-11-08 09:51:19 -05001419 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001420 let expected: [u8; 8] = [
1421 0x05, /* field type */
1422 0x00, /* first field id */
1423 0x06, /* field type */
1424 0x20, /* zig-zag varint field id */
1425 0x0A, /* field type */
1426 0xC6,
1427 0x01, /* zig-zag varint field id */
1428 0x00 /* field stop */,
1429 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001430
Allen George0e22c362017-01-30 07:15:00 -05001431 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001432 }
1433
1434 #[test]
1435 fn must_round_trip_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001436 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001437
1438 // no bytes should be written however
1439 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1440
1441 // write three fields with field ids that cannot be encoded as deltas
1442
1443 // since this is the first field (and it's zero) it gets the full varint write
1444 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
1445 assert_success!(o_prot.write_field_begin(&field_ident_1));
1446 assert_success!(o_prot.write_field_end());
1447
1448 // since this delta is > 15 it is encoded as a zig-zag varint
1449 let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
1450 assert_success!(o_prot.write_field_begin(&field_ident_2));
1451 assert_success!(o_prot.write_field_end());
1452
1453 // since this delta is > 15 it is encoded as a zig-zag varint
1454 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
1455 assert_success!(o_prot.write_field_begin(&field_ident_3));
1456 assert_success!(o_prot.write_field_end());
1457
1458 // now, finish the struct off
1459 assert_success!(o_prot.write_field_stop());
1460 assert_success!(o_prot.write_struct_end());
1461
Allen George0e22c362017-01-30 07:15:00 -05001462 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001463
1464 // read the struct back
1465 assert_success!(i_prot.read_struct_begin());
1466
1467 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001468 assert_eq!(
1469 read_ident_1,
1470 TFieldIdentifier {
1471 name: None,
1472 ..field_ident_1
1473 }
1474 );
Allen George8b96bfb2016-11-02 08:01:08 -04001475 assert_success!(i_prot.read_field_end());
1476
1477 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001478 assert_eq!(
1479 read_ident_2,
1480 TFieldIdentifier {
1481 name: None,
1482 ..field_ident_2
1483 }
1484 );
Allen George8b96bfb2016-11-02 08:01:08 -04001485 assert_success!(i_prot.read_field_end());
1486
1487 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001488 assert_eq!(
1489 read_ident_3,
1490 TFieldIdentifier {
1491 name: None,
1492 ..field_ident_3
1493 }
1494 );
Allen George8b96bfb2016-11-02 08:01:08 -04001495 assert_success!(i_prot.read_field_end());
1496
1497 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001498 assert_eq!(
1499 read_ident_4,
1500 TFieldIdentifier {
1501 name: None,
1502 field_type: TType::Stop,
1503 id: None,
1504 }
1505 );
Allen George8b96bfb2016-11-02 08:01:08 -04001506
1507 assert_success!(i_prot.read_struct_end());
1508 }
1509
1510 #[test]
1511 fn must_write_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001512 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001513
1514 // no bytes should be written however
1515 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1516
1517 // write three fields with field ids that cannot be encoded as deltas
1518
1519 // since the delta is > 0 and < 15 it gets a delta write
1520 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1521 assert_success!(o_prot.write_field_end());
1522
1523 // since this delta > 0 and < 15 it gets a delta write
1524 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1525 assert_success!(o_prot.write_field_end());
1526
1527 // since this delta is > 15 it is encoded as a zig-zag varint
1528 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
1529 assert_success!(o_prot.write_field_end());
1530
1531 // since this delta is > 15 it is encoded as a zig-zag varint
1532 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
1533 assert_success!(o_prot.write_field_end());
1534
1535 // since this is only 3 up from the previous it is recorded as a delta
1536 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
1537 assert_success!(o_prot.write_field_end());
1538
1539 // now, finish the struct off
1540 assert_success!(o_prot.write_field_stop());
1541 assert_success!(o_prot.write_struct_end());
1542
Allen George7ddbcc02020-11-08 09:51:19 -05001543 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001544 let expected: [u8; 10] = [
1545 0x16, /* field delta (1) | field type */
1546 0x85, /* field delta (8) | field type */
1547 0x0A, /* field type */
1548 0xD0,
1549 0x0F, /* zig-zag varint field id */
1550 0x0A, /* field type */
1551 0xA2,
1552 0x1F, /* zig-zag varint field id */
1553 0x3A, /* field delta (3) | field type */
1554 0x00 /* field stop */,
1555 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001556
Allen George0e22c362017-01-30 07:15:00 -05001557 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001558 }
1559
Allen George7ddbcc02020-11-08 09:51:19 -05001560 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001561 #[test]
1562 fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001563 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001564
1565 // no bytes should be written however
1566 let struct_ident = TStructIdentifier::new("foo");
1567 assert_success!(o_prot.write_struct_begin(&struct_ident));
1568
1569 // write three fields with field ids that cannot be encoded as deltas
1570
1571 // since the delta is > 0 and < 15 it gets a delta write
1572 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1573 assert_success!(o_prot.write_field_begin(&field_ident_1));
1574 assert_success!(o_prot.write_field_end());
1575
1576 // since this delta > 0 and < 15 it gets a delta write
1577 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1578 assert_success!(o_prot.write_field_begin(&field_ident_2));
1579 assert_success!(o_prot.write_field_end());
1580
1581 // since this delta is > 15 it is encoded as a zig-zag varint
1582 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
1583 assert_success!(o_prot.write_field_begin(&field_ident_3));
1584 assert_success!(o_prot.write_field_end());
1585
1586 // since this delta is > 15 it is encoded as a zig-zag varint
1587 let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
1588 assert_success!(o_prot.write_field_begin(&field_ident_4));
1589 assert_success!(o_prot.write_field_end());
1590
1591 // since this is only 3 up from the previous it is recorded as a delta
1592 let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
1593 assert_success!(o_prot.write_field_begin(&field_ident_5));
1594 assert_success!(o_prot.write_field_end());
1595
1596 // now, finish the struct off
1597 assert_success!(o_prot.write_field_stop());
1598 assert_success!(o_prot.write_struct_end());
1599
Allen George0e22c362017-01-30 07:15:00 -05001600 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001601
1602 // read the struct back
1603 assert_success!(i_prot.read_struct_begin());
1604
1605 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001606 assert_eq!(
1607 read_ident_1,
1608 TFieldIdentifier {
1609 name: None,
1610 ..field_ident_1
1611 }
1612 );
Allen George8b96bfb2016-11-02 08:01:08 -04001613 assert_success!(i_prot.read_field_end());
1614
1615 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001616 assert_eq!(
1617 read_ident_2,
1618 TFieldIdentifier {
1619 name: None,
1620 ..field_ident_2
1621 }
1622 );
Allen George8b96bfb2016-11-02 08:01:08 -04001623 assert_success!(i_prot.read_field_end());
1624
1625 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001626 assert_eq!(
1627 read_ident_3,
1628 TFieldIdentifier {
1629 name: None,
1630 ..field_ident_3
1631 }
1632 );
Allen George8b96bfb2016-11-02 08:01:08 -04001633 assert_success!(i_prot.read_field_end());
1634
1635 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001636 assert_eq!(
1637 read_ident_4,
1638 TFieldIdentifier {
1639 name: None,
1640 ..field_ident_4
1641 }
1642 );
Allen George8b96bfb2016-11-02 08:01:08 -04001643 assert_success!(i_prot.read_field_end());
1644
1645 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001646 assert_eq!(
1647 read_ident_5,
1648 TFieldIdentifier {
1649 name: None,
1650 ..field_ident_5
1651 }
1652 );
Allen George8b96bfb2016-11-02 08:01:08 -04001653 assert_success!(i_prot.read_field_end());
1654
1655 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001656 assert_eq!(
1657 read_ident_6,
1658 TFieldIdentifier {
1659 name: None,
1660 field_type: TType::Stop,
1661 id: None,
1662 }
1663 );
Allen George8b96bfb2016-11-02 08:01:08 -04001664
1665 assert_success!(i_prot.read_struct_end());
1666 }
1667
1668 #[test]
1669 fn must_write_nested_structs_0() {
1670 // last field of the containing struct is a delta
1671 // first field of the the contained struct is a delta
1672
Allen George0e22c362017-01-30 07:15:00 -05001673 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001674
1675 // start containing struct
1676 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1677
1678 // containing struct
1679 // since the delta is > 0 and < 15 it gets a delta write
1680 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1681 assert_success!(o_prot.write_field_end());
1682
1683 // containing struct
1684 // since this delta > 0 and < 15 it gets a delta write
1685 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1686 assert_success!(o_prot.write_field_end());
1687
1688 // start contained struct
1689 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1690
1691 // contained struct
1692 // since the delta is > 0 and < 15 it gets a delta write
1693 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
1694 assert_success!(o_prot.write_field_end());
1695
1696 // contained struct
1697 // since this delta > 15 it gets a full write
1698 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1699 assert_success!(o_prot.write_field_end());
1700
1701 // end contained struct
1702 assert_success!(o_prot.write_field_stop());
1703 assert_success!(o_prot.write_struct_end());
1704
1705 // end containing struct
1706 assert_success!(o_prot.write_field_stop());
1707 assert_success!(o_prot.write_struct_end());
1708
Allen George7ddbcc02020-11-08 09:51:19 -05001709 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001710 let expected: [u8; 7] = [
1711 0x16, /* field delta (1) | field type */
1712 0x85, /* field delta (8) | field type */
1713 0x73, /* field delta (7) | field type */
1714 0x07, /* field type */
1715 0x30, /* zig-zag varint field id */
1716 0x00, /* field stop - contained */
1717 0x00 /* field stop - containing */,
1718 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001719
Allen George0e22c362017-01-30 07:15:00 -05001720 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001721 }
1722
Allen George7ddbcc02020-11-08 09:51:19 -05001723 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001724 #[test]
1725 fn must_round_trip_nested_structs_0() {
1726 // last field of the containing struct is a delta
1727 // first field of the the contained struct is a delta
1728
Allen George0e22c362017-01-30 07:15:00 -05001729 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001730
1731 // start containing struct
1732 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1733
1734 // containing struct
1735 // since the delta is > 0 and < 15 it gets a delta write
1736 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1737 assert_success!(o_prot.write_field_begin(&field_ident_1));
1738 assert_success!(o_prot.write_field_end());
1739
1740 // containing struct
1741 // since this delta > 0 and < 15 it gets a delta write
1742 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1743 assert_success!(o_prot.write_field_begin(&field_ident_2));
1744 assert_success!(o_prot.write_field_end());
1745
1746 // start contained struct
1747 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1748
1749 // contained struct
1750 // since the delta is > 0 and < 15 it gets a delta write
1751 let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
1752 assert_success!(o_prot.write_field_begin(&field_ident_3));
1753 assert_success!(o_prot.write_field_end());
1754
1755 // contained struct
1756 // since this delta > 15 it gets a full write
1757 let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
1758 assert_success!(o_prot.write_field_begin(&field_ident_4));
1759 assert_success!(o_prot.write_field_end());
1760
1761 // end contained struct
1762 assert_success!(o_prot.write_field_stop());
1763 assert_success!(o_prot.write_struct_end());
1764
1765 // end containing struct
1766 assert_success!(o_prot.write_field_stop());
1767 assert_success!(o_prot.write_struct_end());
1768
Allen George0e22c362017-01-30 07:15:00 -05001769 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001770
1771 // read containing struct back
1772 assert_success!(i_prot.read_struct_begin());
1773
1774 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001775 assert_eq!(
1776 read_ident_1,
1777 TFieldIdentifier {
1778 name: None,
1779 ..field_ident_1
1780 }
1781 );
Allen George8b96bfb2016-11-02 08:01:08 -04001782 assert_success!(i_prot.read_field_end());
1783
1784 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001785 assert_eq!(
1786 read_ident_2,
1787 TFieldIdentifier {
1788 name: None,
1789 ..field_ident_2
1790 }
1791 );
Allen George8b96bfb2016-11-02 08:01:08 -04001792 assert_success!(i_prot.read_field_end());
1793
1794 // read contained struct back
1795 assert_success!(i_prot.read_struct_begin());
1796
1797 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001798 assert_eq!(
1799 read_ident_3,
1800 TFieldIdentifier {
1801 name: None,
1802 ..field_ident_3
1803 }
1804 );
Allen George8b96bfb2016-11-02 08:01:08 -04001805 assert_success!(i_prot.read_field_end());
1806
1807 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001808 assert_eq!(
1809 read_ident_4,
1810 TFieldIdentifier {
1811 name: None,
1812 ..field_ident_4
1813 }
1814 );
Allen George8b96bfb2016-11-02 08:01:08 -04001815 assert_success!(i_prot.read_field_end());
1816
1817 // end contained struct
1818 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001819 assert_eq!(
1820 read_ident_6,
1821 TFieldIdentifier {
1822 name: None,
1823 field_type: TType::Stop,
1824 id: None,
1825 }
1826 );
Allen George8b96bfb2016-11-02 08:01:08 -04001827 assert_success!(i_prot.read_struct_end());
1828
1829 // end containing struct
1830 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001831 assert_eq!(
1832 read_ident_7,
1833 TFieldIdentifier {
1834 name: None,
1835 field_type: TType::Stop,
1836 id: None,
1837 }
1838 );
Allen George8b96bfb2016-11-02 08:01:08 -04001839 assert_success!(i_prot.read_struct_end());
1840 }
1841
1842 #[test]
1843 fn must_write_nested_structs_1() {
1844 // last field of the containing struct is a delta
1845 // first field of the the contained struct is a full write
1846
Allen George0e22c362017-01-30 07:15:00 -05001847 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001848
1849 // start containing struct
1850 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1851
1852 // containing struct
1853 // since the delta is > 0 and < 15 it gets a delta write
1854 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1855 assert_success!(o_prot.write_field_end());
1856
1857 // containing struct
1858 // since this delta > 0 and < 15 it gets a delta write
1859 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1860 assert_success!(o_prot.write_field_end());
1861
1862 // start contained struct
1863 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1864
1865 // contained struct
1866 // since this delta > 15 it gets a full write
1867 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1868 assert_success!(o_prot.write_field_end());
1869
1870 // contained struct
1871 // since the delta is > 0 and < 15 it gets a delta write
1872 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1873 assert_success!(o_prot.write_field_end());
1874
1875 // end contained struct
1876 assert_success!(o_prot.write_field_stop());
1877 assert_success!(o_prot.write_struct_end());
1878
1879 // end containing struct
1880 assert_success!(o_prot.write_field_stop());
1881 assert_success!(o_prot.write_struct_end());
1882
Allen George7ddbcc02020-11-08 09:51:19 -05001883 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001884 let expected: [u8; 7] = [
1885 0x16, /* field delta (1) | field type */
1886 0x85, /* field delta (8) | field type */
1887 0x07, /* field type */
1888 0x30, /* zig-zag varint field id */
1889 0x33, /* field delta (3) | field type */
1890 0x00, /* field stop - contained */
1891 0x00 /* field stop - containing */,
1892 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001893
Allen George0e22c362017-01-30 07:15:00 -05001894 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001895 }
1896
Allen George7ddbcc02020-11-08 09:51:19 -05001897 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001898 #[test]
1899 fn must_round_trip_nested_structs_1() {
1900 // last field of the containing struct is a delta
1901 // first field of the the contained struct is a full write
1902
Allen George0e22c362017-01-30 07:15:00 -05001903 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001904
1905 // start containing struct
1906 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1907
1908 // containing struct
1909 // since the delta is > 0 and < 15 it gets a delta write
1910 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1911 assert_success!(o_prot.write_field_begin(&field_ident_1));
1912 assert_success!(o_prot.write_field_end());
1913
1914 // containing struct
1915 // since this delta > 0 and < 15 it gets a delta write
1916 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1917 assert_success!(o_prot.write_field_begin(&field_ident_2));
1918 assert_success!(o_prot.write_field_end());
1919
1920 // start contained struct
1921 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1922
1923 // contained struct
1924 // since this delta > 15 it gets a full write
1925 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
1926 assert_success!(o_prot.write_field_begin(&field_ident_3));
1927 assert_success!(o_prot.write_field_end());
1928
1929 // contained struct
1930 // since the delta is > 0 and < 15 it gets a delta write
1931 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
1932 assert_success!(o_prot.write_field_begin(&field_ident_4));
1933 assert_success!(o_prot.write_field_end());
1934
1935 // end contained struct
1936 assert_success!(o_prot.write_field_stop());
1937 assert_success!(o_prot.write_struct_end());
1938
1939 // end containing struct
1940 assert_success!(o_prot.write_field_stop());
1941 assert_success!(o_prot.write_struct_end());
1942
Allen George0e22c362017-01-30 07:15:00 -05001943 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001944
1945 // read containing struct back
1946 assert_success!(i_prot.read_struct_begin());
1947
1948 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001949 assert_eq!(
1950 read_ident_1,
1951 TFieldIdentifier {
1952 name: None,
1953 ..field_ident_1
1954 }
1955 );
Allen George8b96bfb2016-11-02 08:01:08 -04001956 assert_success!(i_prot.read_field_end());
1957
1958 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001959 assert_eq!(
1960 read_ident_2,
1961 TFieldIdentifier {
1962 name: None,
1963 ..field_ident_2
1964 }
1965 );
Allen George8b96bfb2016-11-02 08:01:08 -04001966 assert_success!(i_prot.read_field_end());
1967
1968 // read contained struct back
1969 assert_success!(i_prot.read_struct_begin());
1970
1971 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001972 assert_eq!(
1973 read_ident_3,
1974 TFieldIdentifier {
1975 name: None,
1976 ..field_ident_3
1977 }
1978 );
Allen George8b96bfb2016-11-02 08:01:08 -04001979 assert_success!(i_prot.read_field_end());
1980
1981 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001982 assert_eq!(
1983 read_ident_4,
1984 TFieldIdentifier {
1985 name: None,
1986 ..field_ident_4
1987 }
1988 );
Allen George8b96bfb2016-11-02 08:01:08 -04001989 assert_success!(i_prot.read_field_end());
1990
1991 // end contained struct
1992 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001993 assert_eq!(
1994 read_ident_6,
1995 TFieldIdentifier {
1996 name: None,
1997 field_type: TType::Stop,
1998 id: None,
1999 }
2000 );
Allen George8b96bfb2016-11-02 08:01:08 -04002001 assert_success!(i_prot.read_struct_end());
2002
2003 // end containing struct
2004 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002005 assert_eq!(
2006 read_ident_7,
2007 TFieldIdentifier {
2008 name: None,
2009 field_type: TType::Stop,
2010 id: None,
2011 }
2012 );
Allen George8b96bfb2016-11-02 08:01:08 -04002013 assert_success!(i_prot.read_struct_end());
2014 }
2015
2016 #[test]
2017 fn must_write_nested_structs_2() {
2018 // last field of the containing struct is a full write
2019 // first field of the the contained struct is a delta write
2020
Allen George0e22c362017-01-30 07:15:00 -05002021 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002022
2023 // start containing struct
2024 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2025
2026 // containing struct
2027 // since the delta is > 0 and < 15 it gets a delta write
2028 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2029 assert_success!(o_prot.write_field_end());
2030
2031 // containing struct
2032 // since this delta > 15 it gets a full write
2033 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2034 assert_success!(o_prot.write_field_end());
2035
2036 // start contained struct
2037 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2038
2039 // contained struct
2040 // since this delta > 0 and < 15 it gets a delta write
2041 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
2042 assert_success!(o_prot.write_field_end());
2043
2044 // contained struct
2045 // since the delta is > 0 and < 15 it gets a delta write
2046 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
2047 assert_success!(o_prot.write_field_end());
2048
2049 // end contained struct
2050 assert_success!(o_prot.write_field_stop());
2051 assert_success!(o_prot.write_struct_end());
2052
2053 // end containing struct
2054 assert_success!(o_prot.write_field_stop());
2055 assert_success!(o_prot.write_struct_end());
2056
Allen George7ddbcc02020-11-08 09:51:19 -05002057 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002058 let expected: [u8; 7] = [
2059 0x16, /* field delta (1) | field type */
2060 0x08, /* field type */
2061 0x2A, /* zig-zag varint field id */
2062 0x77, /* field delta(7) | field type */
2063 0x33, /* field delta (3) | field type */
2064 0x00, /* field stop - contained */
2065 0x00 /* field stop - containing */,
2066 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002067
Allen George0e22c362017-01-30 07:15:00 -05002068 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002069 }
2070
Allen George7ddbcc02020-11-08 09:51:19 -05002071 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002072 #[test]
2073 fn must_round_trip_nested_structs_2() {
Allen George0e22c362017-01-30 07:15:00 -05002074 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002075
2076 // start containing struct
2077 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2078
2079 // containing struct
2080 // since the delta is > 0 and < 15 it gets a delta write
2081 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2082 assert_success!(o_prot.write_field_begin(&field_ident_1));
2083 assert_success!(o_prot.write_field_end());
2084
2085 // containing struct
2086 // since this delta > 15 it gets a full write
2087 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2088 assert_success!(o_prot.write_field_begin(&field_ident_2));
2089 assert_success!(o_prot.write_field_end());
2090
2091 // start contained struct
2092 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2093
2094 // contained struct
2095 // since this delta > 0 and < 15 it gets a delta write
2096 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
2097 assert_success!(o_prot.write_field_begin(&field_ident_3));
2098 assert_success!(o_prot.write_field_end());
2099
2100 // contained struct
2101 // since the delta is > 0 and < 15 it gets a delta write
2102 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
2103 assert_success!(o_prot.write_field_begin(&field_ident_4));
2104 assert_success!(o_prot.write_field_end());
2105
2106 // end contained struct
2107 assert_success!(o_prot.write_field_stop());
2108 assert_success!(o_prot.write_struct_end());
2109
2110 // end containing struct
2111 assert_success!(o_prot.write_field_stop());
2112 assert_success!(o_prot.write_struct_end());
2113
Allen George0e22c362017-01-30 07:15:00 -05002114 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002115
2116 // read containing struct back
2117 assert_success!(i_prot.read_struct_begin());
2118
2119 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002120 assert_eq!(
2121 read_ident_1,
2122 TFieldIdentifier {
2123 name: None,
2124 ..field_ident_1
2125 }
2126 );
Allen George8b96bfb2016-11-02 08:01:08 -04002127 assert_success!(i_prot.read_field_end());
2128
2129 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002130 assert_eq!(
2131 read_ident_2,
2132 TFieldIdentifier {
2133 name: None,
2134 ..field_ident_2
2135 }
2136 );
Allen George8b96bfb2016-11-02 08:01:08 -04002137 assert_success!(i_prot.read_field_end());
2138
2139 // read contained struct back
2140 assert_success!(i_prot.read_struct_begin());
2141
2142 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002143 assert_eq!(
2144 read_ident_3,
2145 TFieldIdentifier {
2146 name: None,
2147 ..field_ident_3
2148 }
2149 );
Allen George8b96bfb2016-11-02 08:01:08 -04002150 assert_success!(i_prot.read_field_end());
2151
2152 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002153 assert_eq!(
2154 read_ident_4,
2155 TFieldIdentifier {
2156 name: None,
2157 ..field_ident_4
2158 }
2159 );
Allen George8b96bfb2016-11-02 08:01:08 -04002160 assert_success!(i_prot.read_field_end());
2161
2162 // end contained struct
2163 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002164 assert_eq!(
2165 read_ident_6,
2166 TFieldIdentifier {
2167 name: None,
2168 field_type: TType::Stop,
2169 id: None,
2170 }
2171 );
Allen George8b96bfb2016-11-02 08:01:08 -04002172 assert_success!(i_prot.read_struct_end());
2173
2174 // end containing struct
2175 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002176 assert_eq!(
2177 read_ident_7,
2178 TFieldIdentifier {
2179 name: None,
2180 field_type: TType::Stop,
2181 id: None,
2182 }
2183 );
Allen George8b96bfb2016-11-02 08:01:08 -04002184 assert_success!(i_prot.read_struct_end());
2185 }
2186
2187 #[test]
2188 fn must_write_nested_structs_3() {
2189 // last field of the containing struct is a full write
2190 // first field of the the contained struct is a full write
2191
Allen George0e22c362017-01-30 07:15:00 -05002192 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002193
2194 // start containing struct
2195 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2196
2197 // containing struct
2198 // since the delta is > 0 and < 15 it gets a delta write
2199 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2200 assert_success!(o_prot.write_field_end());
2201
2202 // containing struct
2203 // since this delta > 15 it gets a full write
2204 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2205 assert_success!(o_prot.write_field_end());
2206
2207 // start contained struct
2208 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2209
2210 // contained struct
2211 // since this delta > 15 it gets a full write
2212 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
2213 assert_success!(o_prot.write_field_end());
2214
2215 // contained struct
2216 // since the delta is > 0 and < 15 it gets a delta write
2217 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
2218 assert_success!(o_prot.write_field_end());
2219
2220 // end contained struct
2221 assert_success!(o_prot.write_field_stop());
2222 assert_success!(o_prot.write_struct_end());
2223
2224 // end containing struct
2225 assert_success!(o_prot.write_field_stop());
2226 assert_success!(o_prot.write_struct_end());
2227
Allen George7ddbcc02020-11-08 09:51:19 -05002228 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002229 let expected: [u8; 8] = [
2230 0x16, /* field delta (1) | field type */
2231 0x08, /* field type */
2232 0x2A, /* zig-zag varint field id */
2233 0x07, /* field type */
2234 0x2A, /* zig-zag varint field id */
2235 0x63, /* field delta (6) | field type */
2236 0x00, /* field stop - contained */
2237 0x00 /* field stop - containing */,
2238 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002239
Allen George0e22c362017-01-30 07:15:00 -05002240 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002241 }
2242
Allen George7ddbcc02020-11-08 09:51:19 -05002243 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002244 #[test]
2245 fn must_round_trip_nested_structs_3() {
2246 // last field of the containing struct is a full write
2247 // first field of the the contained struct is a full write
2248
Allen George0e22c362017-01-30 07:15:00 -05002249 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002250
2251 // start containing struct
2252 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2253
2254 // containing struct
2255 // since the delta is > 0 and < 15 it gets a delta write
2256 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2257 assert_success!(o_prot.write_field_begin(&field_ident_1));
2258 assert_success!(o_prot.write_field_end());
2259
2260 // containing struct
2261 // since this delta > 15 it gets a full write
2262 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2263 assert_success!(o_prot.write_field_begin(&field_ident_2));
2264 assert_success!(o_prot.write_field_end());
2265
2266 // start contained struct
2267 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2268
2269 // contained struct
2270 // since this delta > 15 it gets a full write
2271 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
2272 assert_success!(o_prot.write_field_begin(&field_ident_3));
2273 assert_success!(o_prot.write_field_end());
2274
2275 // contained struct
2276 // since the delta is > 0 and < 15 it gets a delta write
2277 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2278 assert_success!(o_prot.write_field_begin(&field_ident_4));
2279 assert_success!(o_prot.write_field_end());
2280
2281 // end contained struct
2282 assert_success!(o_prot.write_field_stop());
2283 assert_success!(o_prot.write_struct_end());
2284
2285 // end containing struct
2286 assert_success!(o_prot.write_field_stop());
2287 assert_success!(o_prot.write_struct_end());
2288
Allen George0e22c362017-01-30 07:15:00 -05002289 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002290
2291 // read containing struct back
2292 assert_success!(i_prot.read_struct_begin());
2293
2294 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002295 assert_eq!(
2296 read_ident_1,
2297 TFieldIdentifier {
2298 name: None,
2299 ..field_ident_1
2300 }
2301 );
Allen George8b96bfb2016-11-02 08:01:08 -04002302 assert_success!(i_prot.read_field_end());
2303
2304 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002305 assert_eq!(
2306 read_ident_2,
2307 TFieldIdentifier {
2308 name: None,
2309 ..field_ident_2
2310 }
2311 );
Allen George8b96bfb2016-11-02 08:01:08 -04002312 assert_success!(i_prot.read_field_end());
2313
2314 // read contained struct back
2315 assert_success!(i_prot.read_struct_begin());
2316
2317 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002318 assert_eq!(
2319 read_ident_3,
2320 TFieldIdentifier {
2321 name: None,
2322 ..field_ident_3
2323 }
2324 );
Allen George8b96bfb2016-11-02 08:01:08 -04002325 assert_success!(i_prot.read_field_end());
2326
2327 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002328 assert_eq!(
2329 read_ident_4,
2330 TFieldIdentifier {
2331 name: None,
2332 ..field_ident_4
2333 }
2334 );
Allen George8b96bfb2016-11-02 08:01:08 -04002335 assert_success!(i_prot.read_field_end());
2336
2337 // end contained struct
2338 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002339 assert_eq!(
2340 read_ident_6,
2341 TFieldIdentifier {
2342 name: None,
2343 field_type: TType::Stop,
2344 id: None,
2345 }
2346 );
Allen George8b96bfb2016-11-02 08:01:08 -04002347 assert_success!(i_prot.read_struct_end());
2348
2349 // end containing struct
2350 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002351 assert_eq!(
2352 read_ident_7,
2353 TFieldIdentifier {
2354 name: None,
2355 field_type: TType::Stop,
2356 id: None,
2357 }
2358 );
Allen George8b96bfb2016-11-02 08:01:08 -04002359 assert_success!(i_prot.read_struct_end());
2360 }
2361
2362 #[test]
2363 fn must_write_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002364 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002365
2366 // no bytes should be written however
2367 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2368
2369 // write three fields with field ids that cannot be encoded as deltas
2370
2371 // since the delta is > 0 and < 16 it gets a delta write
2372 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2373 assert_success!(o_prot.write_bool(true));
2374 assert_success!(o_prot.write_field_end());
2375
2376 // since this delta > 0 and < 15 it gets a delta write
2377 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
2378 assert_success!(o_prot.write_bool(false));
2379 assert_success!(o_prot.write_field_end());
2380
2381 // since this delta > 15 it gets a full write
2382 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
2383 assert_success!(o_prot.write_bool(true));
2384 assert_success!(o_prot.write_field_end());
2385
2386 // since this delta > 15 it gets a full write
2387 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
2388 assert_success!(o_prot.write_bool(false));
2389 assert_success!(o_prot.write_field_end());
2390
2391 // now, finish the struct off
2392 assert_success!(o_prot.write_field_stop());
2393 assert_success!(o_prot.write_struct_end());
2394
Allen George7ddbcc02020-11-08 09:51:19 -05002395 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002396 let expected: [u8; 7] = [
2397 0x11, /* field delta (1) | true */
2398 0x82, /* field delta (8) | false */
2399 0x01, /* true */
2400 0x34, /* field id */
2401 0x02, /* false */
2402 0x5A, /* field id */
2403 0x00 /* stop field */,
2404 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002405
Allen George0e22c362017-01-30 07:15:00 -05002406 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002407 }
2408
Allen George7ddbcc02020-11-08 09:51:19 -05002409 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002410 #[test]
2411 fn must_round_trip_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002412 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002413
2414 // no bytes should be written however
2415 let struct_ident = TStructIdentifier::new("foo");
2416 assert_success!(o_prot.write_struct_begin(&struct_ident));
2417
2418 // write two fields
2419
2420 // since the delta is > 0 and < 16 it gets a delta write
2421 let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
2422 assert_success!(o_prot.write_field_begin(&field_ident_1));
2423 assert_success!(o_prot.write_bool(true));
2424 assert_success!(o_prot.write_field_end());
2425
2426 // since this delta > 0 and < 15 it gets a delta write
2427 let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
2428 assert_success!(o_prot.write_field_begin(&field_ident_2));
2429 assert_success!(o_prot.write_bool(false));
2430 assert_success!(o_prot.write_field_end());
2431
2432 // since this delta > 15 it gets a full write
2433 let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
2434 assert_success!(o_prot.write_field_begin(&field_ident_3));
2435 assert_success!(o_prot.write_bool(true));
2436 assert_success!(o_prot.write_field_end());
2437
2438 // since this delta > 15 it gets a full write
2439 let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
2440 assert_success!(o_prot.write_field_begin(&field_ident_4));
2441 assert_success!(o_prot.write_bool(false));
2442 assert_success!(o_prot.write_field_end());
2443
2444 // now, finish the struct off
2445 assert_success!(o_prot.write_field_stop());
2446 assert_success!(o_prot.write_struct_end());
2447
Allen George0e22c362017-01-30 07:15:00 -05002448 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002449
2450 // read the struct back
2451 assert_success!(i_prot.read_struct_begin());
2452
2453 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002454 assert_eq!(
2455 read_ident_1,
2456 TFieldIdentifier {
2457 name: None,
2458 ..field_ident_1
2459 }
2460 );
Allen George8b96bfb2016-11-02 08:01:08 -04002461 let read_value_1 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002462 assert!(read_value_1);
Allen George8b96bfb2016-11-02 08:01:08 -04002463 assert_success!(i_prot.read_field_end());
2464
2465 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002466 assert_eq!(
2467 read_ident_2,
2468 TFieldIdentifier {
2469 name: None,
2470 ..field_ident_2
2471 }
2472 );
Allen George8b96bfb2016-11-02 08:01:08 -04002473 let read_value_2 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002474 assert!(!read_value_2);
Allen George8b96bfb2016-11-02 08:01:08 -04002475 assert_success!(i_prot.read_field_end());
2476
2477 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002478 assert_eq!(
2479 read_ident_3,
2480 TFieldIdentifier {
2481 name: None,
2482 ..field_ident_3
2483 }
2484 );
Allen George8b96bfb2016-11-02 08:01:08 -04002485 let read_value_3 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002486 assert!(read_value_3);
Allen George8b96bfb2016-11-02 08:01:08 -04002487 assert_success!(i_prot.read_field_end());
2488
2489 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002490 assert_eq!(
2491 read_ident_4,
2492 TFieldIdentifier {
2493 name: None,
2494 ..field_ident_4
2495 }
2496 );
Allen George8b96bfb2016-11-02 08:01:08 -04002497 let read_value_4 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002498 assert!(!read_value_4);
Allen George8b96bfb2016-11-02 08:01:08 -04002499 assert_success!(i_prot.read_field_end());
2500
2501 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002502 assert_eq!(
2503 read_ident_5,
2504 TFieldIdentifier {
2505 name: None,
2506 field_type: TType::Stop,
2507 id: None,
2508 }
2509 );
Allen George8b96bfb2016-11-02 08:01:08 -04002510
2511 assert_success!(i_prot.read_struct_end());
2512 }
2513
2514 #[test]
2515 #[should_panic]
2516 fn must_fail_if_write_field_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002517 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002518 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2519 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2520 o_prot.write_field_end().unwrap();
2521 }
2522
2523 #[test]
2524 #[should_panic]
2525 fn must_fail_if_write_stop_field_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002526 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002527 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2528 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2529 o_prot.write_field_stop().unwrap();
2530 }
2531
2532 #[test]
2533 #[should_panic]
2534 fn must_fail_if_write_struct_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002535 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002536 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2537 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2538 o_prot.write_struct_end().unwrap();
2539 }
2540
2541 #[test]
2542 #[should_panic]
2543 fn must_fail_if_write_struct_end_without_any_fields() {
Allen George0e22c362017-01-30 07:15:00 -05002544 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002545 o_prot.write_struct_end().unwrap();
2546 }
2547
2548 #[test]
2549 fn must_write_field_end() {
2550 assert_no_write(|o| o.write_field_end());
2551 }
2552
2553 #[test]
2554 fn must_write_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002555 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002556
2557 assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
2558
2559 let expected: [u8; 1] = [0x46 /* size | elem_type */];
2560
Allen George0e22c362017-01-30 07:15:00 -05002561 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002562 }
2563
2564 #[test]
2565 fn must_round_trip_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002566 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002567
2568 let ident = TListIdentifier::new(TType::I08, 10);
2569
2570 assert_success!(o_prot.write_list_begin(&ident));
2571
Allen George0e22c362017-01-30 07:15:00 -05002572 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002573
2574 let res = assert_success!(i_prot.read_list_begin());
2575 assert_eq!(&res, &ident);
2576 }
2577
2578 #[test]
2579 fn must_write_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002580 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002581
2582 let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
2583 assert!(res.is_ok());
2584
Allen George0e22c362017-01-30 07:15:00 -05002585 let expected: [u8; 3] = [
2586 0xF9, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002587 0x8F, 0x4E, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002588 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002589
Allen George0e22c362017-01-30 07:15:00 -05002590 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002591 }
2592
2593 #[test]
2594 fn must_round_trip_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002595 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002596
2597 let ident = TListIdentifier::new(TType::Set, 47381);
2598
2599 assert_success!(o_prot.write_list_begin(&ident));
2600
Allen George0e22c362017-01-30 07:15:00 -05002601 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002602
2603 let res = assert_success!(i_prot.read_list_begin());
2604 assert_eq!(&res, &ident);
2605 }
2606
2607 #[test]
2608 fn must_write_list_end() {
2609 assert_no_write(|o| o.write_list_end());
2610 }
2611
2612 #[test]
2613 fn must_write_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002614 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002615
2616 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
2617
2618 let expected: [u8; 1] = [0x2C /* size | elem_type */];
2619
Allen George0e22c362017-01-30 07:15:00 -05002620 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002621 }
2622
2623 #[test]
2624 fn must_round_trip_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002625 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002626
2627 let ident = TSetIdentifier::new(TType::I16, 7);
2628
2629 assert_success!(o_prot.write_set_begin(&ident));
2630
Allen George0e22c362017-01-30 07:15:00 -05002631 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002632
2633 let res = assert_success!(i_prot.read_set_begin());
2634 assert_eq!(&res, &ident);
2635 }
2636
2637 #[test]
2638 fn must_write_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002639 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002640
2641 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
2642
Allen George0e22c362017-01-30 07:15:00 -05002643 let expected: [u8; 4] = [
2644 0xF7, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002645 0xD3, 0xBA, 0x01, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002646 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002647
Allen George0e22c362017-01-30 07:15:00 -05002648 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002649 }
2650
2651 #[test]
2652 fn must_round_trip_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002653 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002654
Allen George7ddbcc02020-11-08 09:51:19 -05002655 let ident = TSetIdentifier::new(TType::Map, 3_928_429);
Allen George8b96bfb2016-11-02 08:01:08 -04002656
2657 assert_success!(o_prot.write_set_begin(&ident));
2658
Allen George0e22c362017-01-30 07:15:00 -05002659 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002660
2661 let res = assert_success!(i_prot.read_set_begin());
2662 assert_eq!(&res, &ident);
2663 }
2664
2665 #[test]
2666 fn must_write_set_end() {
2667 assert_no_write(|o| o.write_set_end());
2668 }
2669
2670 #[test]
2671 fn must_write_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002672 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002673
2674 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
2675
2676 let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything
2677
Allen George0e22c362017-01-30 07:15:00 -05002678 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002679 }
2680
2681 #[test]
2682 fn must_read_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002683 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002684
2685 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
2686
Allen George0e22c362017-01-30 07:15:00 -05002687 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002688
2689 let res = assert_success!(i_prot.read_map_begin());
Allen George0e22c362017-01-30 07:15:00 -05002690 assert_eq!(
2691 &res,
2692 &TMapIdentifier {
Allen Georgeef7a1892018-12-16 18:01:37 -05002693 key_type: None,
2694 value_type: None,
2695 size: 0,
2696 }
Allen George0e22c362017-01-30 07:15:00 -05002697 );
Allen George8b96bfb2016-11-02 08:01:08 -04002698 }
2699
2700 #[test]
2701 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002702 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002703
Allen Georgeef7a1892018-12-16 18:01:37 -05002704 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
2705 TType::Double,
2706 TType::String,
2707 238
2708 )));
Allen George8b96bfb2016-11-02 08:01:08 -04002709
Allen George0e22c362017-01-30 07:15:00 -05002710 let expected: [u8; 3] = [
Allen Georgeef7a1892018-12-16 18:01:37 -05002711 0xEE, 0x01, /* size as varint */
2712 0x78, /* key type | val type */
Allen George0e22c362017-01-30 07:15:00 -05002713 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002714
Allen George0e22c362017-01-30 07:15:00 -05002715 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002716 }
2717
2718 #[test]
2719 fn must_round_trip_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002720 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002721
Allen George7ddbcc02020-11-08 09:51:19 -05002722 let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349);
Allen George8b96bfb2016-11-02 08:01:08 -04002723
2724 assert_success!(o_prot.write_map_begin(&ident));
2725
Allen George0e22c362017-01-30 07:15:00 -05002726 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002727
2728 let res = assert_success!(i_prot.read_map_begin());
2729 assert_eq!(&res, &ident);
2730 }
2731
2732 #[test]
2733 fn must_write_map_end() {
2734 assert_no_write(|o| o.write_map_end());
2735 }
2736
2737 #[test]
2738 fn must_write_map_with_bool_key_and_value() {
Allen George0e22c362017-01-30 07:15:00 -05002739 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002740
2741 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
2742 assert_success!(o_prot.write_bool(true));
2743 assert_success!(o_prot.write_bool(false));
2744 assert_success!(o_prot.write_map_end());
2745
Allen George0e22c362017-01-30 07:15:00 -05002746 let expected: [u8; 4] = [
2747 0x01, /* size as varint */
2748 0x11, /* key type | val type */
2749 0x01, /* key: true */
Allen Georgeef7a1892018-12-16 18:01:37 -05002750 0x02, /* val: false */
Allen George0e22c362017-01-30 07:15:00 -05002751 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002752
Allen George0e22c362017-01-30 07:15:00 -05002753 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002754 }
2755
2756 #[test]
2757 fn must_round_trip_map_with_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002758 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002759
2760 let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
2761 assert_success!(o_prot.write_map_begin(&map_ident));
2762 assert_success!(o_prot.write_bool(true));
2763 assert_success!(o_prot.write_bool(false));
2764 assert_success!(o_prot.write_bool(false));
2765 assert_success!(o_prot.write_bool(true));
2766 assert_success!(o_prot.write_map_end());
2767
Allen George0e22c362017-01-30 07:15:00 -05002768 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002769
2770 // map header
2771 let rcvd_ident = assert_success!(i_prot.read_map_begin());
2772 assert_eq!(&rcvd_ident, &map_ident);
2773 // key 1
2774 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002775 assert!(b);
Allen George8b96bfb2016-11-02 08:01:08 -04002776 // val 1
2777 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002778 assert!(!b);
Allen George8b96bfb2016-11-02 08:01:08 -04002779 // key 2
2780 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002781 assert!(!b);
Allen George8b96bfb2016-11-02 08:01:08 -04002782 // val 2
2783 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002784 assert!(b);
Allen George8b96bfb2016-11-02 08:01:08 -04002785 // map end
2786 assert_success!(i_prot.read_map_end());
2787 }
2788
2789 #[test]
2790 fn must_read_map_end() {
Allen George0e22c362017-01-30 07:15:00 -05002791 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002792 assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
2793 }
2794
Allen Georgeef7a1892018-12-16 18:01:37 -05002795 fn test_objects() -> (
2796 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2797 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2798 ) {
Allen George0e22c362017-01-30 07:15:00 -05002799 let mem = TBufferChannel::with_capacity(80, 80);
Allen George8b96bfb2016-11-02 08:01:08 -04002800
Allen George0e22c362017-01-30 07:15:00 -05002801 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -04002802
Allen George0e22c362017-01-30 07:15:00 -05002803 let i_prot = TCompactInputProtocol::new(r_mem);
2804 let o_prot = TCompactOutputProtocol::new(w_mem);
Allen George8b96bfb2016-11-02 08:01:08 -04002805
Allen George0e22c362017-01-30 07:15:00 -05002806 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -04002807 }
2808
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002809 #[test]
2810 fn must_read_write_double() {
2811 let (mut i_prot, mut o_prot) = test_objects();
2812
Allen George7ddbcc02020-11-08 09:51:19 -05002813 #[allow(clippy::approx_constant)]
2814 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002815 o_prot.write_double(double).unwrap();
2816 copy_write_buffer_to_read_buffer!(o_prot);
2817
Allen George7ddbcc02020-11-08 09:51:19 -05002818 let read_double = i_prot.read_double().unwrap();
Cameron Martinda54fc82025-01-12 08:55:45 +00002819 assert!((read_double - double).abs() < f64::EPSILON);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002820 }
2821
2822 #[test]
2823 fn must_encode_double_as_other_langs() {
2824 let (_, mut o_prot) = test_objects();
2825 let expected = [24, 45, 68, 84, 251, 33, 9, 64];
2826
Allen George7ddbcc02020-11-08 09:51:19 -05002827 #[allow(clippy::approx_constant)]
2828 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002829 o_prot.write_double(double).unwrap();
2830
2831 assert_eq_written_bytes!(o_prot, expected);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002832 }
2833
Allen George0e22c362017-01-30 07:15:00 -05002834 fn assert_no_write<F>(mut write_fn: F)
2835 where
Allen Georgeb0d14132020-03-29 11:48:55 -04002836 F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> crate::Result<()>,
Allen George0e22c362017-01-30 07:15:00 -05002837 {
2838 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002839 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -05002840 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -04002841 }
2842}