blob: c0c43722ed80b1ca823c57138a89ad6084401fa1 [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 George8a1743d2020-12-05 01:19:27 -0500684 use std::i32;
685
Allen Georgeb0d14132020-03-29 11:48:55 -0400686 use crate::protocol::{
Allen Georgeef7a1892018-12-16 18:01:37 -0500687 TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
688 TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
689 };
Allen Georgeb0d14132020-03-29 11:48:55 -0400690 use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400691
692 use super::*;
693
694 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500695 fn must_write_message_begin_largest_maximum_positive_sequence_number() {
696 let (_, mut o_prot) = test_objects();
697
698 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
699 "bar",
700 TMessageType::Reply,
701 i32::MAX
702 )));
703
704 #[rustfmt::skip]
705 let expected: [u8; 11] = [
706 0x82, /* protocol ID */
707 0x41, /* message type | protocol version */
708 0xFF,
709 0xFF,
710 0xFF,
711 0xFF,
712 0x07, /* non-zig-zag varint sequence number */
713 0x03, /* message-name length */
714 0x62,
715 0x61,
716 0x72 /* "bar" */,
717 ];
718
719 assert_eq_written_bytes!(o_prot, expected);
720 }
721
722 #[test]
723 fn must_read_message_begin_largest_maximum_positive_sequence_number() {
724 let (mut i_prot, _) = test_objects();
725
726 #[rustfmt::skip]
727 let source_bytes: [u8; 11] = [
728 0x82, /* protocol ID */
729 0x41, /* message type | protocol version */
730 0xFF,
731 0xFF,
732 0xFF,
733 0xFF,
734 0x07, /* non-zig-zag varint sequence number */
735 0x03, /* message-name length */
736 0x62,
737 0x61,
738 0x72 /* "bar" */,
739 ];
740
741 i_prot.transport.set_readable_bytes(&source_bytes);
742
743 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MAX);
744 let res = assert_success!(i_prot.read_message_begin());
745
746 assert_eq!(&expected, &res);
747 }
748
749 #[test]
750 fn must_write_message_begin_positive_sequence_number_0() {
Allen George0e22c362017-01-30 07:15:00 -0500751 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400752
Allen Georgeef7a1892018-12-16 18:01:37 -0500753 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
754 "foo",
755 TMessageType::Call,
756 431
757 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400758
Allen George7ddbcc02020-11-08 09:51:19 -0500759 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500760 let expected: [u8; 8] = [
761 0x82, /* protocol ID */
762 0x21, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500763 0xAF,
764 0x03, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500765 0x03, /* message-name length */
766 0x66,
767 0x6F,
768 0x6F /* "foo" */,
769 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400770
Allen George0e22c362017-01-30 07:15:00 -0500771 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400772 }
773
774 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500775 fn must_read_message_begin_positive_sequence_number_0() {
776 let (mut i_prot, _) = test_objects();
777
778 #[rustfmt::skip]
779 let source_bytes: [u8; 8] = [
780 0x82, /* protocol ID */
781 0x21, /* message type | protocol version */
782 0xAF,
783 0x03, /* non-zig-zag varint sequence number */
784 0x03, /* message-name length */
785 0x66,
786 0x6F,
787 0x6F /* "foo" */,
788 ];
789
790 i_prot.transport.set_readable_bytes(&source_bytes);
791
792 let expected = TMessageIdentifier::new("foo", TMessageType::Call, 431);
793 let res = assert_success!(i_prot.read_message_begin());
794
795 assert_eq!(&expected, &res);
796 }
797
798 #[test]
799 fn must_write_message_begin_positive_sequence_number_1() {
Allen George0e22c362017-01-30 07:15:00 -0500800 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400801
Allen Georgeef7a1892018-12-16 18:01:37 -0500802 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
803 "bar",
804 TMessageType::Reply,
Allen George7ddbcc02020-11-08 09:51:19 -0500805 991_828
Allen Georgeef7a1892018-12-16 18:01:37 -0500806 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400807
Allen George7ddbcc02020-11-08 09:51:19 -0500808 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500809 let expected: [u8; 9] = [
810 0x82, /* protocol ID */
811 0x41, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500812 0xD4,
813 0xC4,
814 0x3C, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500815 0x03, /* message-name length */
816 0x62,
817 0x61,
818 0x72 /* "bar" */,
819 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400820
Allen George0e22c362017-01-30 07:15:00 -0500821 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400822 }
823
824 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500825 fn must_read_message_begin_positive_sequence_number_1() {
826 let (mut i_prot, _) = test_objects();
827
828 #[rustfmt::skip]
829 let source_bytes: [u8; 9] = [
830 0x82, /* protocol ID */
831 0x41, /* message type | protocol version */
832 0xD4,
833 0xC4,
834 0x3C, /* non-zig-zag varint sequence number */
835 0x03, /* message-name length */
836 0x62,
837 0x61,
838 0x72 /* "bar" */,
839 ];
840
841 i_prot.transport.set_readable_bytes(&source_bytes);
842
843 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 991_828);
844 let res = assert_success!(i_prot.read_message_begin());
845
846 assert_eq!(&expected, &res);
847 }
848
849 #[test]
850 fn must_write_message_begin_zero_sequence_number() {
851 let (_, mut o_prot) = test_objects();
852
853 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
854 "bar",
855 TMessageType::Reply,
856 0
857 )));
858
859 #[rustfmt::skip]
860 let expected: [u8; 7] = [
861 0x82, /* protocol ID */
862 0x41, /* message type | protocol version */
863 0x00, /* non-zig-zag varint sequence number */
864 0x03, /* message-name length */
865 0x62,
866 0x61,
867 0x72 /* "bar" */,
868 ];
869
870 assert_eq_written_bytes!(o_prot, expected);
871 }
872
873 #[test]
874 fn must_read_message_begin_zero_sequence_number() {
875 let (mut i_prot, _) = test_objects();
876
877 #[rustfmt::skip]
878 let source_bytes: [u8; 7] = [
879 0x82, /* protocol ID */
880 0x41, /* message type | protocol version */
881 0x00, /* non-zig-zag varint sequence number */
882 0x03, /* message-name length */
883 0x62,
884 0x61,
885 0x72 /* "bar" */,
886 ];
887
888 i_prot.transport.set_readable_bytes(&source_bytes);
889
890 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 0);
891 let res = assert_success!(i_prot.read_message_begin());
892
893 assert_eq!(&expected, &res);
894 }
895
896 #[test]
897 fn must_write_message_begin_largest_minimum_negative_sequence_number() {
898 let (_, mut o_prot) = test_objects();
899
900 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
901 "bar",
902 TMessageType::Reply,
903 i32::MIN
904 )));
905
906 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
907 #[rustfmt::skip]
908 let expected: [u8; 11] = [
909 0x82, /* protocol ID */
910 0x41, /* message type | protocol version */
911 0x80,
912 0x80,
913 0x80,
914 0x80,
915 0x08, /* non-zig-zag varint sequence number */
916 0x03, /* message-name length */
917 0x62,
918 0x61,
919 0x72 /* "bar" */,
920 ];
921
922 assert_eq_written_bytes!(o_prot, expected);
923 }
924
925 #[test]
926 fn must_read_message_begin_largest_minimum_negative_sequence_number() {
927 let (mut i_prot, _) = test_objects();
928
929 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
930 #[rustfmt::skip]
931 let source_bytes: [u8; 11] = [
932 0x82, /* protocol ID */
933 0x41, /* message type | protocol version */
934 0x80,
935 0x80,
936 0x80,
937 0x80,
938 0x08, /* non-zig-zag varint sequence number */
939 0x03, /* message-name length */
940 0x62,
941 0x61,
942 0x72 /* "bar" */,
943 ];
944
945 i_prot.transport.set_readable_bytes(&source_bytes);
946
947 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MIN);
948 let res = assert_success!(i_prot.read_message_begin());
949
950 assert_eq!(&expected, &res);
951 }
952
953 #[test]
954 fn must_write_message_begin_negative_sequence_number_0() {
955 let (_, mut o_prot) = test_objects();
956
957 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
958 "foo",
959 TMessageType::Call,
960 -431
961 )));
962
963 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
964 #[rustfmt::skip]
965 let expected: [u8; 11] = [
966 0x82, /* protocol ID */
967 0x21, /* message type | protocol version */
968 0xD1,
969 0xFC,
970 0xFF,
971 0xFF,
972 0x0F, /* non-zig-zag varint sequence number */
973 0x03, /* message-name length */
974 0x66,
975 0x6F,
976 0x6F /* "foo" */,
977 ];
978
979 assert_eq_written_bytes!(o_prot, expected);
980 }
981
982 #[test]
983 fn must_read_message_begin_negative_sequence_number_0() {
984 let (mut i_prot, _) = test_objects();
985
986 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
987 #[rustfmt::skip]
988 let source_bytes: [u8; 11] = [
989 0x82, /* protocol ID */
990 0x21, /* message type | protocol version */
991 0xD1,
992 0xFC,
993 0xFF,
994 0xFF,
995 0x0F, /* non-zig-zag varint sequence number */
996 0x03, /* message-name length */
997 0x66,
998 0x6F,
999 0x6F /* "foo" */,
1000 ];
1001
1002 i_prot.transport.set_readable_bytes(&source_bytes);
1003
1004 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -431);
1005 let res = assert_success!(i_prot.read_message_begin());
1006
1007 assert_eq!(&expected, &res);
1008 }
1009
1010 #[test]
1011 fn must_write_message_begin_negative_sequence_number_1() {
1012 let (_, mut o_prot) = test_objects();
1013
1014 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1015 "foo",
1016 TMessageType::Call,
1017 -73_184_125
1018 )));
1019
1020 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1021 #[rustfmt::skip]
1022 let expected: [u8; 11] = [
1023 0x82, /* protocol ID */
1024 0x21, /* message type | protocol version */
1025 0x83,
1026 0x99,
1027 0x8D,
1028 0xDD,
1029 0x0F, /* non-zig-zag varint sequence number */
1030 0x03, /* message-name length */
1031 0x66,
1032 0x6F,
1033 0x6F /* "foo" */,
1034 ];
1035
1036 assert_eq_written_bytes!(o_prot, expected);
1037 }
1038
1039 #[test]
1040 fn must_read_message_begin_negative_sequence_number_1() {
1041 let (mut i_prot, _) = test_objects();
1042
1043 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1044 #[rustfmt::skip]
1045 let source_bytes: [u8; 11] = [
1046 0x82, /* protocol ID */
1047 0x21, /* message type | protocol version */
1048 0x83,
1049 0x99,
1050 0x8D,
1051 0xDD,
1052 0x0F, /* non-zig-zag varint sequence number */
1053 0x03, /* message-name length */
1054 0x66,
1055 0x6F,
1056 0x6F /* "foo" */,
1057 ];
1058
1059 i_prot.transport.set_readable_bytes(&source_bytes);
1060
1061 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -73_184_125);
1062 let res = assert_success!(i_prot.read_message_begin());
1063
1064 assert_eq!(&expected, &res);
1065 }
1066
1067 #[test]
1068 fn must_write_message_begin_negative_sequence_number_2() {
1069 let (_, mut o_prot) = test_objects();
1070
1071 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1072 "foo",
1073 TMessageType::Call,
1074 -1_073_741_823
1075 )));
1076
1077 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
1078 #[rustfmt::skip]
1079 let expected: [u8; 11] = [
1080 0x82, /* protocol ID */
1081 0x21, /* message type | protocol version */
1082 0x81,
1083 0x80,
1084 0x80,
1085 0x80,
1086 0x0C, /* non-zig-zag varint sequence number */
1087 0x03, /* message-name length */
1088 0x66,
1089 0x6F,
1090 0x6F /* "foo" */,
1091 ];
1092
1093 assert_eq_written_bytes!(o_prot, expected);
1094 }
1095
1096 #[test]
1097 fn must_read_message_begin_negative_sequence_number_2() {
1098 let (mut i_prot, _) = test_objects();
1099
1100 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
Allen George55c3e4c2021-03-01 23:19:52 -05001101 #[rustfmt::skip]
Allen George8a1743d2020-12-05 01:19:27 -05001102 let source_bytes: [u8; 11] = [
1103 0x82, /* protocol ID */
1104 0x21, /* message type | protocol version */
1105 0x81,
1106 0x80,
1107 0x80,
1108 0x80,
1109 0x0C, /* non-zig-zag varint sequence number */
1110 0x03, /* message-name length */
1111 0x66,
1112 0x6F,
Allen George55c3e4c2021-03-01 23:19:52 -05001113 0x6F, /* "foo" */
Allen George8a1743d2020-12-05 01:19:27 -05001114 ];
1115
1116 i_prot.transport.set_readable_bytes(&source_bytes);
1117
1118 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -1_073_741_823);
1119 let res = assert_success!(i_prot.read_message_begin());
1120
1121 assert_eq!(&expected, &res);
1122 }
1123
1124 #[test]
Nik Claytone7917602020-03-05 11:51:15 +01001125 fn must_round_trip_upto_i64_maxvalue() {
1126 // See https://issues.apache.org/jira/browse/THRIFT-5131
1127 for i in 0..64 {
1128 let (mut i_prot, mut o_prot) = test_objects();
1129 let val: i64 = ((1u64 << i) - 1) as i64;
1130
1131 o_prot
Allen George8a1743d2020-12-05 01:19:27 -05001132 .write_field_begin(&TFieldIdentifier::new("val", TType::I64, 1))
Nik Claytone7917602020-03-05 11:51:15 +01001133 .unwrap();
1134 o_prot.write_i64(val).unwrap();
1135 o_prot.write_field_end().unwrap();
1136 o_prot.flush().unwrap();
1137
1138 copy_write_buffer_to_read_buffer!(o_prot);
1139
1140 i_prot.read_field_begin().unwrap();
1141 assert_eq!(val, i_prot.read_i64().unwrap());
1142 }
1143 }
1144
1145 #[test]
Allen George8b96bfb2016-11-02 08:01:08 -04001146 fn must_round_trip_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -05001147 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001148
Allen George7ddbcc02020-11-08 09:51:19 -05001149 let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948);
Allen George8b96bfb2016-11-02 08:01:08 -04001150
1151 assert_success!(o_prot.write_message_begin(&ident));
1152
Allen George0e22c362017-01-30 07:15:00 -05001153 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001154
1155 let res = assert_success!(i_prot.read_message_begin());
1156 assert_eq!(&res, &ident);
1157 }
1158
1159 #[test]
1160 fn must_write_message_end() {
1161 assert_no_write(|o| o.write_message_end());
1162 }
1163
1164 // NOTE: structs and fields are tested together
1165 //
1166
1167 #[test]
1168 fn must_write_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001169 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001170
1171 // no bytes should be written however
1172 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1173
1174 // write three fields with tiny field ids
1175 // since they're small the field ids will be encoded as deltas
1176
1177 // since this is the first field (and it's zero) it gets the full varint write
1178 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
1179 assert_success!(o_prot.write_field_end());
1180
1181 // since this delta > 0 and < 15 it can be encoded as a delta
1182 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
1183 assert_success!(o_prot.write_field_end());
1184
1185 // since this delta > 0 and < 15 it can be encoded as a delta
1186 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
1187 assert_success!(o_prot.write_field_end());
1188
1189 // now, finish the struct off
1190 assert_success!(o_prot.write_field_stop());
1191 assert_success!(o_prot.write_struct_end());
1192
Allen George7ddbcc02020-11-08 09:51:19 -05001193 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001194 let expected: [u8; 5] = [
1195 0x03, /* field type */
1196 0x00, /* first field id */
1197 0x44, /* field delta (4) | field type */
1198 0x59, /* field delta (5) | field type */
1199 0x00 /* field stop */,
1200 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001201
Allen George0e22c362017-01-30 07:15:00 -05001202 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001203 }
1204
1205 #[test]
1206 fn must_round_trip_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001207 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001208
1209 // no bytes should be written however
1210 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1211
1212 // write three fields with tiny field ids
1213 // since they're small the field ids will be encoded as deltas
1214
1215 // since this is the first field (and it's zero) it gets the full varint write
1216 let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
1217 assert_success!(o_prot.write_field_begin(&field_ident_1));
1218 assert_success!(o_prot.write_field_end());
1219
1220 // since this delta > 0 and < 15 it can be encoded as a delta
1221 let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
1222 assert_success!(o_prot.write_field_begin(&field_ident_2));
1223 assert_success!(o_prot.write_field_end());
1224
1225 // since this delta > 0 and < 15 it can be encoded as a delta
1226 let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
1227 assert_success!(o_prot.write_field_begin(&field_ident_3));
1228 assert_success!(o_prot.write_field_end());
1229
1230 // now, finish the struct off
1231 assert_success!(o_prot.write_field_stop());
1232 assert_success!(o_prot.write_struct_end());
1233
Allen George0e22c362017-01-30 07:15:00 -05001234 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001235
1236 // read the struct back
1237 assert_success!(i_prot.read_struct_begin());
1238
1239 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001240 assert_eq!(
1241 read_ident_1,
1242 TFieldIdentifier {
1243 name: None,
1244 ..field_ident_1
1245 }
1246 );
Allen George8b96bfb2016-11-02 08:01:08 -04001247 assert_success!(i_prot.read_field_end());
1248
1249 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001250 assert_eq!(
1251 read_ident_2,
1252 TFieldIdentifier {
1253 name: None,
1254 ..field_ident_2
1255 }
1256 );
Allen George8b96bfb2016-11-02 08:01:08 -04001257 assert_success!(i_prot.read_field_end());
1258
1259 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001260 assert_eq!(
1261 read_ident_3,
1262 TFieldIdentifier {
1263 name: None,
1264 ..field_ident_3
1265 }
1266 );
Allen George8b96bfb2016-11-02 08:01:08 -04001267 assert_success!(i_prot.read_field_end());
1268
1269 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001270 assert_eq!(
1271 read_ident_4,
1272 TFieldIdentifier {
1273 name: None,
1274 field_type: TType::Stop,
1275 id: None,
1276 }
1277 );
Allen George8b96bfb2016-11-02 08:01:08 -04001278
1279 assert_success!(i_prot.read_struct_end());
1280 }
1281
1282 #[test]
1283 fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001284 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001285
1286 // no bytes should be written however
1287 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1288
1289 // write three fields with tiny field ids
1290 // since they're small the field ids will be encoded as deltas
1291
1292 // gets a delta write
1293 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
1294 assert_success!(o_prot.write_field_end());
1295
1296 // since this delta > 0 and < 15 it can be encoded as a delta
1297 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
1298 assert_success!(o_prot.write_field_end());
1299
1300 // since this delta > 0 and < 15 it can be encoded as a delta
1301 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
1302 assert_success!(o_prot.write_field_end());
1303
1304 // now, finish the struct off
1305 assert_success!(o_prot.write_field_stop());
1306 assert_success!(o_prot.write_struct_end());
1307
Allen George7ddbcc02020-11-08 09:51:19 -05001308 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001309 let expected: [u8; 4] = [
1310 0x15, /* field delta (1) | field type */
1311 0x1A, /* field delta (1) | field type */
1312 0x48, /* field delta (4) | field type */
1313 0x00 /* field stop */,
1314 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001315
Allen George0e22c362017-01-30 07:15:00 -05001316 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001317 }
1318
1319 #[test]
1320 fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001321 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001322
1323 // no bytes should be written however
1324 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1325
1326 // write three fields with tiny field ids
1327 // since they're small the field ids will be encoded as deltas
1328
1329 // gets a delta write
1330 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
1331 assert_success!(o_prot.write_field_begin(&field_ident_1));
1332 assert_success!(o_prot.write_field_end());
1333
1334 // since this delta > 0 and < 15 it can be encoded as a delta
1335 let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
1336 assert_success!(o_prot.write_field_begin(&field_ident_2));
1337 assert_success!(o_prot.write_field_end());
1338
1339 // since this delta > 0 and < 15 it can be encoded as a delta
1340 let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
1341 assert_success!(o_prot.write_field_begin(&field_ident_3));
1342 assert_success!(o_prot.write_field_end());
1343
1344 // now, finish the struct off
1345 assert_success!(o_prot.write_field_stop());
1346 assert_success!(o_prot.write_struct_end());
1347
Allen George0e22c362017-01-30 07:15:00 -05001348 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001349
1350 // read the struct back
1351 assert_success!(i_prot.read_struct_begin());
1352
1353 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001354 assert_eq!(
1355 read_ident_1,
1356 TFieldIdentifier {
1357 name: None,
1358 ..field_ident_1
1359 }
1360 );
Allen George8b96bfb2016-11-02 08:01:08 -04001361 assert_success!(i_prot.read_field_end());
1362
1363 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001364 assert_eq!(
1365 read_ident_2,
1366 TFieldIdentifier {
1367 name: None,
1368 ..field_ident_2
1369 }
1370 );
Allen George8b96bfb2016-11-02 08:01:08 -04001371 assert_success!(i_prot.read_field_end());
1372
1373 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001374 assert_eq!(
1375 read_ident_3,
1376 TFieldIdentifier {
1377 name: None,
1378 ..field_ident_3
1379 }
1380 );
Allen George8b96bfb2016-11-02 08:01:08 -04001381 assert_success!(i_prot.read_field_end());
1382
1383 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001384 assert_eq!(
1385 read_ident_4,
1386 TFieldIdentifier {
1387 name: None,
1388 field_type: TType::Stop,
1389 id: None,
1390 }
1391 );
Allen George8b96bfb2016-11-02 08:01:08 -04001392
1393 assert_success!(i_prot.read_struct_end());
1394 }
1395
1396 #[test]
1397 fn must_write_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001398 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001399
1400 // no bytes should be written however
1401 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1402
1403 // write three fields with field ids that cannot be encoded as deltas
1404
1405 // since this is the first field (and it's zero) it gets the full varint write
1406 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
1407 assert_success!(o_prot.write_field_end());
1408
1409 // since this delta is > 15 it is encoded as a zig-zag varint
1410 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
1411 assert_success!(o_prot.write_field_end());
1412
1413 // since this delta is > 15 it is encoded as a zig-zag varint
1414 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
1415 assert_success!(o_prot.write_field_end());
1416
1417 // now, finish the struct off
1418 assert_success!(o_prot.write_field_stop());
1419 assert_success!(o_prot.write_struct_end());
1420
Allen George7ddbcc02020-11-08 09:51:19 -05001421 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001422 let expected: [u8; 8] = [
1423 0x05, /* field type */
1424 0x00, /* first field id */
1425 0x06, /* field type */
1426 0x20, /* zig-zag varint field id */
1427 0x0A, /* field type */
1428 0xC6,
1429 0x01, /* zig-zag varint field id */
1430 0x00 /* field stop */,
1431 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001432
Allen George0e22c362017-01-30 07:15:00 -05001433 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001434 }
1435
1436 #[test]
1437 fn must_round_trip_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001438 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001439
1440 // no bytes should be written however
1441 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1442
1443 // write three fields with field ids that cannot be encoded as deltas
1444
1445 // since this is the first field (and it's zero) it gets the full varint write
1446 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
1447 assert_success!(o_prot.write_field_begin(&field_ident_1));
1448 assert_success!(o_prot.write_field_end());
1449
1450 // since this delta is > 15 it is encoded as a zig-zag varint
1451 let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
1452 assert_success!(o_prot.write_field_begin(&field_ident_2));
1453 assert_success!(o_prot.write_field_end());
1454
1455 // since this delta is > 15 it is encoded as a zig-zag varint
1456 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
1457 assert_success!(o_prot.write_field_begin(&field_ident_3));
1458 assert_success!(o_prot.write_field_end());
1459
1460 // now, finish the struct off
1461 assert_success!(o_prot.write_field_stop());
1462 assert_success!(o_prot.write_struct_end());
1463
Allen George0e22c362017-01-30 07:15:00 -05001464 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001465
1466 // read the struct back
1467 assert_success!(i_prot.read_struct_begin());
1468
1469 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001470 assert_eq!(
1471 read_ident_1,
1472 TFieldIdentifier {
1473 name: None,
1474 ..field_ident_1
1475 }
1476 );
Allen George8b96bfb2016-11-02 08:01:08 -04001477 assert_success!(i_prot.read_field_end());
1478
1479 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001480 assert_eq!(
1481 read_ident_2,
1482 TFieldIdentifier {
1483 name: None,
1484 ..field_ident_2
1485 }
1486 );
Allen George8b96bfb2016-11-02 08:01:08 -04001487 assert_success!(i_prot.read_field_end());
1488
1489 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001490 assert_eq!(
1491 read_ident_3,
1492 TFieldIdentifier {
1493 name: None,
1494 ..field_ident_3
1495 }
1496 );
Allen George8b96bfb2016-11-02 08:01:08 -04001497 assert_success!(i_prot.read_field_end());
1498
1499 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001500 assert_eq!(
1501 read_ident_4,
1502 TFieldIdentifier {
1503 name: None,
1504 field_type: TType::Stop,
1505 id: None,
1506 }
1507 );
Allen George8b96bfb2016-11-02 08:01:08 -04001508
1509 assert_success!(i_prot.read_struct_end());
1510 }
1511
1512 #[test]
1513 fn must_write_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001514 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001515
1516 // no bytes should be written however
1517 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1518
1519 // write three fields with field ids that cannot be encoded as deltas
1520
1521 // since the delta is > 0 and < 15 it gets a delta write
1522 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1523 assert_success!(o_prot.write_field_end());
1524
1525 // since this delta > 0 and < 15 it gets a delta write
1526 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1527 assert_success!(o_prot.write_field_end());
1528
1529 // since this delta is > 15 it is encoded as a zig-zag varint
1530 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
1531 assert_success!(o_prot.write_field_end());
1532
1533 // since this delta is > 15 it is encoded as a zig-zag varint
1534 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
1535 assert_success!(o_prot.write_field_end());
1536
1537 // since this is only 3 up from the previous it is recorded as a delta
1538 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
1539 assert_success!(o_prot.write_field_end());
1540
1541 // now, finish the struct off
1542 assert_success!(o_prot.write_field_stop());
1543 assert_success!(o_prot.write_struct_end());
1544
Allen George7ddbcc02020-11-08 09:51:19 -05001545 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001546 let expected: [u8; 10] = [
1547 0x16, /* field delta (1) | field type */
1548 0x85, /* field delta (8) | field type */
1549 0x0A, /* field type */
1550 0xD0,
1551 0x0F, /* zig-zag varint field id */
1552 0x0A, /* field type */
1553 0xA2,
1554 0x1F, /* zig-zag varint field id */
1555 0x3A, /* field delta (3) | field type */
1556 0x00 /* field stop */,
1557 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001558
Allen George0e22c362017-01-30 07:15:00 -05001559 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001560 }
1561
Allen George7ddbcc02020-11-08 09:51:19 -05001562 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001563 #[test]
1564 fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001565 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001566
1567 // no bytes should be written however
1568 let struct_ident = TStructIdentifier::new("foo");
1569 assert_success!(o_prot.write_struct_begin(&struct_ident));
1570
1571 // write three fields with field ids that cannot be encoded as deltas
1572
1573 // since the delta is > 0 and < 15 it gets a delta write
1574 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1575 assert_success!(o_prot.write_field_begin(&field_ident_1));
1576 assert_success!(o_prot.write_field_end());
1577
1578 // since this delta > 0 and < 15 it gets a delta write
1579 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1580 assert_success!(o_prot.write_field_begin(&field_ident_2));
1581 assert_success!(o_prot.write_field_end());
1582
1583 // since this delta is > 15 it is encoded as a zig-zag varint
1584 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
1585 assert_success!(o_prot.write_field_begin(&field_ident_3));
1586 assert_success!(o_prot.write_field_end());
1587
1588 // since this delta is > 15 it is encoded as a zig-zag varint
1589 let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
1590 assert_success!(o_prot.write_field_begin(&field_ident_4));
1591 assert_success!(o_prot.write_field_end());
1592
1593 // since this is only 3 up from the previous it is recorded as a delta
1594 let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
1595 assert_success!(o_prot.write_field_begin(&field_ident_5));
1596 assert_success!(o_prot.write_field_end());
1597
1598 // now, finish the struct off
1599 assert_success!(o_prot.write_field_stop());
1600 assert_success!(o_prot.write_struct_end());
1601
Allen George0e22c362017-01-30 07:15:00 -05001602 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001603
1604 // read the struct back
1605 assert_success!(i_prot.read_struct_begin());
1606
1607 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001608 assert_eq!(
1609 read_ident_1,
1610 TFieldIdentifier {
1611 name: None,
1612 ..field_ident_1
1613 }
1614 );
Allen George8b96bfb2016-11-02 08:01:08 -04001615 assert_success!(i_prot.read_field_end());
1616
1617 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001618 assert_eq!(
1619 read_ident_2,
1620 TFieldIdentifier {
1621 name: None,
1622 ..field_ident_2
1623 }
1624 );
Allen George8b96bfb2016-11-02 08:01:08 -04001625 assert_success!(i_prot.read_field_end());
1626
1627 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001628 assert_eq!(
1629 read_ident_3,
1630 TFieldIdentifier {
1631 name: None,
1632 ..field_ident_3
1633 }
1634 );
Allen George8b96bfb2016-11-02 08:01:08 -04001635 assert_success!(i_prot.read_field_end());
1636
1637 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001638 assert_eq!(
1639 read_ident_4,
1640 TFieldIdentifier {
1641 name: None,
1642 ..field_ident_4
1643 }
1644 );
Allen George8b96bfb2016-11-02 08:01:08 -04001645 assert_success!(i_prot.read_field_end());
1646
1647 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001648 assert_eq!(
1649 read_ident_5,
1650 TFieldIdentifier {
1651 name: None,
1652 ..field_ident_5
1653 }
1654 );
Allen George8b96bfb2016-11-02 08:01:08 -04001655 assert_success!(i_prot.read_field_end());
1656
1657 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001658 assert_eq!(
1659 read_ident_6,
1660 TFieldIdentifier {
1661 name: None,
1662 field_type: TType::Stop,
1663 id: None,
1664 }
1665 );
Allen George8b96bfb2016-11-02 08:01:08 -04001666
1667 assert_success!(i_prot.read_struct_end());
1668 }
1669
1670 #[test]
1671 fn must_write_nested_structs_0() {
1672 // last field of the containing struct is a delta
1673 // first field of the the contained struct is a delta
1674
Allen George0e22c362017-01-30 07:15:00 -05001675 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001676
1677 // start containing struct
1678 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1679
1680 // containing struct
1681 // since the delta is > 0 and < 15 it gets a delta write
1682 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1683 assert_success!(o_prot.write_field_end());
1684
1685 // containing struct
1686 // since this delta > 0 and < 15 it gets a delta write
1687 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1688 assert_success!(o_prot.write_field_end());
1689
1690 // start contained struct
1691 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1692
1693 // contained struct
1694 // since the delta is > 0 and < 15 it gets a delta write
1695 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
1696 assert_success!(o_prot.write_field_end());
1697
1698 // contained struct
1699 // since this delta > 15 it gets a full write
1700 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1701 assert_success!(o_prot.write_field_end());
1702
1703 // end contained struct
1704 assert_success!(o_prot.write_field_stop());
1705 assert_success!(o_prot.write_struct_end());
1706
1707 // end containing struct
1708 assert_success!(o_prot.write_field_stop());
1709 assert_success!(o_prot.write_struct_end());
1710
Allen George7ddbcc02020-11-08 09:51:19 -05001711 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001712 let expected: [u8; 7] = [
1713 0x16, /* field delta (1) | field type */
1714 0x85, /* field delta (8) | field type */
1715 0x73, /* field delta (7) | field type */
1716 0x07, /* field type */
1717 0x30, /* zig-zag varint field id */
1718 0x00, /* field stop - contained */
1719 0x00 /* field stop - containing */,
1720 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001721
Allen George0e22c362017-01-30 07:15:00 -05001722 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001723 }
1724
Allen George7ddbcc02020-11-08 09:51:19 -05001725 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001726 #[test]
1727 fn must_round_trip_nested_structs_0() {
1728 // last field of the containing struct is a delta
1729 // first field of the the contained struct is a delta
1730
Allen George0e22c362017-01-30 07:15:00 -05001731 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001732
1733 // start containing struct
1734 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1735
1736 // containing struct
1737 // since the delta is > 0 and < 15 it gets a delta write
1738 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1739 assert_success!(o_prot.write_field_begin(&field_ident_1));
1740 assert_success!(o_prot.write_field_end());
1741
1742 // containing struct
1743 // since this delta > 0 and < 15 it gets a delta write
1744 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1745 assert_success!(o_prot.write_field_begin(&field_ident_2));
1746 assert_success!(o_prot.write_field_end());
1747
1748 // start contained struct
1749 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1750
1751 // contained struct
1752 // since the delta is > 0 and < 15 it gets a delta write
1753 let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
1754 assert_success!(o_prot.write_field_begin(&field_ident_3));
1755 assert_success!(o_prot.write_field_end());
1756
1757 // contained struct
1758 // since this delta > 15 it gets a full write
1759 let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
1760 assert_success!(o_prot.write_field_begin(&field_ident_4));
1761 assert_success!(o_prot.write_field_end());
1762
1763 // end contained struct
1764 assert_success!(o_prot.write_field_stop());
1765 assert_success!(o_prot.write_struct_end());
1766
1767 // end containing struct
1768 assert_success!(o_prot.write_field_stop());
1769 assert_success!(o_prot.write_struct_end());
1770
Allen George0e22c362017-01-30 07:15:00 -05001771 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001772
1773 // read containing struct back
1774 assert_success!(i_prot.read_struct_begin());
1775
1776 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001777 assert_eq!(
1778 read_ident_1,
1779 TFieldIdentifier {
1780 name: None,
1781 ..field_ident_1
1782 }
1783 );
Allen George8b96bfb2016-11-02 08:01:08 -04001784 assert_success!(i_prot.read_field_end());
1785
1786 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001787 assert_eq!(
1788 read_ident_2,
1789 TFieldIdentifier {
1790 name: None,
1791 ..field_ident_2
1792 }
1793 );
Allen George8b96bfb2016-11-02 08:01:08 -04001794 assert_success!(i_prot.read_field_end());
1795
1796 // read contained struct back
1797 assert_success!(i_prot.read_struct_begin());
1798
1799 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001800 assert_eq!(
1801 read_ident_3,
1802 TFieldIdentifier {
1803 name: None,
1804 ..field_ident_3
1805 }
1806 );
Allen George8b96bfb2016-11-02 08:01:08 -04001807 assert_success!(i_prot.read_field_end());
1808
1809 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001810 assert_eq!(
1811 read_ident_4,
1812 TFieldIdentifier {
1813 name: None,
1814 ..field_ident_4
1815 }
1816 );
Allen George8b96bfb2016-11-02 08:01:08 -04001817 assert_success!(i_prot.read_field_end());
1818
1819 // end contained struct
1820 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001821 assert_eq!(
1822 read_ident_6,
1823 TFieldIdentifier {
1824 name: None,
1825 field_type: TType::Stop,
1826 id: None,
1827 }
1828 );
Allen George8b96bfb2016-11-02 08:01:08 -04001829 assert_success!(i_prot.read_struct_end());
1830
1831 // end containing struct
1832 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001833 assert_eq!(
1834 read_ident_7,
1835 TFieldIdentifier {
1836 name: None,
1837 field_type: TType::Stop,
1838 id: None,
1839 }
1840 );
Allen George8b96bfb2016-11-02 08:01:08 -04001841 assert_success!(i_prot.read_struct_end());
1842 }
1843
1844 #[test]
1845 fn must_write_nested_structs_1() {
1846 // last field of the containing struct is a delta
1847 // first field of the the contained struct is a full write
1848
Allen George0e22c362017-01-30 07:15:00 -05001849 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001850
1851 // start containing struct
1852 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1853
1854 // containing struct
1855 // since the delta is > 0 and < 15 it gets a delta write
1856 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1857 assert_success!(o_prot.write_field_end());
1858
1859 // containing struct
1860 // since this delta > 0 and < 15 it gets a delta write
1861 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1862 assert_success!(o_prot.write_field_end());
1863
1864 // start contained struct
1865 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1866
1867 // contained struct
1868 // since this delta > 15 it gets a full write
1869 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1870 assert_success!(o_prot.write_field_end());
1871
1872 // contained struct
1873 // since the delta is > 0 and < 15 it gets a delta write
1874 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1875 assert_success!(o_prot.write_field_end());
1876
1877 // end contained struct
1878 assert_success!(o_prot.write_field_stop());
1879 assert_success!(o_prot.write_struct_end());
1880
1881 // end containing struct
1882 assert_success!(o_prot.write_field_stop());
1883 assert_success!(o_prot.write_struct_end());
1884
Allen George7ddbcc02020-11-08 09:51:19 -05001885 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001886 let expected: [u8; 7] = [
1887 0x16, /* field delta (1) | field type */
1888 0x85, /* field delta (8) | field type */
1889 0x07, /* field type */
1890 0x30, /* zig-zag varint field id */
1891 0x33, /* field delta (3) | field type */
1892 0x00, /* field stop - contained */
1893 0x00 /* field stop - containing */,
1894 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001895
Allen George0e22c362017-01-30 07:15:00 -05001896 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001897 }
1898
Allen George7ddbcc02020-11-08 09:51:19 -05001899 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001900 #[test]
1901 fn must_round_trip_nested_structs_1() {
1902 // last field of the containing struct is a delta
1903 // first field of the the contained struct is a full write
1904
Allen George0e22c362017-01-30 07:15:00 -05001905 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001906
1907 // start containing struct
1908 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1909
1910 // containing struct
1911 // since the delta is > 0 and < 15 it gets a delta write
1912 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1913 assert_success!(o_prot.write_field_begin(&field_ident_1));
1914 assert_success!(o_prot.write_field_end());
1915
1916 // containing struct
1917 // since this delta > 0 and < 15 it gets a delta write
1918 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1919 assert_success!(o_prot.write_field_begin(&field_ident_2));
1920 assert_success!(o_prot.write_field_end());
1921
1922 // start contained struct
1923 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1924
1925 // contained struct
1926 // since this delta > 15 it gets a full write
1927 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
1928 assert_success!(o_prot.write_field_begin(&field_ident_3));
1929 assert_success!(o_prot.write_field_end());
1930
1931 // contained struct
1932 // since the delta is > 0 and < 15 it gets a delta write
1933 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
1934 assert_success!(o_prot.write_field_begin(&field_ident_4));
1935 assert_success!(o_prot.write_field_end());
1936
1937 // end contained struct
1938 assert_success!(o_prot.write_field_stop());
1939 assert_success!(o_prot.write_struct_end());
1940
1941 // end containing struct
1942 assert_success!(o_prot.write_field_stop());
1943 assert_success!(o_prot.write_struct_end());
1944
Allen George0e22c362017-01-30 07:15:00 -05001945 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001946
1947 // read containing struct back
1948 assert_success!(i_prot.read_struct_begin());
1949
1950 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001951 assert_eq!(
1952 read_ident_1,
1953 TFieldIdentifier {
1954 name: None,
1955 ..field_ident_1
1956 }
1957 );
Allen George8b96bfb2016-11-02 08:01:08 -04001958 assert_success!(i_prot.read_field_end());
1959
1960 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001961 assert_eq!(
1962 read_ident_2,
1963 TFieldIdentifier {
1964 name: None,
1965 ..field_ident_2
1966 }
1967 );
Allen George8b96bfb2016-11-02 08:01:08 -04001968 assert_success!(i_prot.read_field_end());
1969
1970 // read contained struct back
1971 assert_success!(i_prot.read_struct_begin());
1972
1973 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001974 assert_eq!(
1975 read_ident_3,
1976 TFieldIdentifier {
1977 name: None,
1978 ..field_ident_3
1979 }
1980 );
Allen George8b96bfb2016-11-02 08:01:08 -04001981 assert_success!(i_prot.read_field_end());
1982
1983 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001984 assert_eq!(
1985 read_ident_4,
1986 TFieldIdentifier {
1987 name: None,
1988 ..field_ident_4
1989 }
1990 );
Allen George8b96bfb2016-11-02 08:01:08 -04001991 assert_success!(i_prot.read_field_end());
1992
1993 // end contained struct
1994 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001995 assert_eq!(
1996 read_ident_6,
1997 TFieldIdentifier {
1998 name: None,
1999 field_type: TType::Stop,
2000 id: None,
2001 }
2002 );
Allen George8b96bfb2016-11-02 08:01:08 -04002003 assert_success!(i_prot.read_struct_end());
2004
2005 // end containing struct
2006 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002007 assert_eq!(
2008 read_ident_7,
2009 TFieldIdentifier {
2010 name: None,
2011 field_type: TType::Stop,
2012 id: None,
2013 }
2014 );
Allen George8b96bfb2016-11-02 08:01:08 -04002015 assert_success!(i_prot.read_struct_end());
2016 }
2017
2018 #[test]
2019 fn must_write_nested_structs_2() {
2020 // last field of the containing struct is a full write
2021 // first field of the the contained struct is a delta write
2022
Allen George0e22c362017-01-30 07:15:00 -05002023 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002024
2025 // start containing struct
2026 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2027
2028 // containing struct
2029 // since the delta is > 0 and < 15 it gets a delta write
2030 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2031 assert_success!(o_prot.write_field_end());
2032
2033 // containing struct
2034 // since this delta > 15 it gets a full write
2035 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2036 assert_success!(o_prot.write_field_end());
2037
2038 // start contained struct
2039 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2040
2041 // contained struct
2042 // since this delta > 0 and < 15 it gets a delta write
2043 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
2044 assert_success!(o_prot.write_field_end());
2045
2046 // contained struct
2047 // since the delta is > 0 and < 15 it gets a delta write
2048 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
2049 assert_success!(o_prot.write_field_end());
2050
2051 // end contained struct
2052 assert_success!(o_prot.write_field_stop());
2053 assert_success!(o_prot.write_struct_end());
2054
2055 // end containing struct
2056 assert_success!(o_prot.write_field_stop());
2057 assert_success!(o_prot.write_struct_end());
2058
Allen George7ddbcc02020-11-08 09:51:19 -05002059 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002060 let expected: [u8; 7] = [
2061 0x16, /* field delta (1) | field type */
2062 0x08, /* field type */
2063 0x2A, /* zig-zag varint field id */
2064 0x77, /* field delta(7) | field type */
2065 0x33, /* field delta (3) | field type */
2066 0x00, /* field stop - contained */
2067 0x00 /* field stop - containing */,
2068 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002069
Allen George0e22c362017-01-30 07:15:00 -05002070 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002071 }
2072
Allen George7ddbcc02020-11-08 09:51:19 -05002073 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002074 #[test]
2075 fn must_round_trip_nested_structs_2() {
Allen George0e22c362017-01-30 07:15:00 -05002076 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002077
2078 // start containing struct
2079 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2080
2081 // containing struct
2082 // since the delta is > 0 and < 15 it gets a delta write
2083 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2084 assert_success!(o_prot.write_field_begin(&field_ident_1));
2085 assert_success!(o_prot.write_field_end());
2086
2087 // containing struct
2088 // since this delta > 15 it gets a full write
2089 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2090 assert_success!(o_prot.write_field_begin(&field_ident_2));
2091 assert_success!(o_prot.write_field_end());
2092
2093 // start contained struct
2094 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2095
2096 // contained struct
2097 // since this delta > 0 and < 15 it gets a delta write
2098 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
2099 assert_success!(o_prot.write_field_begin(&field_ident_3));
2100 assert_success!(o_prot.write_field_end());
2101
2102 // contained struct
2103 // since the delta is > 0 and < 15 it gets a delta write
2104 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
2105 assert_success!(o_prot.write_field_begin(&field_ident_4));
2106 assert_success!(o_prot.write_field_end());
2107
2108 // end contained struct
2109 assert_success!(o_prot.write_field_stop());
2110 assert_success!(o_prot.write_struct_end());
2111
2112 // end containing struct
2113 assert_success!(o_prot.write_field_stop());
2114 assert_success!(o_prot.write_struct_end());
2115
Allen George0e22c362017-01-30 07:15:00 -05002116 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002117
2118 // read containing struct back
2119 assert_success!(i_prot.read_struct_begin());
2120
2121 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002122 assert_eq!(
2123 read_ident_1,
2124 TFieldIdentifier {
2125 name: None,
2126 ..field_ident_1
2127 }
2128 );
Allen George8b96bfb2016-11-02 08:01:08 -04002129 assert_success!(i_prot.read_field_end());
2130
2131 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002132 assert_eq!(
2133 read_ident_2,
2134 TFieldIdentifier {
2135 name: None,
2136 ..field_ident_2
2137 }
2138 );
Allen George8b96bfb2016-11-02 08:01:08 -04002139 assert_success!(i_prot.read_field_end());
2140
2141 // read contained struct back
2142 assert_success!(i_prot.read_struct_begin());
2143
2144 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002145 assert_eq!(
2146 read_ident_3,
2147 TFieldIdentifier {
2148 name: None,
2149 ..field_ident_3
2150 }
2151 );
Allen George8b96bfb2016-11-02 08:01:08 -04002152 assert_success!(i_prot.read_field_end());
2153
2154 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002155 assert_eq!(
2156 read_ident_4,
2157 TFieldIdentifier {
2158 name: None,
2159 ..field_ident_4
2160 }
2161 );
Allen George8b96bfb2016-11-02 08:01:08 -04002162 assert_success!(i_prot.read_field_end());
2163
2164 // end contained struct
2165 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002166 assert_eq!(
2167 read_ident_6,
2168 TFieldIdentifier {
2169 name: None,
2170 field_type: TType::Stop,
2171 id: None,
2172 }
2173 );
Allen George8b96bfb2016-11-02 08:01:08 -04002174 assert_success!(i_prot.read_struct_end());
2175
2176 // end containing struct
2177 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002178 assert_eq!(
2179 read_ident_7,
2180 TFieldIdentifier {
2181 name: None,
2182 field_type: TType::Stop,
2183 id: None,
2184 }
2185 );
Allen George8b96bfb2016-11-02 08:01:08 -04002186 assert_success!(i_prot.read_struct_end());
2187 }
2188
2189 #[test]
2190 fn must_write_nested_structs_3() {
2191 // last field of the containing struct is a full write
2192 // first field of the the contained struct is a full write
2193
Allen George0e22c362017-01-30 07:15:00 -05002194 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002195
2196 // start containing struct
2197 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2198
2199 // containing struct
2200 // since the delta is > 0 and < 15 it gets a delta write
2201 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2202 assert_success!(o_prot.write_field_end());
2203
2204 // containing struct
2205 // since this delta > 15 it gets a full write
2206 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2207 assert_success!(o_prot.write_field_end());
2208
2209 // start contained struct
2210 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2211
2212 // contained struct
2213 // since this delta > 15 it gets a full write
2214 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
2215 assert_success!(o_prot.write_field_end());
2216
2217 // contained struct
2218 // since the delta is > 0 and < 15 it gets a delta write
2219 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
2220 assert_success!(o_prot.write_field_end());
2221
2222 // end contained struct
2223 assert_success!(o_prot.write_field_stop());
2224 assert_success!(o_prot.write_struct_end());
2225
2226 // end containing struct
2227 assert_success!(o_prot.write_field_stop());
2228 assert_success!(o_prot.write_struct_end());
2229
Allen George7ddbcc02020-11-08 09:51:19 -05002230 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002231 let expected: [u8; 8] = [
2232 0x16, /* field delta (1) | field type */
2233 0x08, /* field type */
2234 0x2A, /* zig-zag varint field id */
2235 0x07, /* field type */
2236 0x2A, /* zig-zag varint field id */
2237 0x63, /* field delta (6) | field type */
2238 0x00, /* field stop - contained */
2239 0x00 /* field stop - containing */,
2240 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002241
Allen George0e22c362017-01-30 07:15:00 -05002242 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002243 }
2244
Allen George7ddbcc02020-11-08 09:51:19 -05002245 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002246 #[test]
2247 fn must_round_trip_nested_structs_3() {
2248 // last field of the containing struct is a full write
2249 // first field of the the contained struct is a full write
2250
Allen George0e22c362017-01-30 07:15:00 -05002251 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002252
2253 // start containing struct
2254 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2255
2256 // containing struct
2257 // since the delta is > 0 and < 15 it gets a delta write
2258 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2259 assert_success!(o_prot.write_field_begin(&field_ident_1));
2260 assert_success!(o_prot.write_field_end());
2261
2262 // containing struct
2263 // since this delta > 15 it gets a full write
2264 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2265 assert_success!(o_prot.write_field_begin(&field_ident_2));
2266 assert_success!(o_prot.write_field_end());
2267
2268 // start contained struct
2269 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2270
2271 // contained struct
2272 // since this delta > 15 it gets a full write
2273 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
2274 assert_success!(o_prot.write_field_begin(&field_ident_3));
2275 assert_success!(o_prot.write_field_end());
2276
2277 // contained struct
2278 // since the delta is > 0 and < 15 it gets a delta write
2279 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2280 assert_success!(o_prot.write_field_begin(&field_ident_4));
2281 assert_success!(o_prot.write_field_end());
2282
2283 // end contained struct
2284 assert_success!(o_prot.write_field_stop());
2285 assert_success!(o_prot.write_struct_end());
2286
2287 // end containing struct
2288 assert_success!(o_prot.write_field_stop());
2289 assert_success!(o_prot.write_struct_end());
2290
Allen George0e22c362017-01-30 07:15:00 -05002291 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002292
2293 // read containing struct back
2294 assert_success!(i_prot.read_struct_begin());
2295
2296 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002297 assert_eq!(
2298 read_ident_1,
2299 TFieldIdentifier {
2300 name: None,
2301 ..field_ident_1
2302 }
2303 );
Allen George8b96bfb2016-11-02 08:01:08 -04002304 assert_success!(i_prot.read_field_end());
2305
2306 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002307 assert_eq!(
2308 read_ident_2,
2309 TFieldIdentifier {
2310 name: None,
2311 ..field_ident_2
2312 }
2313 );
Allen George8b96bfb2016-11-02 08:01:08 -04002314 assert_success!(i_prot.read_field_end());
2315
2316 // read contained struct back
2317 assert_success!(i_prot.read_struct_begin());
2318
2319 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002320 assert_eq!(
2321 read_ident_3,
2322 TFieldIdentifier {
2323 name: None,
2324 ..field_ident_3
2325 }
2326 );
Allen George8b96bfb2016-11-02 08:01:08 -04002327 assert_success!(i_prot.read_field_end());
2328
2329 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002330 assert_eq!(
2331 read_ident_4,
2332 TFieldIdentifier {
2333 name: None,
2334 ..field_ident_4
2335 }
2336 );
Allen George8b96bfb2016-11-02 08:01:08 -04002337 assert_success!(i_prot.read_field_end());
2338
2339 // end contained struct
2340 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002341 assert_eq!(
2342 read_ident_6,
2343 TFieldIdentifier {
2344 name: None,
2345 field_type: TType::Stop,
2346 id: None,
2347 }
2348 );
Allen George8b96bfb2016-11-02 08:01:08 -04002349 assert_success!(i_prot.read_struct_end());
2350
2351 // end containing struct
2352 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002353 assert_eq!(
2354 read_ident_7,
2355 TFieldIdentifier {
2356 name: None,
2357 field_type: TType::Stop,
2358 id: None,
2359 }
2360 );
Allen George8b96bfb2016-11-02 08:01:08 -04002361 assert_success!(i_prot.read_struct_end());
2362 }
2363
2364 #[test]
2365 fn must_write_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002366 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002367
2368 // no bytes should be written however
2369 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2370
2371 // write three fields with field ids that cannot be encoded as deltas
2372
2373 // since the delta is > 0 and < 16 it gets a delta write
2374 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2375 assert_success!(o_prot.write_bool(true));
2376 assert_success!(o_prot.write_field_end());
2377
2378 // since this delta > 0 and < 15 it gets a delta write
2379 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
2380 assert_success!(o_prot.write_bool(false));
2381 assert_success!(o_prot.write_field_end());
2382
2383 // since this delta > 15 it gets a full write
2384 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
2385 assert_success!(o_prot.write_bool(true));
2386 assert_success!(o_prot.write_field_end());
2387
2388 // since this delta > 15 it gets a full write
2389 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
2390 assert_success!(o_prot.write_bool(false));
2391 assert_success!(o_prot.write_field_end());
2392
2393 // now, finish the struct off
2394 assert_success!(o_prot.write_field_stop());
2395 assert_success!(o_prot.write_struct_end());
2396
Allen George7ddbcc02020-11-08 09:51:19 -05002397 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002398 let expected: [u8; 7] = [
2399 0x11, /* field delta (1) | true */
2400 0x82, /* field delta (8) | false */
2401 0x01, /* true */
2402 0x34, /* field id */
2403 0x02, /* false */
2404 0x5A, /* field id */
2405 0x00 /* stop field */,
2406 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002407
Allen George0e22c362017-01-30 07:15:00 -05002408 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002409 }
2410
Allen George7ddbcc02020-11-08 09:51:19 -05002411 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002412 #[test]
2413 fn must_round_trip_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002414 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002415
2416 // no bytes should be written however
2417 let struct_ident = TStructIdentifier::new("foo");
2418 assert_success!(o_prot.write_struct_begin(&struct_ident));
2419
2420 // write two fields
2421
2422 // since the delta is > 0 and < 16 it gets a delta write
2423 let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
2424 assert_success!(o_prot.write_field_begin(&field_ident_1));
2425 assert_success!(o_prot.write_bool(true));
2426 assert_success!(o_prot.write_field_end());
2427
2428 // since this delta > 0 and < 15 it gets a delta write
2429 let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
2430 assert_success!(o_prot.write_field_begin(&field_ident_2));
2431 assert_success!(o_prot.write_bool(false));
2432 assert_success!(o_prot.write_field_end());
2433
2434 // since this delta > 15 it gets a full write
2435 let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
2436 assert_success!(o_prot.write_field_begin(&field_ident_3));
2437 assert_success!(o_prot.write_bool(true));
2438 assert_success!(o_prot.write_field_end());
2439
2440 // since this delta > 15 it gets a full write
2441 let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
2442 assert_success!(o_prot.write_field_begin(&field_ident_4));
2443 assert_success!(o_prot.write_bool(false));
2444 assert_success!(o_prot.write_field_end());
2445
2446 // now, finish the struct off
2447 assert_success!(o_prot.write_field_stop());
2448 assert_success!(o_prot.write_struct_end());
2449
Allen George0e22c362017-01-30 07:15:00 -05002450 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002451
2452 // read the struct back
2453 assert_success!(i_prot.read_struct_begin());
2454
2455 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002456 assert_eq!(
2457 read_ident_1,
2458 TFieldIdentifier {
2459 name: None,
2460 ..field_ident_1
2461 }
2462 );
Allen George8b96bfb2016-11-02 08:01:08 -04002463 let read_value_1 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002464 assert!(read_value_1);
Allen George8b96bfb2016-11-02 08:01:08 -04002465 assert_success!(i_prot.read_field_end());
2466
2467 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002468 assert_eq!(
2469 read_ident_2,
2470 TFieldIdentifier {
2471 name: None,
2472 ..field_ident_2
2473 }
2474 );
Allen George8b96bfb2016-11-02 08:01:08 -04002475 let read_value_2 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002476 assert!(!read_value_2);
Allen George8b96bfb2016-11-02 08:01:08 -04002477 assert_success!(i_prot.read_field_end());
2478
2479 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002480 assert_eq!(
2481 read_ident_3,
2482 TFieldIdentifier {
2483 name: None,
2484 ..field_ident_3
2485 }
2486 );
Allen George8b96bfb2016-11-02 08:01:08 -04002487 let read_value_3 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002488 assert!(read_value_3);
Allen George8b96bfb2016-11-02 08:01:08 -04002489 assert_success!(i_prot.read_field_end());
2490
2491 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002492 assert_eq!(
2493 read_ident_4,
2494 TFieldIdentifier {
2495 name: None,
2496 ..field_ident_4
2497 }
2498 );
Allen George8b96bfb2016-11-02 08:01:08 -04002499 let read_value_4 = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002500 assert!(!read_value_4);
Allen George8b96bfb2016-11-02 08:01:08 -04002501 assert_success!(i_prot.read_field_end());
2502
2503 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002504 assert_eq!(
2505 read_ident_5,
2506 TFieldIdentifier {
2507 name: None,
2508 field_type: TType::Stop,
2509 id: None,
2510 }
2511 );
Allen George8b96bfb2016-11-02 08:01:08 -04002512
2513 assert_success!(i_prot.read_struct_end());
2514 }
2515
2516 #[test]
2517 #[should_panic]
2518 fn must_fail_if_write_field_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002519 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002520 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2521 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2522 o_prot.write_field_end().unwrap();
2523 }
2524
2525 #[test]
2526 #[should_panic]
2527 fn must_fail_if_write_stop_field_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002528 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002529 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2530 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2531 o_prot.write_field_stop().unwrap();
2532 }
2533
2534 #[test]
2535 #[should_panic]
2536 fn must_fail_if_write_struct_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002537 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002538 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2539 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2540 o_prot.write_struct_end().unwrap();
2541 }
2542
2543 #[test]
2544 #[should_panic]
2545 fn must_fail_if_write_struct_end_without_any_fields() {
Allen George0e22c362017-01-30 07:15:00 -05002546 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002547 o_prot.write_struct_end().unwrap();
2548 }
2549
2550 #[test]
2551 fn must_write_field_end() {
2552 assert_no_write(|o| o.write_field_end());
2553 }
2554
2555 #[test]
2556 fn must_write_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002557 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002558
2559 assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
2560
2561 let expected: [u8; 1] = [0x46 /* size | elem_type */];
2562
Allen George0e22c362017-01-30 07:15:00 -05002563 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002564 }
2565
2566 #[test]
2567 fn must_round_trip_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002568 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002569
2570 let ident = TListIdentifier::new(TType::I08, 10);
2571
2572 assert_success!(o_prot.write_list_begin(&ident));
2573
Allen George0e22c362017-01-30 07:15:00 -05002574 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002575
2576 let res = assert_success!(i_prot.read_list_begin());
2577 assert_eq!(&res, &ident);
2578 }
2579
2580 #[test]
2581 fn must_write_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002582 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002583
2584 let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
2585 assert!(res.is_ok());
2586
Allen George0e22c362017-01-30 07:15:00 -05002587 let expected: [u8; 3] = [
2588 0xF9, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002589 0x8F, 0x4E, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002590 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002591
Allen George0e22c362017-01-30 07:15:00 -05002592 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002593 }
2594
2595 #[test]
2596 fn must_round_trip_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002597 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002598
2599 let ident = TListIdentifier::new(TType::Set, 47381);
2600
2601 assert_success!(o_prot.write_list_begin(&ident));
2602
Allen George0e22c362017-01-30 07:15:00 -05002603 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002604
2605 let res = assert_success!(i_prot.read_list_begin());
2606 assert_eq!(&res, &ident);
2607 }
2608
2609 #[test]
2610 fn must_write_list_end() {
2611 assert_no_write(|o| o.write_list_end());
2612 }
2613
2614 #[test]
2615 fn must_write_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002616 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002617
2618 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
2619
2620 let expected: [u8; 1] = [0x2C /* size | elem_type */];
2621
Allen George0e22c362017-01-30 07:15:00 -05002622 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002623 }
2624
2625 #[test]
2626 fn must_round_trip_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002627 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002628
2629 let ident = TSetIdentifier::new(TType::I16, 7);
2630
2631 assert_success!(o_prot.write_set_begin(&ident));
2632
Allen George0e22c362017-01-30 07:15:00 -05002633 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002634
2635 let res = assert_success!(i_prot.read_set_begin());
2636 assert_eq!(&res, &ident);
2637 }
2638
2639 #[test]
2640 fn must_write_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002641 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002642
2643 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
2644
Allen George0e22c362017-01-30 07:15:00 -05002645 let expected: [u8; 4] = [
2646 0xF7, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002647 0xD3, 0xBA, 0x01, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002648 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002649
Allen George0e22c362017-01-30 07:15:00 -05002650 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002651 }
2652
2653 #[test]
2654 fn must_round_trip_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002655 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002656
Allen George7ddbcc02020-11-08 09:51:19 -05002657 let ident = TSetIdentifier::new(TType::Map, 3_928_429);
Allen George8b96bfb2016-11-02 08:01:08 -04002658
2659 assert_success!(o_prot.write_set_begin(&ident));
2660
Allen George0e22c362017-01-30 07:15:00 -05002661 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002662
2663 let res = assert_success!(i_prot.read_set_begin());
2664 assert_eq!(&res, &ident);
2665 }
2666
2667 #[test]
2668 fn must_write_set_end() {
2669 assert_no_write(|o| o.write_set_end());
2670 }
2671
2672 #[test]
2673 fn must_write_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002674 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002675
2676 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
2677
2678 let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything
2679
Allen George0e22c362017-01-30 07:15:00 -05002680 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002681 }
2682
2683 #[test]
2684 fn must_read_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002685 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002686
2687 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
2688
Allen George0e22c362017-01-30 07:15:00 -05002689 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002690
2691 let res = assert_success!(i_prot.read_map_begin());
Allen George0e22c362017-01-30 07:15:00 -05002692 assert_eq!(
2693 &res,
2694 &TMapIdentifier {
Allen Georgeef7a1892018-12-16 18:01:37 -05002695 key_type: None,
2696 value_type: None,
2697 size: 0,
2698 }
Allen George0e22c362017-01-30 07:15:00 -05002699 );
Allen George8b96bfb2016-11-02 08:01:08 -04002700 }
2701
2702 #[test]
2703 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002704 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002705
Allen Georgeef7a1892018-12-16 18:01:37 -05002706 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
2707 TType::Double,
2708 TType::String,
2709 238
2710 )));
Allen George8b96bfb2016-11-02 08:01:08 -04002711
Allen George0e22c362017-01-30 07:15:00 -05002712 let expected: [u8; 3] = [
Allen Georgeef7a1892018-12-16 18:01:37 -05002713 0xEE, 0x01, /* size as varint */
2714 0x78, /* key type | val type */
Allen George0e22c362017-01-30 07:15:00 -05002715 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002716
Allen George0e22c362017-01-30 07:15:00 -05002717 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002718 }
2719
2720 #[test]
2721 fn must_round_trip_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002722 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002723
Allen George7ddbcc02020-11-08 09:51:19 -05002724 let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349);
Allen George8b96bfb2016-11-02 08:01:08 -04002725
2726 assert_success!(o_prot.write_map_begin(&ident));
2727
Allen George0e22c362017-01-30 07:15:00 -05002728 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002729
2730 let res = assert_success!(i_prot.read_map_begin());
2731 assert_eq!(&res, &ident);
2732 }
2733
2734 #[test]
2735 fn must_write_map_end() {
2736 assert_no_write(|o| o.write_map_end());
2737 }
2738
2739 #[test]
2740 fn must_write_map_with_bool_key_and_value() {
Allen George0e22c362017-01-30 07:15:00 -05002741 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002742
2743 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
2744 assert_success!(o_prot.write_bool(true));
2745 assert_success!(o_prot.write_bool(false));
2746 assert_success!(o_prot.write_map_end());
2747
Allen George0e22c362017-01-30 07:15:00 -05002748 let expected: [u8; 4] = [
2749 0x01, /* size as varint */
2750 0x11, /* key type | val type */
2751 0x01, /* key: true */
Allen Georgeef7a1892018-12-16 18:01:37 -05002752 0x02, /* val: false */
Allen George0e22c362017-01-30 07:15:00 -05002753 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002754
Allen George0e22c362017-01-30 07:15:00 -05002755 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002756 }
2757
2758 #[test]
2759 fn must_round_trip_map_with_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002760 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002761
2762 let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
2763 assert_success!(o_prot.write_map_begin(&map_ident));
2764 assert_success!(o_prot.write_bool(true));
2765 assert_success!(o_prot.write_bool(false));
2766 assert_success!(o_prot.write_bool(false));
2767 assert_success!(o_prot.write_bool(true));
2768 assert_success!(o_prot.write_map_end());
2769
Allen George0e22c362017-01-30 07:15:00 -05002770 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002771
2772 // map header
2773 let rcvd_ident = assert_success!(i_prot.read_map_begin());
2774 assert_eq!(&rcvd_ident, &map_ident);
2775 // key 1
2776 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002777 assert!(b);
Allen George8b96bfb2016-11-02 08:01:08 -04002778 // val 1
2779 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002780 assert!(!b);
Allen George8b96bfb2016-11-02 08:01:08 -04002781 // key 2
2782 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002783 assert!(!b);
Allen George8b96bfb2016-11-02 08:01:08 -04002784 // val 2
2785 let b = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +08002786 assert!(b);
Allen George8b96bfb2016-11-02 08:01:08 -04002787 // map end
2788 assert_success!(i_prot.read_map_end());
2789 }
2790
2791 #[test]
2792 fn must_read_map_end() {
Allen George0e22c362017-01-30 07:15:00 -05002793 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002794 assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
2795 }
2796
Allen Georgeef7a1892018-12-16 18:01:37 -05002797 fn test_objects() -> (
2798 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2799 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2800 ) {
Allen George0e22c362017-01-30 07:15:00 -05002801 let mem = TBufferChannel::with_capacity(80, 80);
Allen George8b96bfb2016-11-02 08:01:08 -04002802
Allen George0e22c362017-01-30 07:15:00 -05002803 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -04002804
Allen George0e22c362017-01-30 07:15:00 -05002805 let i_prot = TCompactInputProtocol::new(r_mem);
2806 let o_prot = TCompactOutputProtocol::new(w_mem);
Allen George8b96bfb2016-11-02 08:01:08 -04002807
Allen George0e22c362017-01-30 07:15:00 -05002808 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -04002809 }
2810
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002811 #[test]
2812 fn must_read_write_double() {
2813 let (mut i_prot, mut o_prot) = test_objects();
2814
Allen George7ddbcc02020-11-08 09:51:19 -05002815 #[allow(clippy::approx_constant)]
2816 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002817 o_prot.write_double(double).unwrap();
2818 copy_write_buffer_to_read_buffer!(o_prot);
2819
Allen George7ddbcc02020-11-08 09:51:19 -05002820 let read_double = i_prot.read_double().unwrap();
2821 assert!(read_double - double < std::f64::EPSILON);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002822 }
2823
2824 #[test]
2825 fn must_encode_double_as_other_langs() {
2826 let (_, mut o_prot) = test_objects();
2827 let expected = [24, 45, 68, 84, 251, 33, 9, 64];
2828
Allen George7ddbcc02020-11-08 09:51:19 -05002829 #[allow(clippy::approx_constant)]
2830 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002831 o_prot.write_double(double).unwrap();
2832
2833 assert_eq_written_bytes!(o_prot, expected);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002834 }
2835
Allen George0e22c362017-01-30 07:15:00 -05002836 fn assert_no_write<F>(mut write_fn: F)
2837 where
Allen Georgeb0d14132020-03-29 11:48:55 -04002838 F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> crate::Result<()>,
Allen George0e22c362017-01-30 07:15:00 -05002839 {
2840 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002841 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -05002842 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -04002843 }
2844}