blob: 87cfbfc46ed520683c96e332394ed1779ffdcd06 [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
Allen Georgeb0d14132020-03-29 11:48:55 -0400255 fn read_string(&mut self) -> crate::Result<String> {
Allen George8b96bfb2016-11-02 08:01:08 -0400256 let bytes = self.read_bytes()?;
257 String::from_utf8(bytes).map_err(From::from)
258 }
259
Allen Georgeb0d14132020-03-29 11:48:55 -0400260 fn read_list_begin(&mut self) -> crate::Result<TListIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400261 let (element_type, element_count) = self.read_list_set_begin()?;
262 Ok(TListIdentifier::new(element_type, element_count))
263 }
264
Allen Georgeb0d14132020-03-29 11:48:55 -0400265 fn read_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400266 Ok(())
267 }
268
Allen Georgeb0d14132020-03-29 11:48:55 -0400269 fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400270 let (element_type, element_count) = self.read_list_set_begin()?;
271 Ok(TSetIdentifier::new(element_type, element_count))
272 }
273
Allen Georgeb0d14132020-03-29 11:48:55 -0400274 fn read_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400275 Ok(())
276 }
277
Allen Georgeb0d14132020-03-29 11:48:55 -0400278 fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier> {
Allen George0e22c362017-01-30 07:15:00 -0500279 let element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400280 if element_count == 0 {
281 Ok(TMapIdentifier::new(None, None, 0))
282 } else {
283 let type_header = self.read_byte()?;
284 let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
285 let val_type = collection_u8_to_type(type_header & 0x0F)?;
286 Ok(TMapIdentifier::new(key_type, val_type, element_count))
287 }
288 }
289
Allen Georgeb0d14132020-03-29 11:48:55 -0400290 fn read_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400291 Ok(())
292 }
293
294 // utility
295 //
296
Allen Georgeb0d14132020-03-29 11:48:55 -0400297 fn read_byte(&mut self) -> crate::Result<u8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400298 let mut buf = [0u8; 1];
Allen George0e22c362017-01-30 07:15:00 -0500299 self.transport
300 .read_exact(&mut buf)
301 .map_err(From::from)
302 .map(|_| buf[0])
Allen George8b96bfb2016-11-02 08:01:08 -0400303 }
304}
305
Vadim Chekand3355af2018-01-05 23:12:47 -0500306impl<T> io::Seek for TCompactInputProtocol<T>
307where
308 T: io::Seek + TReadTransport,
309{
310 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
311 self.transport.seek(pos)
312 }
313}
314
Allen George8b96bfb2016-11-02 08:01:08 -0400315/// Factory for creating instances of `TCompactInputProtocol`.
316#[derive(Default)]
317pub struct TCompactInputProtocolFactory;
318
319impl TCompactInputProtocolFactory {
320 /// Create a `TCompactInputProtocolFactory`.
321 pub fn new() -> TCompactInputProtocolFactory {
322 TCompactInputProtocolFactory {}
323 }
324}
325
326impl TInputProtocolFactory for TCompactInputProtocolFactory {
Danny Browning77d96c12019-08-21 13:41:07 -0600327 fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500328 Box::new(TCompactInputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400329 }
330}
331
332/// Write messages using the Thrift compact protocol.
333///
334/// # Examples
335///
336/// Create and use a `TCompactOutputProtocol`.
337///
338/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -0400339/// use thrift::protocol::{TCompactOutputProtocol, TOutputProtocol};
Allen George0e22c362017-01-30 07:15:00 -0500340/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -0400341///
Allen George0e22c362017-01-30 07:15:00 -0500342/// let mut channel = TTcpChannel::new();
343/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400344///
Allen George0e22c362017-01-30 07:15:00 -0500345/// let mut protocol = TCompactOutputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -0400346///
Allen George0e22c362017-01-30 07:15:00 -0500347/// protocol.write_bool(true).unwrap();
348/// protocol.write_string("test_string").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400349/// ```
Allen George0e22c362017-01-30 07:15:00 -0500350#[derive(Debug)]
351pub struct TCompactOutputProtocol<T>
352where
353 T: TWriteTransport,
354{
Allen George8b96bfb2016-11-02 08:01:08 -0400355 // Identifier of the last field serialized for a struct.
356 last_write_field_id: i16,
Allen George0e22c362017-01-30 07:15:00 -0500357 // Stack of the last written field ids (new entry added each time a nested struct is written).
Allen George8b96bfb2016-11-02 08:01:08 -0400358 write_field_id_stack: Vec<i16>,
359 // Field identifier of the boolean field to be written.
360 // Saved because boolean fields and their value are encoded in a single byte
361 pending_write_bool_field_identifier: Option<TFieldIdentifier>,
362 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -0500363 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -0400364}
365
Allen George0e22c362017-01-30 07:15:00 -0500366impl<T> TCompactOutputProtocol<T>
367where
368 T: TWriteTransport,
369{
Allen George8b96bfb2016-11-02 08:01:08 -0400370 /// Create a `TCompactOutputProtocol` that writes bytes to `transport`.
Allen George0e22c362017-01-30 07:15:00 -0500371 pub fn new(transport: T) -> TCompactOutputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -0400372 TCompactOutputProtocol {
373 last_write_field_id: 0,
374 write_field_id_stack: Vec::new(),
375 pending_write_bool_field_identifier: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500376 transport,
Allen George8b96bfb2016-11-02 08:01:08 -0400377 }
378 }
379
380 // FIXME: field_type as unconstrained u8 is bad
Allen Georgeb0d14132020-03-29 11:48:55 -0400381 fn write_field_header(&mut self, field_type: u8, field_id: i16) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400382 let field_delta = field_id - self.last_write_field_id;
383 if field_delta > 0 && field_delta < 15 {
384 self.write_byte(((field_delta as u8) << 4) | field_type)?;
385 } else {
386 self.write_byte(field_type)?;
387 self.write_i16(field_id)?;
388 }
389 self.last_write_field_id = field_id;
390 Ok(())
391 }
392
Allen George8a1743d2020-12-05 01:19:27 -0500393 fn write_list_set_begin(
394 &mut self,
395 element_type: TType,
396 element_count: i32,
397 ) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400398 let elem_identifier = collection_type_to_u8(element_type);
399 if element_count <= 14 {
400 let header = (element_count as u8) << 4 | elem_identifier;
401 self.write_byte(header)
402 } else {
403 let header = 0xF0 | elem_identifier;
404 self.write_byte(header)?;
Allen George48905102021-02-20 08:47:01 -0500405 // element count is strictly positive as per the spec, so
406 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George8b96bfb2016-11-02 08:01:08 -0400407 self.transport
Allen George8b96bfb2016-11-02 08:01:08 -0400408 .write_varint(element_count as u32)
409 .map_err(From::from)
410 .map(|_| ())
411 }
412 }
413
414 fn assert_no_pending_bool_write(&self) {
415 if let Some(ref f) = self.pending_write_bool_field_identifier {
416 panic!("pending bool field {:?} not written", f)
417 }
418 }
419}
420
Allen George0e22c362017-01-30 07:15:00 -0500421impl<T> TOutputProtocol for TCompactOutputProtocol<T>
422where
423 T: TWriteTransport,
424{
Allen Georgeb0d14132020-03-29 11:48:55 -0400425 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400426 self.write_byte(COMPACT_PROTOCOL_ID)?;
427 self.write_byte((u8::from(identifier.message_type) << 5) | COMPACT_VERSION)?;
Allen George48905102021-02-20 08:47:01 -0500428 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George55c3e4c2021-03-01 23:19:52 -0500429 self.transport
430 .write_varint(identifier.sequence_number as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400431 self.write_string(&identifier.name)?;
432 Ok(())
433 }
434
Allen Georgeb0d14132020-03-29 11:48:55 -0400435 fn write_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400436 self.assert_no_pending_bool_write();
437 Ok(())
438 }
439
Allen Georgeb0d14132020-03-29 11:48:55 -0400440 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400441 self.write_field_id_stack.push(self.last_write_field_id);
442 self.last_write_field_id = 0;
443 Ok(())
444 }
445
Allen Georgeb0d14132020-03-29 11:48:55 -0400446 fn write_struct_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400447 self.assert_no_pending_bool_write();
Allen Georgeef7a1892018-12-16 18:01:37 -0500448 self.last_write_field_id = self
449 .write_field_id_stack
Allen George0e22c362017-01-30 07:15:00 -0500450 .pop()
451 .expect("should have previous field ids");
Allen George8b96bfb2016-11-02 08:01:08 -0400452 Ok(())
453 }
454
Allen Georgeb0d14132020-03-29 11:48:55 -0400455 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400456 match identifier.field_type {
457 TType::Bool => {
458 if self.pending_write_bool_field_identifier.is_some() {
Allen George0e22c362017-01-30 07:15:00 -0500459 panic!(
460 "should not have a pending bool while writing another bool with id: \
Allen Georgeef7a1892018-12-16 18:01:37 -0500461 {:?}",
Allen George0e22c362017-01-30 07:15:00 -0500462 identifier
463 )
Allen George8b96bfb2016-11-02 08:01:08 -0400464 }
465 self.pending_write_bool_field_identifier = Some(identifier.clone());
466 Ok(())
467 }
468 _ => {
469 let field_type = type_to_u8(identifier.field_type);
Allen Georgeef7a1892018-12-16 18:01:37 -0500470 let field_id = identifier.id.expect("non-stop field should have field id");
Allen George8b96bfb2016-11-02 08:01:08 -0400471 self.write_field_header(field_type, field_id)
472 }
473 }
474 }
475
Allen Georgeb0d14132020-03-29 11:48:55 -0400476 fn write_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400477 self.assert_no_pending_bool_write();
478 Ok(())
479 }
480
Allen Georgeb0d14132020-03-29 11:48:55 -0400481 fn write_field_stop(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400482 self.assert_no_pending_bool_write();
483 self.write_byte(type_to_u8(TType::Stop))
484 }
485
Allen Georgeb0d14132020-03-29 11:48:55 -0400486 fn write_bool(&mut self, b: bool) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400487 match self.pending_write_bool_field_identifier.take() {
488 Some(pending) => {
489 let field_id = pending.id.expect("bool field should have a field id");
490 let field_type_as_u8 = if b { 0x01 } else { 0x02 };
491 self.write_field_header(field_type_as_u8, field_id)
492 }
493 None => {
494 if b {
495 self.write_byte(0x01)
496 } else {
497 self.write_byte(0x02)
498 }
499 }
500 }
501 }
502
Allen Georgeb0d14132020-03-29 11:48:55 -0400503 fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> {
Allen George48905102021-02-20 08:47:01 -0500504 // length is strictly positive as per the spec, so
505 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500506 self.transport.write_varint(b.len() as u32)?;
507 self.transport.write_all(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400508 }
509
Allen Georgeb0d14132020-03-29 11:48:55 -0400510 fn write_i8(&mut self, i: i8) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400511 self.write_byte(i as u8)
512 }
513
Allen Georgeb0d14132020-03-29 11:48:55 -0400514 fn write_i16(&mut self, i: i16) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500515 self.transport
Allen George48905102021-02-20 08:47:01 -0500516 .write_varint(i)
Allen George0e22c362017-01-30 07:15:00 -0500517 .map_err(From::from)
518 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400519 }
520
Allen Georgeb0d14132020-03-29 11:48:55 -0400521 fn write_i32(&mut self, i: i32) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500522 self.transport
523 .write_varint(i)
524 .map_err(From::from)
525 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400526 }
527
Allen Georgeb0d14132020-03-29 11:48:55 -0400528 fn write_i64(&mut self, i: i64) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500529 self.transport
530 .write_varint(i)
531 .map_err(From::from)
532 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400533 }
534
Allen Georgeb0d14132020-03-29 11:48:55 -0400535 fn write_double(&mut self, d: f64) -> crate::Result<()> {
Allen George8a1743d2020-12-05 01:19:27 -0500536 self.transport
537 .write_f64::<LittleEndian>(d)
538 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400539 }
540
Allen Georgeb0d14132020-03-29 11:48:55 -0400541 fn write_string(&mut self, s: &str) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400542 self.write_bytes(s.as_bytes())
543 }
544
Allen Georgeb0d14132020-03-29 11:48:55 -0400545 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400546 self.write_list_set_begin(identifier.element_type, identifier.size)
547 }
548
Allen Georgeb0d14132020-03-29 11:48:55 -0400549 fn write_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400550 Ok(())
551 }
552
Allen Georgeb0d14132020-03-29 11:48:55 -0400553 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> 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_set_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_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400562 if identifier.size == 0 {
563 self.write_byte(0)
564 } else {
Allen George48905102021-02-20 08:47:01 -0500565 // element count is strictly positive as per the spec, so
566 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500567 self.transport.write_varint(identifier.size as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400568
Allen George0e22c362017-01-30 07:15:00 -0500569 let key_type = identifier
570 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400571 .expect("map identifier to write should contain key type");
572 let key_type_byte = collection_type_to_u8(key_type) << 4;
573
Allen George0e22c362017-01-30 07:15:00 -0500574 let val_type = identifier
575 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400576 .expect("map identifier to write should contain value type");
577 let val_type_byte = collection_type_to_u8(val_type);
578
579 let map_type_header = key_type_byte | val_type_byte;
580 self.write_byte(map_type_header)
581 }
582 }
583
Allen Georgeb0d14132020-03-29 11:48:55 -0400584 fn write_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400585 Ok(())
586 }
587
Allen Georgeb0d14132020-03-29 11:48:55 -0400588 fn flush(&mut self) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500589 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400590 }
591
592 // utility
593 //
594
Allen Georgeb0d14132020-03-29 11:48:55 -0400595 fn write_byte(&mut self, b: u8) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500596 self.transport.write(&[b]).map_err(From::from).map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400597 }
598}
599
600/// Factory for creating instances of `TCompactOutputProtocol`.
601#[derive(Default)]
602pub struct TCompactOutputProtocolFactory;
603
604impl TCompactOutputProtocolFactory {
605 /// Create a `TCompactOutputProtocolFactory`.
606 pub fn new() -> TCompactOutputProtocolFactory {
607 TCompactOutputProtocolFactory {}
608 }
609}
610
611impl TOutputProtocolFactory for TCompactOutputProtocolFactory {
Allen George8a1743d2020-12-05 01:19:27 -0500612 fn create(
613 &self,
614 transport: Box<dyn TWriteTransport + Send>,
615 ) -> Box<dyn TOutputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500616 Box::new(TCompactOutputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400617 }
618}
619
620fn collection_type_to_u8(field_type: TType) -> u8 {
621 match field_type {
622 TType::Bool => 0x01,
623 f => type_to_u8(f),
624 }
625}
626
627fn type_to_u8(field_type: TType) -> u8 {
628 match field_type {
629 TType::Stop => 0x00,
630 TType::I08 => 0x03, // equivalent to TType::Byte
631 TType::I16 => 0x04,
632 TType::I32 => 0x05,
633 TType::I64 => 0x06,
634 TType::Double => 0x07,
635 TType::String => 0x08,
636 TType::List => 0x09,
637 TType::Set => 0x0A,
638 TType::Map => 0x0B,
639 TType::Struct => 0x0C,
Allen George2b691ee2021-10-14 22:25:07 -0400640 _ => panic!("should not have attempted to convert {} to u8", field_type),
Allen George8b96bfb2016-11-02 08:01:08 -0400641 }
642}
643
Allen Georgeb0d14132020-03-29 11:48:55 -0400644fn collection_u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400645 match b {
646 0x01 => Ok(TType::Bool),
647 o => u8_to_type(o),
648 }
649}
650
Allen Georgeb0d14132020-03-29 11:48:55 -0400651fn u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400652 match b {
653 0x00 => Ok(TType::Stop),
654 0x03 => Ok(TType::I08), // equivalent to TType::Byte
655 0x04 => Ok(TType::I16),
656 0x05 => Ok(TType::I32),
657 0x06 => Ok(TType::I64),
658 0x07 => Ok(TType::Double),
659 0x08 => Ok(TType::String),
660 0x09 => Ok(TType::List),
661 0x0A => Ok(TType::Set),
662 0x0B => Ok(TType::Map),
663 0x0C => Ok(TType::Struct),
Allen Georgeb0d14132020-03-29 11:48:55 -0400664 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
665 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500666 message: format!("cannot convert {} into TType", unkn),
667 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400668 }
669}
670
671#[cfg(test)]
672mod tests {
673
Allen George8a1743d2020-12-05 01:19:27 -0500674 use std::i32;
675
Allen Georgeb0d14132020-03-29 11:48:55 -0400676 use crate::protocol::{
Allen Georgeef7a1892018-12-16 18:01:37 -0500677 TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
678 TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
679 };
Allen Georgeb0d14132020-03-29 11:48:55 -0400680 use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400681
682 use super::*;
683
684 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500685 fn must_write_message_begin_largest_maximum_positive_sequence_number() {
686 let (_, mut o_prot) = test_objects();
687
688 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
689 "bar",
690 TMessageType::Reply,
691 i32::MAX
692 )));
693
694 #[rustfmt::skip]
695 let expected: [u8; 11] = [
696 0x82, /* protocol ID */
697 0x41, /* message type | protocol version */
698 0xFF,
699 0xFF,
700 0xFF,
701 0xFF,
702 0x07, /* non-zig-zag varint sequence number */
703 0x03, /* message-name length */
704 0x62,
705 0x61,
706 0x72 /* "bar" */,
707 ];
708
709 assert_eq_written_bytes!(o_prot, expected);
710 }
711
712 #[test]
713 fn must_read_message_begin_largest_maximum_positive_sequence_number() {
714 let (mut i_prot, _) = test_objects();
715
716 #[rustfmt::skip]
717 let source_bytes: [u8; 11] = [
718 0x82, /* protocol ID */
719 0x41, /* message type | protocol version */
720 0xFF,
721 0xFF,
722 0xFF,
723 0xFF,
724 0x07, /* non-zig-zag varint sequence number */
725 0x03, /* message-name length */
726 0x62,
727 0x61,
728 0x72 /* "bar" */,
729 ];
730
731 i_prot.transport.set_readable_bytes(&source_bytes);
732
733 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MAX);
734 let res = assert_success!(i_prot.read_message_begin());
735
736 assert_eq!(&expected, &res);
737 }
738
739 #[test]
740 fn must_write_message_begin_positive_sequence_number_0() {
Allen George0e22c362017-01-30 07:15:00 -0500741 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400742
Allen Georgeef7a1892018-12-16 18:01:37 -0500743 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
744 "foo",
745 TMessageType::Call,
746 431
747 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400748
Allen George7ddbcc02020-11-08 09:51:19 -0500749 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500750 let expected: [u8; 8] = [
751 0x82, /* protocol ID */
752 0x21, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500753 0xAF,
754 0x03, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500755 0x03, /* message-name length */
756 0x66,
757 0x6F,
758 0x6F /* "foo" */,
759 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400760
Allen George0e22c362017-01-30 07:15:00 -0500761 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400762 }
763
764 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500765 fn must_read_message_begin_positive_sequence_number_0() {
766 let (mut i_prot, _) = test_objects();
767
768 #[rustfmt::skip]
769 let source_bytes: [u8; 8] = [
770 0x82, /* protocol ID */
771 0x21, /* message type | protocol version */
772 0xAF,
773 0x03, /* non-zig-zag varint sequence number */
774 0x03, /* message-name length */
775 0x66,
776 0x6F,
777 0x6F /* "foo" */,
778 ];
779
780 i_prot.transport.set_readable_bytes(&source_bytes);
781
782 let expected = TMessageIdentifier::new("foo", TMessageType::Call, 431);
783 let res = assert_success!(i_prot.read_message_begin());
784
785 assert_eq!(&expected, &res);
786 }
787
788 #[test]
789 fn must_write_message_begin_positive_sequence_number_1() {
Allen George0e22c362017-01-30 07:15:00 -0500790 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400791
Allen Georgeef7a1892018-12-16 18:01:37 -0500792 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
793 "bar",
794 TMessageType::Reply,
Allen George7ddbcc02020-11-08 09:51:19 -0500795 991_828
Allen Georgeef7a1892018-12-16 18:01:37 -0500796 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400797
Allen George7ddbcc02020-11-08 09:51:19 -0500798 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500799 let expected: [u8; 9] = [
800 0x82, /* protocol ID */
801 0x41, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500802 0xD4,
803 0xC4,
804 0x3C, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500805 0x03, /* message-name length */
806 0x62,
807 0x61,
808 0x72 /* "bar" */,
809 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400810
Allen George0e22c362017-01-30 07:15:00 -0500811 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400812 }
813
814 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500815 fn must_read_message_begin_positive_sequence_number_1() {
816 let (mut i_prot, _) = test_objects();
817
818 #[rustfmt::skip]
819 let source_bytes: [u8; 9] = [
820 0x82, /* protocol ID */
821 0x41, /* message type | protocol version */
822 0xD4,
823 0xC4,
824 0x3C, /* non-zig-zag varint sequence number */
825 0x03, /* message-name length */
826 0x62,
827 0x61,
828 0x72 /* "bar" */,
829 ];
830
831 i_prot.transport.set_readable_bytes(&source_bytes);
832
833 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 991_828);
834 let res = assert_success!(i_prot.read_message_begin());
835
836 assert_eq!(&expected, &res);
837 }
838
839 #[test]
840 fn must_write_message_begin_zero_sequence_number() {
841 let (_, mut o_prot) = test_objects();
842
843 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
844 "bar",
845 TMessageType::Reply,
846 0
847 )));
848
849 #[rustfmt::skip]
850 let expected: [u8; 7] = [
851 0x82, /* protocol ID */
852 0x41, /* message type | protocol version */
853 0x00, /* non-zig-zag varint sequence number */
854 0x03, /* message-name length */
855 0x62,
856 0x61,
857 0x72 /* "bar" */,
858 ];
859
860 assert_eq_written_bytes!(o_prot, expected);
861 }
862
863 #[test]
864 fn must_read_message_begin_zero_sequence_number() {
865 let (mut i_prot, _) = test_objects();
866
867 #[rustfmt::skip]
868 let source_bytes: [u8; 7] = [
869 0x82, /* protocol ID */
870 0x41, /* message type | protocol version */
871 0x00, /* non-zig-zag varint sequence number */
872 0x03, /* message-name length */
873 0x62,
874 0x61,
875 0x72 /* "bar" */,
876 ];
877
878 i_prot.transport.set_readable_bytes(&source_bytes);
879
880 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 0);
881 let res = assert_success!(i_prot.read_message_begin());
882
883 assert_eq!(&expected, &res);
884 }
885
886 #[test]
887 fn must_write_message_begin_largest_minimum_negative_sequence_number() {
888 let (_, mut o_prot) = test_objects();
889
890 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
891 "bar",
892 TMessageType::Reply,
893 i32::MIN
894 )));
895
896 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
897 #[rustfmt::skip]
898 let expected: [u8; 11] = [
899 0x82, /* protocol ID */
900 0x41, /* message type | protocol version */
901 0x80,
902 0x80,
903 0x80,
904 0x80,
905 0x08, /* non-zig-zag varint sequence number */
906 0x03, /* message-name length */
907 0x62,
908 0x61,
909 0x72 /* "bar" */,
910 ];
911
912 assert_eq_written_bytes!(o_prot, expected);
913 }
914
915 #[test]
916 fn must_read_message_begin_largest_minimum_negative_sequence_number() {
917 let (mut i_prot, _) = test_objects();
918
919 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
920 #[rustfmt::skip]
921 let source_bytes: [u8; 11] = [
922 0x82, /* protocol ID */
923 0x41, /* message type | protocol version */
924 0x80,
925 0x80,
926 0x80,
927 0x80,
928 0x08, /* non-zig-zag varint sequence number */
929 0x03, /* message-name length */
930 0x62,
931 0x61,
932 0x72 /* "bar" */,
933 ];
934
935 i_prot.transport.set_readable_bytes(&source_bytes);
936
937 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MIN);
938 let res = assert_success!(i_prot.read_message_begin());
939
940 assert_eq!(&expected, &res);
941 }
942
943 #[test]
944 fn must_write_message_begin_negative_sequence_number_0() {
945 let (_, mut o_prot) = test_objects();
946
947 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
948 "foo",
949 TMessageType::Call,
950 -431
951 )));
952
953 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
954 #[rustfmt::skip]
955 let expected: [u8; 11] = [
956 0x82, /* protocol ID */
957 0x21, /* message type | protocol version */
958 0xD1,
959 0xFC,
960 0xFF,
961 0xFF,
962 0x0F, /* non-zig-zag varint sequence number */
963 0x03, /* message-name length */
964 0x66,
965 0x6F,
966 0x6F /* "foo" */,
967 ];
968
969 assert_eq_written_bytes!(o_prot, expected);
970 }
971
972 #[test]
973 fn must_read_message_begin_negative_sequence_number_0() {
974 let (mut i_prot, _) = test_objects();
975
976 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
977 #[rustfmt::skip]
978 let source_bytes: [u8; 11] = [
979 0x82, /* protocol ID */
980 0x21, /* message type | protocol version */
981 0xD1,
982 0xFC,
983 0xFF,
984 0xFF,
985 0x0F, /* non-zig-zag varint sequence number */
986 0x03, /* message-name length */
987 0x66,
988 0x6F,
989 0x6F /* "foo" */,
990 ];
991
992 i_prot.transport.set_readable_bytes(&source_bytes);
993
994 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -431);
995 let res = assert_success!(i_prot.read_message_begin());
996
997 assert_eq!(&expected, &res);
998 }
999
1000 #[test]
1001 fn must_write_message_begin_negative_sequence_number_1() {
1002 let (_, mut o_prot) = test_objects();
1003
1004 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1005 "foo",
1006 TMessageType::Call,
1007 -73_184_125
1008 )));
1009
1010 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1011 #[rustfmt::skip]
1012 let expected: [u8; 11] = [
1013 0x82, /* protocol ID */
1014 0x21, /* message type | protocol version */
1015 0x83,
1016 0x99,
1017 0x8D,
1018 0xDD,
1019 0x0F, /* non-zig-zag varint sequence number */
1020 0x03, /* message-name length */
1021 0x66,
1022 0x6F,
1023 0x6F /* "foo" */,
1024 ];
1025
1026 assert_eq_written_bytes!(o_prot, expected);
1027 }
1028
1029 #[test]
1030 fn must_read_message_begin_negative_sequence_number_1() {
1031 let (mut i_prot, _) = test_objects();
1032
1033 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1034 #[rustfmt::skip]
1035 let source_bytes: [u8; 11] = [
1036 0x82, /* protocol ID */
1037 0x21, /* message type | protocol version */
1038 0x83,
1039 0x99,
1040 0x8D,
1041 0xDD,
1042 0x0F, /* non-zig-zag varint sequence number */
1043 0x03, /* message-name length */
1044 0x66,
1045 0x6F,
1046 0x6F /* "foo" */,
1047 ];
1048
1049 i_prot.transport.set_readable_bytes(&source_bytes);
1050
1051 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -73_184_125);
1052 let res = assert_success!(i_prot.read_message_begin());
1053
1054 assert_eq!(&expected, &res);
1055 }
1056
1057 #[test]
1058 fn must_write_message_begin_negative_sequence_number_2() {
1059 let (_, mut o_prot) = test_objects();
1060
1061 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1062 "foo",
1063 TMessageType::Call,
1064 -1_073_741_823
1065 )));
1066
1067 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
1068 #[rustfmt::skip]
1069 let expected: [u8; 11] = [
1070 0x82, /* protocol ID */
1071 0x21, /* message type | protocol version */
1072 0x81,
1073 0x80,
1074 0x80,
1075 0x80,
1076 0x0C, /* non-zig-zag varint sequence number */
1077 0x03, /* message-name length */
1078 0x66,
1079 0x6F,
1080 0x6F /* "foo" */,
1081 ];
1082
1083 assert_eq_written_bytes!(o_prot, expected);
1084 }
1085
1086 #[test]
1087 fn must_read_message_begin_negative_sequence_number_2() {
1088 let (mut i_prot, _) = test_objects();
1089
1090 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
Allen George55c3e4c2021-03-01 23:19:52 -05001091 #[rustfmt::skip]
Allen George8a1743d2020-12-05 01:19:27 -05001092 let source_bytes: [u8; 11] = [
1093 0x82, /* protocol ID */
1094 0x21, /* message type | protocol version */
1095 0x81,
1096 0x80,
1097 0x80,
1098 0x80,
1099 0x0C, /* non-zig-zag varint sequence number */
1100 0x03, /* message-name length */
1101 0x66,
1102 0x6F,
Allen George55c3e4c2021-03-01 23:19:52 -05001103 0x6F, /* "foo" */
Allen George8a1743d2020-12-05 01:19:27 -05001104 ];
1105
1106 i_prot.transport.set_readable_bytes(&source_bytes);
1107
1108 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -1_073_741_823);
1109 let res = assert_success!(i_prot.read_message_begin());
1110
1111 assert_eq!(&expected, &res);
1112 }
1113
1114 #[test]
Nik Claytone7917602020-03-05 11:51:15 +01001115 fn must_round_trip_upto_i64_maxvalue() {
1116 // See https://issues.apache.org/jira/browse/THRIFT-5131
1117 for i in 0..64 {
1118 let (mut i_prot, mut o_prot) = test_objects();
1119 let val: i64 = ((1u64 << i) - 1) as i64;
1120
1121 o_prot
Allen George8a1743d2020-12-05 01:19:27 -05001122 .write_field_begin(&TFieldIdentifier::new("val", TType::I64, 1))
Nik Claytone7917602020-03-05 11:51:15 +01001123 .unwrap();
1124 o_prot.write_i64(val).unwrap();
1125 o_prot.write_field_end().unwrap();
1126 o_prot.flush().unwrap();
1127
1128 copy_write_buffer_to_read_buffer!(o_prot);
1129
1130 i_prot.read_field_begin().unwrap();
1131 assert_eq!(val, i_prot.read_i64().unwrap());
1132 }
1133 }
1134
1135 #[test]
Allen George8b96bfb2016-11-02 08:01:08 -04001136 fn must_round_trip_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -05001137 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001138
Allen George7ddbcc02020-11-08 09:51:19 -05001139 let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948);
Allen George8b96bfb2016-11-02 08:01:08 -04001140
1141 assert_success!(o_prot.write_message_begin(&ident));
1142
Allen George0e22c362017-01-30 07:15:00 -05001143 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001144
1145 let res = assert_success!(i_prot.read_message_begin());
1146 assert_eq!(&res, &ident);
1147 }
1148
1149 #[test]
1150 fn must_write_message_end() {
1151 assert_no_write(|o| o.write_message_end());
1152 }
1153
1154 // NOTE: structs and fields are tested together
1155 //
1156
1157 #[test]
1158 fn must_write_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001159 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001160
1161 // no bytes should be written however
1162 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1163
1164 // write three fields with tiny field ids
1165 // since they're small the field ids will be encoded as deltas
1166
1167 // since this is the first field (and it's zero) it gets the full varint write
1168 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
1169 assert_success!(o_prot.write_field_end());
1170
1171 // since this delta > 0 and < 15 it can be encoded as a delta
1172 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
1173 assert_success!(o_prot.write_field_end());
1174
1175 // since this delta > 0 and < 15 it can be encoded as a delta
1176 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
1177 assert_success!(o_prot.write_field_end());
1178
1179 // now, finish the struct off
1180 assert_success!(o_prot.write_field_stop());
1181 assert_success!(o_prot.write_struct_end());
1182
Allen George7ddbcc02020-11-08 09:51:19 -05001183 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001184 let expected: [u8; 5] = [
1185 0x03, /* field type */
1186 0x00, /* first field id */
1187 0x44, /* field delta (4) | field type */
1188 0x59, /* field delta (5) | field type */
1189 0x00 /* field stop */,
1190 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001191
Allen George0e22c362017-01-30 07:15:00 -05001192 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001193 }
1194
1195 #[test]
1196 fn must_round_trip_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001197 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001198
1199 // no bytes should be written however
1200 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1201
1202 // write three fields with tiny field ids
1203 // since they're small the field ids will be encoded as deltas
1204
1205 // since this is the first field (and it's zero) it gets the full varint write
1206 let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
1207 assert_success!(o_prot.write_field_begin(&field_ident_1));
1208 assert_success!(o_prot.write_field_end());
1209
1210 // since this delta > 0 and < 15 it can be encoded as a delta
1211 let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
1212 assert_success!(o_prot.write_field_begin(&field_ident_2));
1213 assert_success!(o_prot.write_field_end());
1214
1215 // since this delta > 0 and < 15 it can be encoded as a delta
1216 let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
1217 assert_success!(o_prot.write_field_begin(&field_ident_3));
1218 assert_success!(o_prot.write_field_end());
1219
1220 // now, finish the struct off
1221 assert_success!(o_prot.write_field_stop());
1222 assert_success!(o_prot.write_struct_end());
1223
Allen George0e22c362017-01-30 07:15:00 -05001224 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001225
1226 // read the struct back
1227 assert_success!(i_prot.read_struct_begin());
1228
1229 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001230 assert_eq!(
1231 read_ident_1,
1232 TFieldIdentifier {
1233 name: None,
1234 ..field_ident_1
1235 }
1236 );
Allen George8b96bfb2016-11-02 08:01:08 -04001237 assert_success!(i_prot.read_field_end());
1238
1239 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001240 assert_eq!(
1241 read_ident_2,
1242 TFieldIdentifier {
1243 name: None,
1244 ..field_ident_2
1245 }
1246 );
Allen George8b96bfb2016-11-02 08:01:08 -04001247 assert_success!(i_prot.read_field_end());
1248
1249 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001250 assert_eq!(
1251 read_ident_3,
1252 TFieldIdentifier {
1253 name: None,
1254 ..field_ident_3
1255 }
1256 );
Allen George8b96bfb2016-11-02 08:01:08 -04001257 assert_success!(i_prot.read_field_end());
1258
1259 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001260 assert_eq!(
1261 read_ident_4,
1262 TFieldIdentifier {
1263 name: None,
1264 field_type: TType::Stop,
1265 id: None,
1266 }
1267 );
Allen George8b96bfb2016-11-02 08:01:08 -04001268
1269 assert_success!(i_prot.read_struct_end());
1270 }
1271
1272 #[test]
1273 fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001274 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001275
1276 // no bytes should be written however
1277 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1278
1279 // write three fields with tiny field ids
1280 // since they're small the field ids will be encoded as deltas
1281
1282 // gets a delta write
1283 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
1284 assert_success!(o_prot.write_field_end());
1285
1286 // since this delta > 0 and < 15 it can be encoded as a delta
1287 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
1288 assert_success!(o_prot.write_field_end());
1289
1290 // since this delta > 0 and < 15 it can be encoded as a delta
1291 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
1292 assert_success!(o_prot.write_field_end());
1293
1294 // now, finish the struct off
1295 assert_success!(o_prot.write_field_stop());
1296 assert_success!(o_prot.write_struct_end());
1297
Allen George7ddbcc02020-11-08 09:51:19 -05001298 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001299 let expected: [u8; 4] = [
1300 0x15, /* field delta (1) | field type */
1301 0x1A, /* field delta (1) | field type */
1302 0x48, /* field delta (4) | field type */
1303 0x00 /* field stop */,
1304 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001305
Allen George0e22c362017-01-30 07:15:00 -05001306 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001307 }
1308
1309 #[test]
1310 fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001311 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001312
1313 // no bytes should be written however
1314 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1315
1316 // write three fields with tiny field ids
1317 // since they're small the field ids will be encoded as deltas
1318
1319 // gets a delta write
1320 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
1321 assert_success!(o_prot.write_field_begin(&field_ident_1));
1322 assert_success!(o_prot.write_field_end());
1323
1324 // since this delta > 0 and < 15 it can be encoded as a delta
1325 let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
1326 assert_success!(o_prot.write_field_begin(&field_ident_2));
1327 assert_success!(o_prot.write_field_end());
1328
1329 // since this delta > 0 and < 15 it can be encoded as a delta
1330 let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
1331 assert_success!(o_prot.write_field_begin(&field_ident_3));
1332 assert_success!(o_prot.write_field_end());
1333
1334 // now, finish the struct off
1335 assert_success!(o_prot.write_field_stop());
1336 assert_success!(o_prot.write_struct_end());
1337
Allen George0e22c362017-01-30 07:15:00 -05001338 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001339
1340 // read the struct back
1341 assert_success!(i_prot.read_struct_begin());
1342
1343 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001344 assert_eq!(
1345 read_ident_1,
1346 TFieldIdentifier {
1347 name: None,
1348 ..field_ident_1
1349 }
1350 );
Allen George8b96bfb2016-11-02 08:01:08 -04001351 assert_success!(i_prot.read_field_end());
1352
1353 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001354 assert_eq!(
1355 read_ident_2,
1356 TFieldIdentifier {
1357 name: None,
1358 ..field_ident_2
1359 }
1360 );
Allen George8b96bfb2016-11-02 08:01:08 -04001361 assert_success!(i_prot.read_field_end());
1362
1363 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001364 assert_eq!(
1365 read_ident_3,
1366 TFieldIdentifier {
1367 name: None,
1368 ..field_ident_3
1369 }
1370 );
Allen George8b96bfb2016-11-02 08:01:08 -04001371 assert_success!(i_prot.read_field_end());
1372
1373 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001374 assert_eq!(
1375 read_ident_4,
1376 TFieldIdentifier {
1377 name: None,
1378 field_type: TType::Stop,
1379 id: None,
1380 }
1381 );
Allen George8b96bfb2016-11-02 08:01:08 -04001382
1383 assert_success!(i_prot.read_struct_end());
1384 }
1385
1386 #[test]
1387 fn must_write_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001388 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001389
1390 // no bytes should be written however
1391 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1392
1393 // write three fields with field ids that cannot be encoded as deltas
1394
1395 // since this is the first field (and it's zero) it gets the full varint write
1396 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
1397 assert_success!(o_prot.write_field_end());
1398
1399 // since this delta is > 15 it is encoded as a zig-zag varint
1400 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
1401 assert_success!(o_prot.write_field_end());
1402
1403 // since this delta is > 15 it is encoded as a zig-zag varint
1404 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
1405 assert_success!(o_prot.write_field_end());
1406
1407 // now, finish the struct off
1408 assert_success!(o_prot.write_field_stop());
1409 assert_success!(o_prot.write_struct_end());
1410
Allen George7ddbcc02020-11-08 09:51:19 -05001411 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001412 let expected: [u8; 8] = [
1413 0x05, /* field type */
1414 0x00, /* first field id */
1415 0x06, /* field type */
1416 0x20, /* zig-zag varint field id */
1417 0x0A, /* field type */
1418 0xC6,
1419 0x01, /* zig-zag varint field id */
1420 0x00 /* field stop */,
1421 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001422
Allen George0e22c362017-01-30 07:15:00 -05001423 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001424 }
1425
1426 #[test]
1427 fn must_round_trip_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001428 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001429
1430 // no bytes should be written however
1431 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1432
1433 // write three fields with field ids that cannot be encoded as deltas
1434
1435 // since this is the first field (and it's zero) it gets the full varint write
1436 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
1437 assert_success!(o_prot.write_field_begin(&field_ident_1));
1438 assert_success!(o_prot.write_field_end());
1439
1440 // since this delta is > 15 it is encoded as a zig-zag varint
1441 let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
1442 assert_success!(o_prot.write_field_begin(&field_ident_2));
1443 assert_success!(o_prot.write_field_end());
1444
1445 // since this delta is > 15 it is encoded as a zig-zag varint
1446 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
1447 assert_success!(o_prot.write_field_begin(&field_ident_3));
1448 assert_success!(o_prot.write_field_end());
1449
1450 // now, finish the struct off
1451 assert_success!(o_prot.write_field_stop());
1452 assert_success!(o_prot.write_struct_end());
1453
Allen George0e22c362017-01-30 07:15:00 -05001454 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001455
1456 // read the struct back
1457 assert_success!(i_prot.read_struct_begin());
1458
1459 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001460 assert_eq!(
1461 read_ident_1,
1462 TFieldIdentifier {
1463 name: None,
1464 ..field_ident_1
1465 }
1466 );
Allen George8b96bfb2016-11-02 08:01:08 -04001467 assert_success!(i_prot.read_field_end());
1468
1469 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001470 assert_eq!(
1471 read_ident_2,
1472 TFieldIdentifier {
1473 name: None,
1474 ..field_ident_2
1475 }
1476 );
Allen George8b96bfb2016-11-02 08:01:08 -04001477 assert_success!(i_prot.read_field_end());
1478
1479 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001480 assert_eq!(
1481 read_ident_3,
1482 TFieldIdentifier {
1483 name: None,
1484 ..field_ident_3
1485 }
1486 );
Allen George8b96bfb2016-11-02 08:01:08 -04001487 assert_success!(i_prot.read_field_end());
1488
1489 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001490 assert_eq!(
1491 read_ident_4,
1492 TFieldIdentifier {
1493 name: None,
1494 field_type: TType::Stop,
1495 id: None,
1496 }
1497 );
Allen George8b96bfb2016-11-02 08:01:08 -04001498
1499 assert_success!(i_prot.read_struct_end());
1500 }
1501
1502 #[test]
1503 fn must_write_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001504 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001505
1506 // no bytes should be written however
1507 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1508
1509 // write three fields with field ids that cannot be encoded as deltas
1510
1511 // since the delta is > 0 and < 15 it gets a delta write
1512 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1513 assert_success!(o_prot.write_field_end());
1514
1515 // since this delta > 0 and < 15 it gets a delta write
1516 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1517 assert_success!(o_prot.write_field_end());
1518
1519 // since this delta is > 15 it is encoded as a zig-zag varint
1520 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
1521 assert_success!(o_prot.write_field_end());
1522
1523 // since this delta is > 15 it is encoded as a zig-zag varint
1524 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
1525 assert_success!(o_prot.write_field_end());
1526
1527 // since this is only 3 up from the previous it is recorded as a delta
1528 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
1529 assert_success!(o_prot.write_field_end());
1530
1531 // now, finish the struct off
1532 assert_success!(o_prot.write_field_stop());
1533 assert_success!(o_prot.write_struct_end());
1534
Allen George7ddbcc02020-11-08 09:51:19 -05001535 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001536 let expected: [u8; 10] = [
1537 0x16, /* field delta (1) | field type */
1538 0x85, /* field delta (8) | field type */
1539 0x0A, /* field type */
1540 0xD0,
1541 0x0F, /* zig-zag varint field id */
1542 0x0A, /* field type */
1543 0xA2,
1544 0x1F, /* zig-zag varint field id */
1545 0x3A, /* field delta (3) | field type */
1546 0x00 /* field stop */,
1547 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001548
Allen George0e22c362017-01-30 07:15:00 -05001549 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001550 }
1551
Allen George7ddbcc02020-11-08 09:51:19 -05001552 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001553 #[test]
1554 fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001555 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001556
1557 // no bytes should be written however
1558 let struct_ident = TStructIdentifier::new("foo");
1559 assert_success!(o_prot.write_struct_begin(&struct_ident));
1560
1561 // write three fields with field ids that cannot be encoded as deltas
1562
1563 // since the delta is > 0 and < 15 it gets a delta write
1564 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1565 assert_success!(o_prot.write_field_begin(&field_ident_1));
1566 assert_success!(o_prot.write_field_end());
1567
1568 // since this delta > 0 and < 15 it gets a delta write
1569 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1570 assert_success!(o_prot.write_field_begin(&field_ident_2));
1571 assert_success!(o_prot.write_field_end());
1572
1573 // since this delta is > 15 it is encoded as a zig-zag varint
1574 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
1575 assert_success!(o_prot.write_field_begin(&field_ident_3));
1576 assert_success!(o_prot.write_field_end());
1577
1578 // since this delta is > 15 it is encoded as a zig-zag varint
1579 let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
1580 assert_success!(o_prot.write_field_begin(&field_ident_4));
1581 assert_success!(o_prot.write_field_end());
1582
1583 // since this is only 3 up from the previous it is recorded as a delta
1584 let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
1585 assert_success!(o_prot.write_field_begin(&field_ident_5));
1586 assert_success!(o_prot.write_field_end());
1587
1588 // now, finish the struct off
1589 assert_success!(o_prot.write_field_stop());
1590 assert_success!(o_prot.write_struct_end());
1591
Allen George0e22c362017-01-30 07:15:00 -05001592 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001593
1594 // read the struct back
1595 assert_success!(i_prot.read_struct_begin());
1596
1597 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001598 assert_eq!(
1599 read_ident_1,
1600 TFieldIdentifier {
1601 name: None,
1602 ..field_ident_1
1603 }
1604 );
Allen George8b96bfb2016-11-02 08:01:08 -04001605 assert_success!(i_prot.read_field_end());
1606
1607 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001608 assert_eq!(
1609 read_ident_2,
1610 TFieldIdentifier {
1611 name: None,
1612 ..field_ident_2
1613 }
1614 );
Allen George8b96bfb2016-11-02 08:01:08 -04001615 assert_success!(i_prot.read_field_end());
1616
1617 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001618 assert_eq!(
1619 read_ident_3,
1620 TFieldIdentifier {
1621 name: None,
1622 ..field_ident_3
1623 }
1624 );
Allen George8b96bfb2016-11-02 08:01:08 -04001625 assert_success!(i_prot.read_field_end());
1626
1627 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001628 assert_eq!(
1629 read_ident_4,
1630 TFieldIdentifier {
1631 name: None,
1632 ..field_ident_4
1633 }
1634 );
Allen George8b96bfb2016-11-02 08:01:08 -04001635 assert_success!(i_prot.read_field_end());
1636
1637 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001638 assert_eq!(
1639 read_ident_5,
1640 TFieldIdentifier {
1641 name: None,
1642 ..field_ident_5
1643 }
1644 );
Allen George8b96bfb2016-11-02 08:01:08 -04001645 assert_success!(i_prot.read_field_end());
1646
1647 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001648 assert_eq!(
1649 read_ident_6,
1650 TFieldIdentifier {
1651 name: None,
1652 field_type: TType::Stop,
1653 id: None,
1654 }
1655 );
Allen George8b96bfb2016-11-02 08:01:08 -04001656
1657 assert_success!(i_prot.read_struct_end());
1658 }
1659
1660 #[test]
1661 fn must_write_nested_structs_0() {
1662 // last field of the containing struct is a delta
1663 // first field of the the contained struct is a delta
1664
Allen George0e22c362017-01-30 07:15:00 -05001665 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001666
1667 // start containing struct
1668 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1669
1670 // containing struct
1671 // since the delta is > 0 and < 15 it gets a delta write
1672 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1673 assert_success!(o_prot.write_field_end());
1674
1675 // containing struct
1676 // since this delta > 0 and < 15 it gets a delta write
1677 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1678 assert_success!(o_prot.write_field_end());
1679
1680 // start contained struct
1681 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1682
1683 // contained struct
1684 // since the delta is > 0 and < 15 it gets a delta write
1685 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
1686 assert_success!(o_prot.write_field_end());
1687
1688 // contained struct
1689 // since this delta > 15 it gets a full write
1690 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1691 assert_success!(o_prot.write_field_end());
1692
1693 // end contained struct
1694 assert_success!(o_prot.write_field_stop());
1695 assert_success!(o_prot.write_struct_end());
1696
1697 // end containing struct
1698 assert_success!(o_prot.write_field_stop());
1699 assert_success!(o_prot.write_struct_end());
1700
Allen George7ddbcc02020-11-08 09:51:19 -05001701 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001702 let expected: [u8; 7] = [
1703 0x16, /* field delta (1) | field type */
1704 0x85, /* field delta (8) | field type */
1705 0x73, /* field delta (7) | field type */
1706 0x07, /* field type */
1707 0x30, /* zig-zag varint field id */
1708 0x00, /* field stop - contained */
1709 0x00 /* field stop - containing */,
1710 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001711
Allen George0e22c362017-01-30 07:15:00 -05001712 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001713 }
1714
Allen George7ddbcc02020-11-08 09:51:19 -05001715 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001716 #[test]
1717 fn must_round_trip_nested_structs_0() {
1718 // last field of the containing struct is a delta
1719 // first field of the the contained struct is a delta
1720
Allen George0e22c362017-01-30 07:15:00 -05001721 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001722
1723 // start containing struct
1724 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1725
1726 // containing struct
1727 // since the delta is > 0 and < 15 it gets a delta write
1728 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1729 assert_success!(o_prot.write_field_begin(&field_ident_1));
1730 assert_success!(o_prot.write_field_end());
1731
1732 // containing struct
1733 // since this delta > 0 and < 15 it gets a delta write
1734 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1735 assert_success!(o_prot.write_field_begin(&field_ident_2));
1736 assert_success!(o_prot.write_field_end());
1737
1738 // start contained struct
1739 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1740
1741 // contained struct
1742 // since the delta is > 0 and < 15 it gets a delta write
1743 let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
1744 assert_success!(o_prot.write_field_begin(&field_ident_3));
1745 assert_success!(o_prot.write_field_end());
1746
1747 // contained struct
1748 // since this delta > 15 it gets a full write
1749 let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
1750 assert_success!(o_prot.write_field_begin(&field_ident_4));
1751 assert_success!(o_prot.write_field_end());
1752
1753 // end contained struct
1754 assert_success!(o_prot.write_field_stop());
1755 assert_success!(o_prot.write_struct_end());
1756
1757 // end containing struct
1758 assert_success!(o_prot.write_field_stop());
1759 assert_success!(o_prot.write_struct_end());
1760
Allen George0e22c362017-01-30 07:15:00 -05001761 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001762
1763 // read containing struct back
1764 assert_success!(i_prot.read_struct_begin());
1765
1766 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001767 assert_eq!(
1768 read_ident_1,
1769 TFieldIdentifier {
1770 name: None,
1771 ..field_ident_1
1772 }
1773 );
Allen George8b96bfb2016-11-02 08:01:08 -04001774 assert_success!(i_prot.read_field_end());
1775
1776 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001777 assert_eq!(
1778 read_ident_2,
1779 TFieldIdentifier {
1780 name: None,
1781 ..field_ident_2
1782 }
1783 );
Allen George8b96bfb2016-11-02 08:01:08 -04001784 assert_success!(i_prot.read_field_end());
1785
1786 // read contained struct back
1787 assert_success!(i_prot.read_struct_begin());
1788
1789 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001790 assert_eq!(
1791 read_ident_3,
1792 TFieldIdentifier {
1793 name: None,
1794 ..field_ident_3
1795 }
1796 );
Allen George8b96bfb2016-11-02 08:01:08 -04001797 assert_success!(i_prot.read_field_end());
1798
1799 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001800 assert_eq!(
1801 read_ident_4,
1802 TFieldIdentifier {
1803 name: None,
1804 ..field_ident_4
1805 }
1806 );
Allen George8b96bfb2016-11-02 08:01:08 -04001807 assert_success!(i_prot.read_field_end());
1808
1809 // end contained struct
1810 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001811 assert_eq!(
1812 read_ident_6,
1813 TFieldIdentifier {
1814 name: None,
1815 field_type: TType::Stop,
1816 id: None,
1817 }
1818 );
Allen George8b96bfb2016-11-02 08:01:08 -04001819 assert_success!(i_prot.read_struct_end());
1820
1821 // end containing struct
1822 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001823 assert_eq!(
1824 read_ident_7,
1825 TFieldIdentifier {
1826 name: None,
1827 field_type: TType::Stop,
1828 id: None,
1829 }
1830 );
Allen George8b96bfb2016-11-02 08:01:08 -04001831 assert_success!(i_prot.read_struct_end());
1832 }
1833
1834 #[test]
1835 fn must_write_nested_structs_1() {
1836 // last field of the containing struct is a delta
1837 // first field of the the contained struct is a full write
1838
Allen George0e22c362017-01-30 07:15:00 -05001839 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001840
1841 // start containing struct
1842 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1843
1844 // containing struct
1845 // since the delta is > 0 and < 15 it gets a delta write
1846 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1847 assert_success!(o_prot.write_field_end());
1848
1849 // containing struct
1850 // since this delta > 0 and < 15 it gets a delta write
1851 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1852 assert_success!(o_prot.write_field_end());
1853
1854 // start contained struct
1855 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1856
1857 // contained struct
1858 // since this delta > 15 it gets a full write
1859 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1860 assert_success!(o_prot.write_field_end());
1861
1862 // contained struct
1863 // since the delta is > 0 and < 15 it gets a delta write
1864 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1865 assert_success!(o_prot.write_field_end());
1866
1867 // end contained struct
1868 assert_success!(o_prot.write_field_stop());
1869 assert_success!(o_prot.write_struct_end());
1870
1871 // end containing struct
1872 assert_success!(o_prot.write_field_stop());
1873 assert_success!(o_prot.write_struct_end());
1874
Allen George7ddbcc02020-11-08 09:51:19 -05001875 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001876 let expected: [u8; 7] = [
1877 0x16, /* field delta (1) | field type */
1878 0x85, /* field delta (8) | field type */
1879 0x07, /* field type */
1880 0x30, /* zig-zag varint field id */
1881 0x33, /* field delta (3) | field type */
1882 0x00, /* field stop - contained */
1883 0x00 /* field stop - containing */,
1884 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001885
Allen George0e22c362017-01-30 07:15:00 -05001886 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001887 }
1888
Allen George7ddbcc02020-11-08 09:51:19 -05001889 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001890 #[test]
1891 fn must_round_trip_nested_structs_1() {
1892 // last field of the containing struct is a delta
1893 // first field of the the contained struct is a full write
1894
Allen George0e22c362017-01-30 07:15:00 -05001895 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001896
1897 // start containing struct
1898 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1899
1900 // containing struct
1901 // since the delta is > 0 and < 15 it gets a delta write
1902 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1903 assert_success!(o_prot.write_field_begin(&field_ident_1));
1904 assert_success!(o_prot.write_field_end());
1905
1906 // containing struct
1907 // since this delta > 0 and < 15 it gets a delta write
1908 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1909 assert_success!(o_prot.write_field_begin(&field_ident_2));
1910 assert_success!(o_prot.write_field_end());
1911
1912 // start contained struct
1913 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1914
1915 // contained struct
1916 // since this delta > 15 it gets a full write
1917 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
1918 assert_success!(o_prot.write_field_begin(&field_ident_3));
1919 assert_success!(o_prot.write_field_end());
1920
1921 // contained struct
1922 // since the delta is > 0 and < 15 it gets a delta write
1923 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
1924 assert_success!(o_prot.write_field_begin(&field_ident_4));
1925 assert_success!(o_prot.write_field_end());
1926
1927 // end contained struct
1928 assert_success!(o_prot.write_field_stop());
1929 assert_success!(o_prot.write_struct_end());
1930
1931 // end containing struct
1932 assert_success!(o_prot.write_field_stop());
1933 assert_success!(o_prot.write_struct_end());
1934
Allen George0e22c362017-01-30 07:15:00 -05001935 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001936
1937 // read containing struct back
1938 assert_success!(i_prot.read_struct_begin());
1939
1940 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001941 assert_eq!(
1942 read_ident_1,
1943 TFieldIdentifier {
1944 name: None,
1945 ..field_ident_1
1946 }
1947 );
Allen George8b96bfb2016-11-02 08:01:08 -04001948 assert_success!(i_prot.read_field_end());
1949
1950 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001951 assert_eq!(
1952 read_ident_2,
1953 TFieldIdentifier {
1954 name: None,
1955 ..field_ident_2
1956 }
1957 );
Allen George8b96bfb2016-11-02 08:01:08 -04001958 assert_success!(i_prot.read_field_end());
1959
1960 // read contained struct back
1961 assert_success!(i_prot.read_struct_begin());
1962
1963 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001964 assert_eq!(
1965 read_ident_3,
1966 TFieldIdentifier {
1967 name: None,
1968 ..field_ident_3
1969 }
1970 );
Allen George8b96bfb2016-11-02 08:01:08 -04001971 assert_success!(i_prot.read_field_end());
1972
1973 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001974 assert_eq!(
1975 read_ident_4,
1976 TFieldIdentifier {
1977 name: None,
1978 ..field_ident_4
1979 }
1980 );
Allen George8b96bfb2016-11-02 08:01:08 -04001981 assert_success!(i_prot.read_field_end());
1982
1983 // end contained struct
1984 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001985 assert_eq!(
1986 read_ident_6,
1987 TFieldIdentifier {
1988 name: None,
1989 field_type: TType::Stop,
1990 id: None,
1991 }
1992 );
Allen George8b96bfb2016-11-02 08:01:08 -04001993 assert_success!(i_prot.read_struct_end());
1994
1995 // end containing struct
1996 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001997 assert_eq!(
1998 read_ident_7,
1999 TFieldIdentifier {
2000 name: None,
2001 field_type: TType::Stop,
2002 id: None,
2003 }
2004 );
Allen George8b96bfb2016-11-02 08:01:08 -04002005 assert_success!(i_prot.read_struct_end());
2006 }
2007
2008 #[test]
2009 fn must_write_nested_structs_2() {
2010 // last field of the containing struct is a full write
2011 // first field of the the contained struct is a delta write
2012
Allen George0e22c362017-01-30 07:15:00 -05002013 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002014
2015 // start containing struct
2016 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2017
2018 // containing struct
2019 // since the delta is > 0 and < 15 it gets a delta write
2020 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2021 assert_success!(o_prot.write_field_end());
2022
2023 // containing struct
2024 // since this delta > 15 it gets a full write
2025 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2026 assert_success!(o_prot.write_field_end());
2027
2028 // start contained struct
2029 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2030
2031 // contained struct
2032 // since this delta > 0 and < 15 it gets a delta write
2033 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
2034 assert_success!(o_prot.write_field_end());
2035
2036 // contained struct
2037 // since the delta is > 0 and < 15 it gets a delta write
2038 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
2039 assert_success!(o_prot.write_field_end());
2040
2041 // end contained struct
2042 assert_success!(o_prot.write_field_stop());
2043 assert_success!(o_prot.write_struct_end());
2044
2045 // end containing struct
2046 assert_success!(o_prot.write_field_stop());
2047 assert_success!(o_prot.write_struct_end());
2048
Allen George7ddbcc02020-11-08 09:51:19 -05002049 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002050 let expected: [u8; 7] = [
2051 0x16, /* field delta (1) | field type */
2052 0x08, /* field type */
2053 0x2A, /* zig-zag varint field id */
2054 0x77, /* field delta(7) | field type */
2055 0x33, /* field delta (3) | field type */
2056 0x00, /* field stop - contained */
2057 0x00 /* field stop - containing */,
2058 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002059
Allen George0e22c362017-01-30 07:15:00 -05002060 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002061 }
2062
Allen George7ddbcc02020-11-08 09:51:19 -05002063 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002064 #[test]
2065 fn must_round_trip_nested_structs_2() {
Allen George0e22c362017-01-30 07:15:00 -05002066 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002067
2068 // start containing struct
2069 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2070
2071 // containing struct
2072 // since the delta is > 0 and < 15 it gets a delta write
2073 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2074 assert_success!(o_prot.write_field_begin(&field_ident_1));
2075 assert_success!(o_prot.write_field_end());
2076
2077 // containing struct
2078 // since this delta > 15 it gets a full write
2079 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2080 assert_success!(o_prot.write_field_begin(&field_ident_2));
2081 assert_success!(o_prot.write_field_end());
2082
2083 // start contained struct
2084 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2085
2086 // contained struct
2087 // since this delta > 0 and < 15 it gets a delta write
2088 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
2089 assert_success!(o_prot.write_field_begin(&field_ident_3));
2090 assert_success!(o_prot.write_field_end());
2091
2092 // contained struct
2093 // since the delta is > 0 and < 15 it gets a delta write
2094 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
2095 assert_success!(o_prot.write_field_begin(&field_ident_4));
2096 assert_success!(o_prot.write_field_end());
2097
2098 // end contained struct
2099 assert_success!(o_prot.write_field_stop());
2100 assert_success!(o_prot.write_struct_end());
2101
2102 // end containing struct
2103 assert_success!(o_prot.write_field_stop());
2104 assert_success!(o_prot.write_struct_end());
2105
Allen George0e22c362017-01-30 07:15:00 -05002106 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002107
2108 // read containing struct back
2109 assert_success!(i_prot.read_struct_begin());
2110
2111 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002112 assert_eq!(
2113 read_ident_1,
2114 TFieldIdentifier {
2115 name: None,
2116 ..field_ident_1
2117 }
2118 );
Allen George8b96bfb2016-11-02 08:01:08 -04002119 assert_success!(i_prot.read_field_end());
2120
2121 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002122 assert_eq!(
2123 read_ident_2,
2124 TFieldIdentifier {
2125 name: None,
2126 ..field_ident_2
2127 }
2128 );
Allen George8b96bfb2016-11-02 08:01:08 -04002129 assert_success!(i_prot.read_field_end());
2130
2131 // read contained struct back
2132 assert_success!(i_prot.read_struct_begin());
2133
2134 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002135 assert_eq!(
2136 read_ident_3,
2137 TFieldIdentifier {
2138 name: None,
2139 ..field_ident_3
2140 }
2141 );
Allen George8b96bfb2016-11-02 08:01:08 -04002142 assert_success!(i_prot.read_field_end());
2143
2144 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002145 assert_eq!(
2146 read_ident_4,
2147 TFieldIdentifier {
2148 name: None,
2149 ..field_ident_4
2150 }
2151 );
Allen George8b96bfb2016-11-02 08:01:08 -04002152 assert_success!(i_prot.read_field_end());
2153
2154 // end contained struct
2155 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002156 assert_eq!(
2157 read_ident_6,
2158 TFieldIdentifier {
2159 name: None,
2160 field_type: TType::Stop,
2161 id: None,
2162 }
2163 );
Allen George8b96bfb2016-11-02 08:01:08 -04002164 assert_success!(i_prot.read_struct_end());
2165
2166 // end containing struct
2167 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002168 assert_eq!(
2169 read_ident_7,
2170 TFieldIdentifier {
2171 name: None,
2172 field_type: TType::Stop,
2173 id: None,
2174 }
2175 );
Allen George8b96bfb2016-11-02 08:01:08 -04002176 assert_success!(i_prot.read_struct_end());
2177 }
2178
2179 #[test]
2180 fn must_write_nested_structs_3() {
2181 // last field of the containing struct is a full write
2182 // first field of the the contained struct is a full write
2183
Allen George0e22c362017-01-30 07:15:00 -05002184 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002185
2186 // start containing struct
2187 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2188
2189 // containing struct
2190 // since the delta is > 0 and < 15 it gets a delta write
2191 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2192 assert_success!(o_prot.write_field_end());
2193
2194 // containing struct
2195 // since this delta > 15 it gets a full write
2196 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2197 assert_success!(o_prot.write_field_end());
2198
2199 // start contained struct
2200 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2201
2202 // contained struct
2203 // since this delta > 15 it gets a full write
2204 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
2205 assert_success!(o_prot.write_field_end());
2206
2207 // contained struct
2208 // since the delta is > 0 and < 15 it gets a delta write
2209 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
2210 assert_success!(o_prot.write_field_end());
2211
2212 // end contained struct
2213 assert_success!(o_prot.write_field_stop());
2214 assert_success!(o_prot.write_struct_end());
2215
2216 // end containing struct
2217 assert_success!(o_prot.write_field_stop());
2218 assert_success!(o_prot.write_struct_end());
2219
Allen George7ddbcc02020-11-08 09:51:19 -05002220 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002221 let expected: [u8; 8] = [
2222 0x16, /* field delta (1) | field type */
2223 0x08, /* field type */
2224 0x2A, /* zig-zag varint field id */
2225 0x07, /* field type */
2226 0x2A, /* zig-zag varint field id */
2227 0x63, /* field delta (6) | field type */
2228 0x00, /* field stop - contained */
2229 0x00 /* field stop - containing */,
2230 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002231
Allen George0e22c362017-01-30 07:15:00 -05002232 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002233 }
2234
Allen George7ddbcc02020-11-08 09:51:19 -05002235 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002236 #[test]
2237 fn must_round_trip_nested_structs_3() {
2238 // last field of the containing struct is a full write
2239 // first field of the the contained struct is a full write
2240
Allen George0e22c362017-01-30 07:15:00 -05002241 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002242
2243 // start containing struct
2244 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2245
2246 // containing struct
2247 // since the delta is > 0 and < 15 it gets a delta write
2248 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2249 assert_success!(o_prot.write_field_begin(&field_ident_1));
2250 assert_success!(o_prot.write_field_end());
2251
2252 // containing struct
2253 // since this delta > 15 it gets a full write
2254 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2255 assert_success!(o_prot.write_field_begin(&field_ident_2));
2256 assert_success!(o_prot.write_field_end());
2257
2258 // start contained struct
2259 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2260
2261 // contained struct
2262 // since this delta > 15 it gets a full write
2263 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
2264 assert_success!(o_prot.write_field_begin(&field_ident_3));
2265 assert_success!(o_prot.write_field_end());
2266
2267 // contained struct
2268 // since the delta is > 0 and < 15 it gets a delta write
2269 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2270 assert_success!(o_prot.write_field_begin(&field_ident_4));
2271 assert_success!(o_prot.write_field_end());
2272
2273 // end contained struct
2274 assert_success!(o_prot.write_field_stop());
2275 assert_success!(o_prot.write_struct_end());
2276
2277 // end containing struct
2278 assert_success!(o_prot.write_field_stop());
2279 assert_success!(o_prot.write_struct_end());
2280
Allen George0e22c362017-01-30 07:15:00 -05002281 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002282
2283 // read containing struct back
2284 assert_success!(i_prot.read_struct_begin());
2285
2286 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002287 assert_eq!(
2288 read_ident_1,
2289 TFieldIdentifier {
2290 name: None,
2291 ..field_ident_1
2292 }
2293 );
Allen George8b96bfb2016-11-02 08:01:08 -04002294 assert_success!(i_prot.read_field_end());
2295
2296 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002297 assert_eq!(
2298 read_ident_2,
2299 TFieldIdentifier {
2300 name: None,
2301 ..field_ident_2
2302 }
2303 );
Allen George8b96bfb2016-11-02 08:01:08 -04002304 assert_success!(i_prot.read_field_end());
2305
2306 // read contained struct back
2307 assert_success!(i_prot.read_struct_begin());
2308
2309 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002310 assert_eq!(
2311 read_ident_3,
2312 TFieldIdentifier {
2313 name: None,
2314 ..field_ident_3
2315 }
2316 );
Allen George8b96bfb2016-11-02 08:01:08 -04002317 assert_success!(i_prot.read_field_end());
2318
2319 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002320 assert_eq!(
2321 read_ident_4,
2322 TFieldIdentifier {
2323 name: None,
2324 ..field_ident_4
2325 }
2326 );
Allen George8b96bfb2016-11-02 08:01:08 -04002327 assert_success!(i_prot.read_field_end());
2328
2329 // end contained struct
2330 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002331 assert_eq!(
2332 read_ident_6,
2333 TFieldIdentifier {
2334 name: None,
2335 field_type: TType::Stop,
2336 id: None,
2337 }
2338 );
Allen George8b96bfb2016-11-02 08:01:08 -04002339 assert_success!(i_prot.read_struct_end());
2340
2341 // end containing struct
2342 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002343 assert_eq!(
2344 read_ident_7,
2345 TFieldIdentifier {
2346 name: None,
2347 field_type: TType::Stop,
2348 id: None,
2349 }
2350 );
Allen George8b96bfb2016-11-02 08:01:08 -04002351 assert_success!(i_prot.read_struct_end());
2352 }
2353
2354 #[test]
2355 fn must_write_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002356 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002357
2358 // no bytes should be written however
2359 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2360
2361 // write three fields with field ids that cannot be encoded as deltas
2362
2363 // since the delta is > 0 and < 16 it gets a delta write
2364 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2365 assert_success!(o_prot.write_bool(true));
2366 assert_success!(o_prot.write_field_end());
2367
2368 // since this delta > 0 and < 15 it gets a delta write
2369 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
2370 assert_success!(o_prot.write_bool(false));
2371 assert_success!(o_prot.write_field_end());
2372
2373 // since this delta > 15 it gets a full write
2374 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
2375 assert_success!(o_prot.write_bool(true));
2376 assert_success!(o_prot.write_field_end());
2377
2378 // since this delta > 15 it gets a full write
2379 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
2380 assert_success!(o_prot.write_bool(false));
2381 assert_success!(o_prot.write_field_end());
2382
2383 // now, finish the struct off
2384 assert_success!(o_prot.write_field_stop());
2385 assert_success!(o_prot.write_struct_end());
2386
Allen George7ddbcc02020-11-08 09:51:19 -05002387 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002388 let expected: [u8; 7] = [
2389 0x11, /* field delta (1) | true */
2390 0x82, /* field delta (8) | false */
2391 0x01, /* true */
2392 0x34, /* field id */
2393 0x02, /* false */
2394 0x5A, /* field id */
2395 0x00 /* stop field */,
2396 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002397
Allen George0e22c362017-01-30 07:15:00 -05002398 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002399 }
2400
Allen George7ddbcc02020-11-08 09:51:19 -05002401 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002402 #[test]
2403 fn must_round_trip_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002404 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002405
2406 // no bytes should be written however
2407 let struct_ident = TStructIdentifier::new("foo");
2408 assert_success!(o_prot.write_struct_begin(&struct_ident));
2409
2410 // write two fields
2411
2412 // since the delta is > 0 and < 16 it gets a delta write
2413 let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
2414 assert_success!(o_prot.write_field_begin(&field_ident_1));
2415 assert_success!(o_prot.write_bool(true));
2416 assert_success!(o_prot.write_field_end());
2417
2418 // since this delta > 0 and < 15 it gets a delta write
2419 let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
2420 assert_success!(o_prot.write_field_begin(&field_ident_2));
2421 assert_success!(o_prot.write_bool(false));
2422 assert_success!(o_prot.write_field_end());
2423
2424 // since this delta > 15 it gets a full write
2425 let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
2426 assert_success!(o_prot.write_field_begin(&field_ident_3));
2427 assert_success!(o_prot.write_bool(true));
2428 assert_success!(o_prot.write_field_end());
2429
2430 // since this delta > 15 it gets a full write
2431 let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
2432 assert_success!(o_prot.write_field_begin(&field_ident_4));
2433 assert_success!(o_prot.write_bool(false));
2434 assert_success!(o_prot.write_field_end());
2435
2436 // now, finish the struct off
2437 assert_success!(o_prot.write_field_stop());
2438 assert_success!(o_prot.write_struct_end());
2439
Allen George0e22c362017-01-30 07:15:00 -05002440 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002441
2442 // read the struct back
2443 assert_success!(i_prot.read_struct_begin());
2444
2445 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002446 assert_eq!(
2447 read_ident_1,
2448 TFieldIdentifier {
2449 name: None,
2450 ..field_ident_1
2451 }
2452 );
Allen George8b96bfb2016-11-02 08:01:08 -04002453 let read_value_1 = assert_success!(i_prot.read_bool());
2454 assert_eq!(read_value_1, true);
2455 assert_success!(i_prot.read_field_end());
2456
2457 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002458 assert_eq!(
2459 read_ident_2,
2460 TFieldIdentifier {
2461 name: None,
2462 ..field_ident_2
2463 }
2464 );
Allen George8b96bfb2016-11-02 08:01:08 -04002465 let read_value_2 = assert_success!(i_prot.read_bool());
2466 assert_eq!(read_value_2, false);
2467 assert_success!(i_prot.read_field_end());
2468
2469 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002470 assert_eq!(
2471 read_ident_3,
2472 TFieldIdentifier {
2473 name: None,
2474 ..field_ident_3
2475 }
2476 );
Allen George8b96bfb2016-11-02 08:01:08 -04002477 let read_value_3 = assert_success!(i_prot.read_bool());
2478 assert_eq!(read_value_3, true);
2479 assert_success!(i_prot.read_field_end());
2480
2481 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002482 assert_eq!(
2483 read_ident_4,
2484 TFieldIdentifier {
2485 name: None,
2486 ..field_ident_4
2487 }
2488 );
Allen George8b96bfb2016-11-02 08:01:08 -04002489 let read_value_4 = assert_success!(i_prot.read_bool());
2490 assert_eq!(read_value_4, false);
2491 assert_success!(i_prot.read_field_end());
2492
2493 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002494 assert_eq!(
2495 read_ident_5,
2496 TFieldIdentifier {
2497 name: None,
2498 field_type: TType::Stop,
2499 id: None,
2500 }
2501 );
Allen George8b96bfb2016-11-02 08:01:08 -04002502
2503 assert_success!(i_prot.read_struct_end());
2504 }
2505
2506 #[test]
2507 #[should_panic]
2508 fn must_fail_if_write_field_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002509 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002510 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2511 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2512 o_prot.write_field_end().unwrap();
2513 }
2514
2515 #[test]
2516 #[should_panic]
2517 fn must_fail_if_write_stop_field_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002518 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002519 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2520 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2521 o_prot.write_field_stop().unwrap();
2522 }
2523
2524 #[test]
2525 #[should_panic]
2526 fn must_fail_if_write_struct_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002527 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002528 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2529 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2530 o_prot.write_struct_end().unwrap();
2531 }
2532
2533 #[test]
2534 #[should_panic]
2535 fn must_fail_if_write_struct_end_without_any_fields() {
Allen George0e22c362017-01-30 07:15:00 -05002536 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002537 o_prot.write_struct_end().unwrap();
2538 }
2539
2540 #[test]
2541 fn must_write_field_end() {
2542 assert_no_write(|o| o.write_field_end());
2543 }
2544
2545 #[test]
2546 fn must_write_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002547 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002548
2549 assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
2550
2551 let expected: [u8; 1] = [0x46 /* size | elem_type */];
2552
Allen George0e22c362017-01-30 07:15:00 -05002553 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002554 }
2555
2556 #[test]
2557 fn must_round_trip_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002558 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002559
2560 let ident = TListIdentifier::new(TType::I08, 10);
2561
2562 assert_success!(o_prot.write_list_begin(&ident));
2563
Allen George0e22c362017-01-30 07:15:00 -05002564 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002565
2566 let res = assert_success!(i_prot.read_list_begin());
2567 assert_eq!(&res, &ident);
2568 }
2569
2570 #[test]
2571 fn must_write_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002572 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002573
2574 let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
2575 assert!(res.is_ok());
2576
Allen George0e22c362017-01-30 07:15:00 -05002577 let expected: [u8; 3] = [
2578 0xF9, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002579 0x8F, 0x4E, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002580 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002581
Allen George0e22c362017-01-30 07:15:00 -05002582 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002583 }
2584
2585 #[test]
2586 fn must_round_trip_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002587 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002588
2589 let ident = TListIdentifier::new(TType::Set, 47381);
2590
2591 assert_success!(o_prot.write_list_begin(&ident));
2592
Allen George0e22c362017-01-30 07:15:00 -05002593 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002594
2595 let res = assert_success!(i_prot.read_list_begin());
2596 assert_eq!(&res, &ident);
2597 }
2598
2599 #[test]
2600 fn must_write_list_end() {
2601 assert_no_write(|o| o.write_list_end());
2602 }
2603
2604 #[test]
2605 fn must_write_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002606 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002607
2608 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
2609
2610 let expected: [u8; 1] = [0x2C /* size | elem_type */];
2611
Allen George0e22c362017-01-30 07:15:00 -05002612 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002613 }
2614
2615 #[test]
2616 fn must_round_trip_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002617 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002618
2619 let ident = TSetIdentifier::new(TType::I16, 7);
2620
2621 assert_success!(o_prot.write_set_begin(&ident));
2622
Allen George0e22c362017-01-30 07:15:00 -05002623 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002624
2625 let res = assert_success!(i_prot.read_set_begin());
2626 assert_eq!(&res, &ident);
2627 }
2628
2629 #[test]
2630 fn must_write_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002631 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002632
2633 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
2634
Allen George0e22c362017-01-30 07:15:00 -05002635 let expected: [u8; 4] = [
2636 0xF7, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002637 0xD3, 0xBA, 0x01, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002638 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002639
Allen George0e22c362017-01-30 07:15:00 -05002640 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002641 }
2642
2643 #[test]
2644 fn must_round_trip_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002645 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002646
Allen George7ddbcc02020-11-08 09:51:19 -05002647 let ident = TSetIdentifier::new(TType::Map, 3_928_429);
Allen George8b96bfb2016-11-02 08:01:08 -04002648
2649 assert_success!(o_prot.write_set_begin(&ident));
2650
Allen George0e22c362017-01-30 07:15:00 -05002651 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002652
2653 let res = assert_success!(i_prot.read_set_begin());
2654 assert_eq!(&res, &ident);
2655 }
2656
2657 #[test]
2658 fn must_write_set_end() {
2659 assert_no_write(|o| o.write_set_end());
2660 }
2661
2662 #[test]
2663 fn must_write_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002664 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002665
2666 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
2667
2668 let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything
2669
Allen George0e22c362017-01-30 07:15:00 -05002670 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002671 }
2672
2673 #[test]
2674 fn must_read_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002675 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002676
2677 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
2678
Allen George0e22c362017-01-30 07:15:00 -05002679 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002680
2681 let res = assert_success!(i_prot.read_map_begin());
Allen George0e22c362017-01-30 07:15:00 -05002682 assert_eq!(
2683 &res,
2684 &TMapIdentifier {
Allen Georgeef7a1892018-12-16 18:01:37 -05002685 key_type: None,
2686 value_type: None,
2687 size: 0,
2688 }
Allen George0e22c362017-01-30 07:15:00 -05002689 );
Allen George8b96bfb2016-11-02 08:01:08 -04002690 }
2691
2692 #[test]
2693 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002694 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002695
Allen Georgeef7a1892018-12-16 18:01:37 -05002696 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
2697 TType::Double,
2698 TType::String,
2699 238
2700 )));
Allen George8b96bfb2016-11-02 08:01:08 -04002701
Allen George0e22c362017-01-30 07:15:00 -05002702 let expected: [u8; 3] = [
Allen Georgeef7a1892018-12-16 18:01:37 -05002703 0xEE, 0x01, /* size as varint */
2704 0x78, /* key type | val type */
Allen George0e22c362017-01-30 07:15:00 -05002705 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002706
Allen George0e22c362017-01-30 07:15:00 -05002707 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002708 }
2709
2710 #[test]
2711 fn must_round_trip_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002712 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002713
Allen George7ddbcc02020-11-08 09:51:19 -05002714 let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349);
Allen George8b96bfb2016-11-02 08:01:08 -04002715
2716 assert_success!(o_prot.write_map_begin(&ident));
2717
Allen George0e22c362017-01-30 07:15:00 -05002718 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002719
2720 let res = assert_success!(i_prot.read_map_begin());
2721 assert_eq!(&res, &ident);
2722 }
2723
2724 #[test]
2725 fn must_write_map_end() {
2726 assert_no_write(|o| o.write_map_end());
2727 }
2728
2729 #[test]
2730 fn must_write_map_with_bool_key_and_value() {
Allen George0e22c362017-01-30 07:15:00 -05002731 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002732
2733 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
2734 assert_success!(o_prot.write_bool(true));
2735 assert_success!(o_prot.write_bool(false));
2736 assert_success!(o_prot.write_map_end());
2737
Allen George0e22c362017-01-30 07:15:00 -05002738 let expected: [u8; 4] = [
2739 0x01, /* size as varint */
2740 0x11, /* key type | val type */
2741 0x01, /* key: true */
Allen Georgeef7a1892018-12-16 18:01:37 -05002742 0x02, /* val: false */
Allen George0e22c362017-01-30 07:15:00 -05002743 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002744
Allen George0e22c362017-01-30 07:15:00 -05002745 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002746 }
2747
2748 #[test]
2749 fn must_round_trip_map_with_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002750 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002751
2752 let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
2753 assert_success!(o_prot.write_map_begin(&map_ident));
2754 assert_success!(o_prot.write_bool(true));
2755 assert_success!(o_prot.write_bool(false));
2756 assert_success!(o_prot.write_bool(false));
2757 assert_success!(o_prot.write_bool(true));
2758 assert_success!(o_prot.write_map_end());
2759
Allen George0e22c362017-01-30 07:15:00 -05002760 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002761
2762 // map header
2763 let rcvd_ident = assert_success!(i_prot.read_map_begin());
2764 assert_eq!(&rcvd_ident, &map_ident);
2765 // key 1
2766 let b = assert_success!(i_prot.read_bool());
2767 assert_eq!(b, true);
2768 // val 1
2769 let b = assert_success!(i_prot.read_bool());
2770 assert_eq!(b, false);
2771 // key 2
2772 let b = assert_success!(i_prot.read_bool());
2773 assert_eq!(b, false);
2774 // val 2
2775 let b = assert_success!(i_prot.read_bool());
2776 assert_eq!(b, true);
2777 // map end
2778 assert_success!(i_prot.read_map_end());
2779 }
2780
2781 #[test]
2782 fn must_read_map_end() {
Allen George0e22c362017-01-30 07:15:00 -05002783 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002784 assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
2785 }
2786
Allen Georgeef7a1892018-12-16 18:01:37 -05002787 fn test_objects() -> (
2788 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2789 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2790 ) {
Allen George0e22c362017-01-30 07:15:00 -05002791 let mem = TBufferChannel::with_capacity(80, 80);
Allen George8b96bfb2016-11-02 08:01:08 -04002792
Allen George0e22c362017-01-30 07:15:00 -05002793 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -04002794
Allen George0e22c362017-01-30 07:15:00 -05002795 let i_prot = TCompactInputProtocol::new(r_mem);
2796 let o_prot = TCompactOutputProtocol::new(w_mem);
Allen George8b96bfb2016-11-02 08:01:08 -04002797
Allen George0e22c362017-01-30 07:15:00 -05002798 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -04002799 }
2800
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002801 #[test]
2802 fn must_read_write_double() {
2803 let (mut i_prot, mut o_prot) = test_objects();
2804
Allen George7ddbcc02020-11-08 09:51:19 -05002805 #[allow(clippy::approx_constant)]
2806 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002807 o_prot.write_double(double).unwrap();
2808 copy_write_buffer_to_read_buffer!(o_prot);
2809
Allen George7ddbcc02020-11-08 09:51:19 -05002810 let read_double = i_prot.read_double().unwrap();
2811 assert!(read_double - double < std::f64::EPSILON);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002812 }
2813
2814 #[test]
2815 fn must_encode_double_as_other_langs() {
2816 let (_, mut o_prot) = test_objects();
2817 let expected = [24, 45, 68, 84, 251, 33, 9, 64];
2818
Allen George7ddbcc02020-11-08 09:51:19 -05002819 #[allow(clippy::approx_constant)]
2820 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002821 o_prot.write_double(double).unwrap();
2822
2823 assert_eq_written_bytes!(o_prot, expected);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002824 }
2825
Allen George0e22c362017-01-30 07:15:00 -05002826 fn assert_no_write<F>(mut write_fn: F)
2827 where
Allen Georgeb0d14132020-03-29 11:48:55 -04002828 F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> crate::Result<()>,
Allen George0e22c362017-01-30 07:15:00 -05002829 {
2830 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002831 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -05002832 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -04002833 }
2834}