blob: 6fa364fa0af100e47407451d14e9ee3cdefc0808 [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
87 let element_count;
88 let possible_element_count = (header & 0xF0) >> 4;
89 if possible_element_count != 15 {
90 // high bits set high if count and type encoded separately
91 element_count = possible_element_count as i32;
92 } else {
Allen George0e22c362017-01-30 07:15:00 -050093 element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -040094 }
95
96 Ok((element_type, element_count))
97 }
98}
99
Allen George0e22c362017-01-30 07:15:00 -0500100impl<T> TInputProtocol for TCompactInputProtocol<T>
101where
102 T: TReadTransport,
103{
Allen Georgeb0d14132020-03-29 11:48:55 -0400104 fn read_message_begin(&mut self) -> crate::Result<TMessageIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400105 let compact_id = self.read_byte()?;
106 if compact_id != COMPACT_PROTOCOL_ID {
Allen Georgeb0d14132020-03-29 11:48:55 -0400107 Err(crate::Error::Protocol(crate::ProtocolError {
108 kind: crate::ProtocolErrorKind::BadVersion,
Allen Georgeef7a1892018-12-16 18:01:37 -0500109 message: format!("invalid compact protocol header {:?}", compact_id),
110 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400111 } else {
112 Ok(())
113 }?;
114
115 let type_and_byte = self.read_byte()?;
116 let received_version = type_and_byte & COMPACT_VERSION_MASK;
117 if received_version != COMPACT_VERSION {
Allen Georgeb0d14132020-03-29 11:48:55 -0400118 Err(crate::Error::Protocol(crate::ProtocolError {
119 kind: crate::ProtocolErrorKind::BadVersion,
Allen Georgeef7a1892018-12-16 18:01:37 -0500120 message: format!(
121 "cannot process compact protocol version {:?}",
122 received_version
Allen George0e22c362017-01-30 07:15:00 -0500123 ),
Allen Georgeef7a1892018-12-16 18:01:37 -0500124 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400125 } else {
126 Ok(())
127 }?;
128
129 // NOTE: unsigned right shift will pad with 0s
130 let message_type: TMessageType = TMessageType::try_from(type_and_byte >> 5)?;
131 let sequence_number = self.read_i32()?;
132 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> {
Marcin Pajkowskib34680f2019-12-02 10:29:16 +0100250 self.transport.read_f64::<LittleEndian>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400251 }
252
Allen Georgeb0d14132020-03-29 11:48:55 -0400253 fn read_string(&mut self) -> crate::Result<String> {
Allen George8b96bfb2016-11-02 08:01:08 -0400254 let bytes = self.read_bytes()?;
255 String::from_utf8(bytes).map_err(From::from)
256 }
257
Allen Georgeb0d14132020-03-29 11:48:55 -0400258 fn read_list_begin(&mut self) -> crate::Result<TListIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400259 let (element_type, element_count) = self.read_list_set_begin()?;
260 Ok(TListIdentifier::new(element_type, element_count))
261 }
262
Allen Georgeb0d14132020-03-29 11:48:55 -0400263 fn read_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400264 Ok(())
265 }
266
Allen Georgeb0d14132020-03-29 11:48:55 -0400267 fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400268 let (element_type, element_count) = self.read_list_set_begin()?;
269 Ok(TSetIdentifier::new(element_type, element_count))
270 }
271
Allen Georgeb0d14132020-03-29 11:48:55 -0400272 fn read_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400273 Ok(())
274 }
275
Allen Georgeb0d14132020-03-29 11:48:55 -0400276 fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier> {
Allen George0e22c362017-01-30 07:15:00 -0500277 let element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400278 if element_count == 0 {
279 Ok(TMapIdentifier::new(None, None, 0))
280 } else {
281 let type_header = self.read_byte()?;
282 let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
283 let val_type = collection_u8_to_type(type_header & 0x0F)?;
284 Ok(TMapIdentifier::new(key_type, val_type, element_count))
285 }
286 }
287
Allen Georgeb0d14132020-03-29 11:48:55 -0400288 fn read_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400289 Ok(())
290 }
291
292 // utility
293 //
294
Allen Georgeb0d14132020-03-29 11:48:55 -0400295 fn read_byte(&mut self) -> crate::Result<u8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400296 let mut buf = [0u8; 1];
Allen George0e22c362017-01-30 07:15:00 -0500297 self.transport
298 .read_exact(&mut buf)
299 .map_err(From::from)
300 .map(|_| buf[0])
Allen George8b96bfb2016-11-02 08:01:08 -0400301 }
302}
303
Vadim Chekand3355af2018-01-05 23:12:47 -0500304impl<T> io::Seek for TCompactInputProtocol<T>
305where
306 T: io::Seek + TReadTransport,
307{
308 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
309 self.transport.seek(pos)
310 }
311}
312
Allen George8b96bfb2016-11-02 08:01:08 -0400313/// Factory for creating instances of `TCompactInputProtocol`.
314#[derive(Default)]
315pub struct TCompactInputProtocolFactory;
316
317impl TCompactInputProtocolFactory {
318 /// Create a `TCompactInputProtocolFactory`.
319 pub fn new() -> TCompactInputProtocolFactory {
320 TCompactInputProtocolFactory {}
321 }
322}
323
324impl TInputProtocolFactory for TCompactInputProtocolFactory {
Danny Browning77d96c12019-08-21 13:41:07 -0600325 fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500326 Box::new(TCompactInputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400327 }
328}
329
330/// Write messages using the Thrift compact protocol.
331///
332/// # Examples
333///
334/// Create and use a `TCompactOutputProtocol`.
335///
336/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -0400337/// use thrift::protocol::{TCompactOutputProtocol, TOutputProtocol};
Allen George0e22c362017-01-30 07:15:00 -0500338/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -0400339///
Allen George0e22c362017-01-30 07:15:00 -0500340/// let mut channel = TTcpChannel::new();
341/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400342///
Allen George0e22c362017-01-30 07:15:00 -0500343/// let mut protocol = TCompactOutputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -0400344///
Allen George0e22c362017-01-30 07:15:00 -0500345/// protocol.write_bool(true).unwrap();
346/// protocol.write_string("test_string").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400347/// ```
Allen George0e22c362017-01-30 07:15:00 -0500348#[derive(Debug)]
349pub struct TCompactOutputProtocol<T>
350where
351 T: TWriteTransport,
352{
Allen George8b96bfb2016-11-02 08:01:08 -0400353 // Identifier of the last field serialized for a struct.
354 last_write_field_id: i16,
Allen George0e22c362017-01-30 07:15:00 -0500355 // Stack of the last written field ids (new entry added each time a nested struct is written).
Allen George8b96bfb2016-11-02 08:01:08 -0400356 write_field_id_stack: Vec<i16>,
357 // Field identifier of the boolean field to be written.
358 // Saved because boolean fields and their value are encoded in a single byte
359 pending_write_bool_field_identifier: Option<TFieldIdentifier>,
360 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -0500361 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -0400362}
363
Allen George0e22c362017-01-30 07:15:00 -0500364impl<T> TCompactOutputProtocol<T>
365where
366 T: TWriteTransport,
367{
Allen George8b96bfb2016-11-02 08:01:08 -0400368 /// Create a `TCompactOutputProtocol` that writes bytes to `transport`.
Allen George0e22c362017-01-30 07:15:00 -0500369 pub fn new(transport: T) -> TCompactOutputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -0400370 TCompactOutputProtocol {
371 last_write_field_id: 0,
372 write_field_id_stack: Vec::new(),
373 pending_write_bool_field_identifier: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500374 transport,
Allen George8b96bfb2016-11-02 08:01:08 -0400375 }
376 }
377
378 // FIXME: field_type as unconstrained u8 is bad
Allen Georgeb0d14132020-03-29 11:48:55 -0400379 fn write_field_header(&mut self, field_type: u8, field_id: i16) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400380 let field_delta = field_id - self.last_write_field_id;
381 if field_delta > 0 && field_delta < 15 {
382 self.write_byte(((field_delta as u8) << 4) | field_type)?;
383 } else {
384 self.write_byte(field_type)?;
385 self.write_i16(field_id)?;
386 }
387 self.last_write_field_id = field_id;
388 Ok(())
389 }
390
Allen Georgeb0d14132020-03-29 11:48:55 -0400391 fn write_list_set_begin(&mut self, element_type: TType, element_count: i32) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400392 let elem_identifier = collection_type_to_u8(element_type);
393 if element_count <= 14 {
394 let header = (element_count as u8) << 4 | elem_identifier;
395 self.write_byte(header)
396 } else {
397 let header = 0xF0 | elem_identifier;
398 self.write_byte(header)?;
399 self.transport
Allen George8b96bfb2016-11-02 08:01:08 -0400400 .write_varint(element_count as u32)
401 .map_err(From::from)
402 .map(|_| ())
403 }
404 }
405
406 fn assert_no_pending_bool_write(&self) {
407 if let Some(ref f) = self.pending_write_bool_field_identifier {
408 panic!("pending bool field {:?} not written", f)
409 }
410 }
411}
412
Allen George0e22c362017-01-30 07:15:00 -0500413impl<T> TOutputProtocol for TCompactOutputProtocol<T>
414where
415 T: TWriteTransport,
416{
Allen Georgeb0d14132020-03-29 11:48:55 -0400417 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400418 self.write_byte(COMPACT_PROTOCOL_ID)?;
419 self.write_byte((u8::from(identifier.message_type) << 5) | COMPACT_VERSION)?;
420 self.write_i32(identifier.sequence_number)?;
421 self.write_string(&identifier.name)?;
422 Ok(())
423 }
424
Allen Georgeb0d14132020-03-29 11:48:55 -0400425 fn write_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400426 self.assert_no_pending_bool_write();
427 Ok(())
428 }
429
Allen Georgeb0d14132020-03-29 11:48:55 -0400430 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400431 self.write_field_id_stack.push(self.last_write_field_id);
432 self.last_write_field_id = 0;
433 Ok(())
434 }
435
Allen Georgeb0d14132020-03-29 11:48:55 -0400436 fn write_struct_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400437 self.assert_no_pending_bool_write();
Allen Georgeef7a1892018-12-16 18:01:37 -0500438 self.last_write_field_id = self
439 .write_field_id_stack
Allen George0e22c362017-01-30 07:15:00 -0500440 .pop()
441 .expect("should have previous field ids");
Allen George8b96bfb2016-11-02 08:01:08 -0400442 Ok(())
443 }
444
Allen Georgeb0d14132020-03-29 11:48:55 -0400445 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400446 match identifier.field_type {
447 TType::Bool => {
448 if self.pending_write_bool_field_identifier.is_some() {
Allen George0e22c362017-01-30 07:15:00 -0500449 panic!(
450 "should not have a pending bool while writing another bool with id: \
Allen Georgeef7a1892018-12-16 18:01:37 -0500451 {:?}",
Allen George0e22c362017-01-30 07:15:00 -0500452 identifier
453 )
Allen George8b96bfb2016-11-02 08:01:08 -0400454 }
455 self.pending_write_bool_field_identifier = Some(identifier.clone());
456 Ok(())
457 }
458 _ => {
459 let field_type = type_to_u8(identifier.field_type);
Allen Georgeef7a1892018-12-16 18:01:37 -0500460 let field_id = identifier.id.expect("non-stop field should have field id");
Allen George8b96bfb2016-11-02 08:01:08 -0400461 self.write_field_header(field_type, field_id)
462 }
463 }
464 }
465
Allen Georgeb0d14132020-03-29 11:48:55 -0400466 fn write_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400467 self.assert_no_pending_bool_write();
468 Ok(())
469 }
470
Allen Georgeb0d14132020-03-29 11:48:55 -0400471 fn write_field_stop(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400472 self.assert_no_pending_bool_write();
473 self.write_byte(type_to_u8(TType::Stop))
474 }
475
Allen Georgeb0d14132020-03-29 11:48:55 -0400476 fn write_bool(&mut self, b: bool) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400477 match self.pending_write_bool_field_identifier.take() {
478 Some(pending) => {
479 let field_id = pending.id.expect("bool field should have a field id");
480 let field_type_as_u8 = if b { 0x01 } else { 0x02 };
481 self.write_field_header(field_type_as_u8, field_id)
482 }
483 None => {
484 if b {
485 self.write_byte(0x01)
486 } else {
487 self.write_byte(0x02)
488 }
489 }
490 }
491 }
492
Allen Georgeb0d14132020-03-29 11:48:55 -0400493 fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500494 self.transport.write_varint(b.len() as u32)?;
495 self.transport.write_all(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400496 }
497
Allen Georgeb0d14132020-03-29 11:48:55 -0400498 fn write_i8(&mut self, i: i8) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400499 self.write_byte(i as u8)
500 }
501
Allen Georgeb0d14132020-03-29 11:48:55 -0400502 fn write_i16(&mut self, i: i16) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500503 self.transport
504 .write_varint(i)
505 .map_err(From::from)
506 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400507 }
508
Allen Georgeb0d14132020-03-29 11:48:55 -0400509 fn write_i32(&mut self, i: i32) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500510 self.transport
511 .write_varint(i)
512 .map_err(From::from)
513 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400514 }
515
Allen Georgeb0d14132020-03-29 11:48:55 -0400516 fn write_i64(&mut self, i: i64) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500517 self.transport
518 .write_varint(i)
519 .map_err(From::from)
520 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400521 }
522
Allen Georgeb0d14132020-03-29 11:48:55 -0400523 fn write_double(&mut self, d: f64) -> crate::Result<()> {
Marcin Pajkowskib34680f2019-12-02 10:29:16 +0100524 self.transport.write_f64::<LittleEndian>(d).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400525 }
526
Allen Georgeb0d14132020-03-29 11:48:55 -0400527 fn write_string(&mut self, s: &str) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400528 self.write_bytes(s.as_bytes())
529 }
530
Allen Georgeb0d14132020-03-29 11:48:55 -0400531 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400532 self.write_list_set_begin(identifier.element_type, identifier.size)
533 }
534
Allen Georgeb0d14132020-03-29 11:48:55 -0400535 fn write_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400536 Ok(())
537 }
538
Allen Georgeb0d14132020-03-29 11:48:55 -0400539 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400540 self.write_list_set_begin(identifier.element_type, identifier.size)
541 }
542
Allen Georgeb0d14132020-03-29 11:48:55 -0400543 fn write_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400544 Ok(())
545 }
546
Allen Georgeb0d14132020-03-29 11:48:55 -0400547 fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400548 if identifier.size == 0 {
549 self.write_byte(0)
550 } else {
Allen George0e22c362017-01-30 07:15:00 -0500551 self.transport.write_varint(identifier.size as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400552
Allen George0e22c362017-01-30 07:15:00 -0500553 let key_type = identifier
554 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400555 .expect("map identifier to write should contain key type");
556 let key_type_byte = collection_type_to_u8(key_type) << 4;
557
Allen George0e22c362017-01-30 07:15:00 -0500558 let val_type = identifier
559 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400560 .expect("map identifier to write should contain value type");
561 let val_type_byte = collection_type_to_u8(val_type);
562
563 let map_type_header = key_type_byte | val_type_byte;
564 self.write_byte(map_type_header)
565 }
566 }
567
Allen Georgeb0d14132020-03-29 11:48:55 -0400568 fn write_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400569 Ok(())
570 }
571
Allen Georgeb0d14132020-03-29 11:48:55 -0400572 fn flush(&mut self) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500573 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400574 }
575
576 // utility
577 //
578
Allen Georgeb0d14132020-03-29 11:48:55 -0400579 fn write_byte(&mut self, b: u8) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500580 self.transport.write(&[b]).map_err(From::from).map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400581 }
582}
583
584/// Factory for creating instances of `TCompactOutputProtocol`.
585#[derive(Default)]
586pub struct TCompactOutputProtocolFactory;
587
588impl TCompactOutputProtocolFactory {
589 /// Create a `TCompactOutputProtocolFactory`.
590 pub fn new() -> TCompactOutputProtocolFactory {
591 TCompactOutputProtocolFactory {}
592 }
593}
594
595impl TOutputProtocolFactory for TCompactOutputProtocolFactory {
Danny Browning77d96c12019-08-21 13:41:07 -0600596 fn create(&self, transport: Box<dyn TWriteTransport + Send>) -> Box<dyn TOutputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500597 Box::new(TCompactOutputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400598 }
599}
600
601fn collection_type_to_u8(field_type: TType) -> u8 {
602 match field_type {
603 TType::Bool => 0x01,
604 f => type_to_u8(f),
605 }
606}
607
608fn type_to_u8(field_type: TType) -> u8 {
609 match field_type {
610 TType::Stop => 0x00,
611 TType::I08 => 0x03, // equivalent to TType::Byte
612 TType::I16 => 0x04,
613 TType::I32 => 0x05,
614 TType::I64 => 0x06,
615 TType::Double => 0x07,
616 TType::String => 0x08,
617 TType::List => 0x09,
618 TType::Set => 0x0A,
619 TType::Map => 0x0B,
620 TType::Struct => 0x0C,
Allen Georgeef7a1892018-12-16 18:01:37 -0500621 _ => panic!(format!(
622 "should not have attempted to convert {} to u8",
623 field_type
624 )),
Allen George8b96bfb2016-11-02 08:01:08 -0400625 }
626}
627
Allen Georgeb0d14132020-03-29 11:48:55 -0400628fn collection_u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400629 match b {
630 0x01 => Ok(TType::Bool),
631 o => u8_to_type(o),
632 }
633}
634
Allen Georgeb0d14132020-03-29 11:48:55 -0400635fn u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400636 match b {
637 0x00 => Ok(TType::Stop),
638 0x03 => Ok(TType::I08), // equivalent to TType::Byte
639 0x04 => Ok(TType::I16),
640 0x05 => Ok(TType::I32),
641 0x06 => Ok(TType::I64),
642 0x07 => Ok(TType::Double),
643 0x08 => Ok(TType::String),
644 0x09 => Ok(TType::List),
645 0x0A => Ok(TType::Set),
646 0x0B => Ok(TType::Map),
647 0x0C => Ok(TType::Struct),
Allen Georgeb0d14132020-03-29 11:48:55 -0400648 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
649 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500650 message: format!("cannot convert {} into TType", unkn),
651 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400652 }
653}
654
655#[cfg(test)]
656mod tests {
657
Allen Georgeb0d14132020-03-29 11:48:55 -0400658 use crate::protocol::{
Allen Georgeef7a1892018-12-16 18:01:37 -0500659 TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
660 TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
661 };
Allen Georgeb0d14132020-03-29 11:48:55 -0400662 use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400663
664 use super::*;
665
666 #[test]
667 fn must_write_message_begin_0() {
Allen George0e22c362017-01-30 07:15:00 -0500668 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400669
Allen Georgeef7a1892018-12-16 18:01:37 -0500670 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
671 "foo",
672 TMessageType::Call,
673 431
674 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400675
Allen George7ddbcc02020-11-08 09:51:19 -0500676 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500677 let expected: [u8; 8] = [
678 0x82, /* protocol ID */
679 0x21, /* message type | protocol version */
680 0xDE,
681 0x06, /* zig-zag varint sequence number */
682 0x03, /* message-name length */
683 0x66,
684 0x6F,
685 0x6F /* "foo" */,
686 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400687
Allen George0e22c362017-01-30 07:15:00 -0500688 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400689 }
690
691 #[test]
692 fn must_write_message_begin_1() {
Allen George0e22c362017-01-30 07:15:00 -0500693 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400694
Allen Georgeef7a1892018-12-16 18:01:37 -0500695 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
696 "bar",
697 TMessageType::Reply,
Allen George7ddbcc02020-11-08 09:51:19 -0500698 991_828
Allen Georgeef7a1892018-12-16 18:01:37 -0500699 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400700
Allen George7ddbcc02020-11-08 09:51:19 -0500701 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500702 let expected: [u8; 9] = [
703 0x82, /* protocol ID */
704 0x41, /* message type | protocol version */
705 0xA8,
706 0x89,
707 0x79, /* zig-zag varint sequence number */
708 0x03, /* message-name length */
709 0x62,
710 0x61,
711 0x72 /* "bar" */,
712 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400713
Allen George0e22c362017-01-30 07:15:00 -0500714 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400715 }
716
717 #[test]
Nik Claytone7917602020-03-05 11:51:15 +0100718 fn must_round_trip_upto_i64_maxvalue() {
719 // See https://issues.apache.org/jira/browse/THRIFT-5131
720 for i in 0..64 {
721 let (mut i_prot, mut o_prot) = test_objects();
722 let val: i64 = ((1u64 << i) - 1) as i64;
723
724 o_prot
725 .write_field_begin(&TFieldIdentifier::new(
726 "val",
727 TType::I64,
728 1
729 ))
730 .unwrap();
731 o_prot.write_i64(val).unwrap();
732 o_prot.write_field_end().unwrap();
733 o_prot.flush().unwrap();
734
735 copy_write_buffer_to_read_buffer!(o_prot);
736
737 i_prot.read_field_begin().unwrap();
738 assert_eq!(val, i_prot.read_i64().unwrap());
739 }
740 }
741
742 #[test]
Allen George8b96bfb2016-11-02 08:01:08 -0400743 fn must_round_trip_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500744 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400745
Allen George7ddbcc02020-11-08 09:51:19 -0500746 let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948);
Allen George8b96bfb2016-11-02 08:01:08 -0400747
748 assert_success!(o_prot.write_message_begin(&ident));
749
Allen George0e22c362017-01-30 07:15:00 -0500750 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400751
752 let res = assert_success!(i_prot.read_message_begin());
753 assert_eq!(&res, &ident);
754 }
755
756 #[test]
757 fn must_write_message_end() {
758 assert_no_write(|o| o.write_message_end());
759 }
760
761 // NOTE: structs and fields are tested together
762 //
763
764 #[test]
765 fn must_write_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500766 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400767
768 // no bytes should be written however
769 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
770
771 // write three fields with tiny field ids
772 // since they're small the field ids will be encoded as deltas
773
774 // since this is the first field (and it's zero) it gets the full varint write
775 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
776 assert_success!(o_prot.write_field_end());
777
778 // since this delta > 0 and < 15 it can be encoded as a delta
779 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
780 assert_success!(o_prot.write_field_end());
781
782 // since this delta > 0 and < 15 it can be encoded as a delta
783 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
784 assert_success!(o_prot.write_field_end());
785
786 // now, finish the struct off
787 assert_success!(o_prot.write_field_stop());
788 assert_success!(o_prot.write_struct_end());
789
Allen George7ddbcc02020-11-08 09:51:19 -0500790 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500791 let expected: [u8; 5] = [
792 0x03, /* field type */
793 0x00, /* first field id */
794 0x44, /* field delta (4) | field type */
795 0x59, /* field delta (5) | field type */
796 0x00 /* field stop */,
797 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400798
Allen George0e22c362017-01-30 07:15:00 -0500799 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400800 }
801
802 #[test]
803 fn must_round_trip_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500804 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400805
806 // no bytes should be written however
807 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
808
809 // write three fields with tiny field ids
810 // since they're small the field ids will be encoded as deltas
811
812 // since this is the first field (and it's zero) it gets the full varint write
813 let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
814 assert_success!(o_prot.write_field_begin(&field_ident_1));
815 assert_success!(o_prot.write_field_end());
816
817 // since this delta > 0 and < 15 it can be encoded as a delta
818 let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
819 assert_success!(o_prot.write_field_begin(&field_ident_2));
820 assert_success!(o_prot.write_field_end());
821
822 // since this delta > 0 and < 15 it can be encoded as a delta
823 let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
824 assert_success!(o_prot.write_field_begin(&field_ident_3));
825 assert_success!(o_prot.write_field_end());
826
827 // now, finish the struct off
828 assert_success!(o_prot.write_field_stop());
829 assert_success!(o_prot.write_struct_end());
830
Allen George0e22c362017-01-30 07:15:00 -0500831 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400832
833 // read the struct back
834 assert_success!(i_prot.read_struct_begin());
835
836 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500837 assert_eq!(
838 read_ident_1,
839 TFieldIdentifier {
840 name: None,
841 ..field_ident_1
842 }
843 );
Allen George8b96bfb2016-11-02 08:01:08 -0400844 assert_success!(i_prot.read_field_end());
845
846 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500847 assert_eq!(
848 read_ident_2,
849 TFieldIdentifier {
850 name: None,
851 ..field_ident_2
852 }
853 );
Allen George8b96bfb2016-11-02 08:01:08 -0400854 assert_success!(i_prot.read_field_end());
855
856 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500857 assert_eq!(
858 read_ident_3,
859 TFieldIdentifier {
860 name: None,
861 ..field_ident_3
862 }
863 );
Allen George8b96bfb2016-11-02 08:01:08 -0400864 assert_success!(i_prot.read_field_end());
865
866 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500867 assert_eq!(
868 read_ident_4,
869 TFieldIdentifier {
870 name: None,
871 field_type: TType::Stop,
872 id: None,
873 }
874 );
Allen George8b96bfb2016-11-02 08:01:08 -0400875
876 assert_success!(i_prot.read_struct_end());
877 }
878
879 #[test]
880 fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500881 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400882
883 // no bytes should be written however
884 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
885
886 // write three fields with tiny field ids
887 // since they're small the field ids will be encoded as deltas
888
889 // gets a delta write
890 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
891 assert_success!(o_prot.write_field_end());
892
893 // since this delta > 0 and < 15 it can be encoded as a delta
894 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
895 assert_success!(o_prot.write_field_end());
896
897 // since this delta > 0 and < 15 it can be encoded as a delta
898 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
899 assert_success!(o_prot.write_field_end());
900
901 // now, finish the struct off
902 assert_success!(o_prot.write_field_stop());
903 assert_success!(o_prot.write_struct_end());
904
Allen George7ddbcc02020-11-08 09:51:19 -0500905 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500906 let expected: [u8; 4] = [
907 0x15, /* field delta (1) | field type */
908 0x1A, /* field delta (1) | field type */
909 0x48, /* field delta (4) | field type */
910 0x00 /* field stop */,
911 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400912
Allen George0e22c362017-01-30 07:15:00 -0500913 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400914 }
915
916 #[test]
917 fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500918 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400919
920 // no bytes should be written however
921 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
922
923 // write three fields with tiny field ids
924 // since they're small the field ids will be encoded as deltas
925
926 // gets a delta write
927 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
928 assert_success!(o_prot.write_field_begin(&field_ident_1));
929 assert_success!(o_prot.write_field_end());
930
931 // since this delta > 0 and < 15 it can be encoded as a delta
932 let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
933 assert_success!(o_prot.write_field_begin(&field_ident_2));
934 assert_success!(o_prot.write_field_end());
935
936 // since this delta > 0 and < 15 it can be encoded as a delta
937 let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
938 assert_success!(o_prot.write_field_begin(&field_ident_3));
939 assert_success!(o_prot.write_field_end());
940
941 // now, finish the struct off
942 assert_success!(o_prot.write_field_stop());
943 assert_success!(o_prot.write_struct_end());
944
Allen George0e22c362017-01-30 07:15:00 -0500945 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400946
947 // read the struct back
948 assert_success!(i_prot.read_struct_begin());
949
950 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500951 assert_eq!(
952 read_ident_1,
953 TFieldIdentifier {
954 name: None,
955 ..field_ident_1
956 }
957 );
Allen George8b96bfb2016-11-02 08:01:08 -0400958 assert_success!(i_prot.read_field_end());
959
960 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500961 assert_eq!(
962 read_ident_2,
963 TFieldIdentifier {
964 name: None,
965 ..field_ident_2
966 }
967 );
Allen George8b96bfb2016-11-02 08:01:08 -0400968 assert_success!(i_prot.read_field_end());
969
970 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500971 assert_eq!(
972 read_ident_3,
973 TFieldIdentifier {
974 name: None,
975 ..field_ident_3
976 }
977 );
Allen George8b96bfb2016-11-02 08:01:08 -0400978 assert_success!(i_prot.read_field_end());
979
980 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500981 assert_eq!(
982 read_ident_4,
983 TFieldIdentifier {
984 name: None,
985 field_type: TType::Stop,
986 id: None,
987 }
988 );
Allen George8b96bfb2016-11-02 08:01:08 -0400989
990 assert_success!(i_prot.read_struct_end());
991 }
992
993 #[test]
994 fn must_write_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500995 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400996
997 // no bytes should be written however
998 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
999
1000 // write three fields with field ids that cannot be encoded as deltas
1001
1002 // since this is the first field (and it's zero) it gets the full varint write
1003 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
1004 assert_success!(o_prot.write_field_end());
1005
1006 // since this delta is > 15 it is encoded as a zig-zag varint
1007 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
1008 assert_success!(o_prot.write_field_end());
1009
1010 // since this delta is > 15 it is encoded as a zig-zag varint
1011 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
1012 assert_success!(o_prot.write_field_end());
1013
1014 // now, finish the struct off
1015 assert_success!(o_prot.write_field_stop());
1016 assert_success!(o_prot.write_struct_end());
1017
Allen George7ddbcc02020-11-08 09:51:19 -05001018 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001019 let expected: [u8; 8] = [
1020 0x05, /* field type */
1021 0x00, /* first field id */
1022 0x06, /* field type */
1023 0x20, /* zig-zag varint field id */
1024 0x0A, /* field type */
1025 0xC6,
1026 0x01, /* zig-zag varint field id */
1027 0x00 /* field stop */,
1028 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001029
Allen George0e22c362017-01-30 07:15:00 -05001030 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001031 }
1032
1033 #[test]
1034 fn must_round_trip_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001035 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001036
1037 // no bytes should be written however
1038 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1039
1040 // write three fields with field ids that cannot be encoded as deltas
1041
1042 // since this is the first field (and it's zero) it gets the full varint write
1043 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
1044 assert_success!(o_prot.write_field_begin(&field_ident_1));
1045 assert_success!(o_prot.write_field_end());
1046
1047 // since this delta is > 15 it is encoded as a zig-zag varint
1048 let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
1049 assert_success!(o_prot.write_field_begin(&field_ident_2));
1050 assert_success!(o_prot.write_field_end());
1051
1052 // since this delta is > 15 it is encoded as a zig-zag varint
1053 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
1054 assert_success!(o_prot.write_field_begin(&field_ident_3));
1055 assert_success!(o_prot.write_field_end());
1056
1057 // now, finish the struct off
1058 assert_success!(o_prot.write_field_stop());
1059 assert_success!(o_prot.write_struct_end());
1060
Allen George0e22c362017-01-30 07:15:00 -05001061 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001062
1063 // read the struct back
1064 assert_success!(i_prot.read_struct_begin());
1065
1066 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001067 assert_eq!(
1068 read_ident_1,
1069 TFieldIdentifier {
1070 name: None,
1071 ..field_ident_1
1072 }
1073 );
Allen George8b96bfb2016-11-02 08:01:08 -04001074 assert_success!(i_prot.read_field_end());
1075
1076 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001077 assert_eq!(
1078 read_ident_2,
1079 TFieldIdentifier {
1080 name: None,
1081 ..field_ident_2
1082 }
1083 );
Allen George8b96bfb2016-11-02 08:01:08 -04001084 assert_success!(i_prot.read_field_end());
1085
1086 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001087 assert_eq!(
1088 read_ident_3,
1089 TFieldIdentifier {
1090 name: None,
1091 ..field_ident_3
1092 }
1093 );
Allen George8b96bfb2016-11-02 08:01:08 -04001094 assert_success!(i_prot.read_field_end());
1095
1096 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001097 assert_eq!(
1098 read_ident_4,
1099 TFieldIdentifier {
1100 name: None,
1101 field_type: TType::Stop,
1102 id: None,
1103 }
1104 );
Allen George8b96bfb2016-11-02 08:01:08 -04001105
1106 assert_success!(i_prot.read_struct_end());
1107 }
1108
1109 #[test]
1110 fn must_write_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001111 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001112
1113 // no bytes should be written however
1114 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1115
1116 // write three fields with field ids that cannot be encoded as deltas
1117
1118 // since the delta is > 0 and < 15 it gets a delta write
1119 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1120 assert_success!(o_prot.write_field_end());
1121
1122 // since this delta > 0 and < 15 it gets a delta write
1123 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1124 assert_success!(o_prot.write_field_end());
1125
1126 // since this delta is > 15 it is encoded as a zig-zag varint
1127 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
1128 assert_success!(o_prot.write_field_end());
1129
1130 // since this delta is > 15 it is encoded as a zig-zag varint
1131 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
1132 assert_success!(o_prot.write_field_end());
1133
1134 // since this is only 3 up from the previous it is recorded as a delta
1135 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
1136 assert_success!(o_prot.write_field_end());
1137
1138 // now, finish the struct off
1139 assert_success!(o_prot.write_field_stop());
1140 assert_success!(o_prot.write_struct_end());
1141
Allen George7ddbcc02020-11-08 09:51:19 -05001142 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001143 let expected: [u8; 10] = [
1144 0x16, /* field delta (1) | field type */
1145 0x85, /* field delta (8) | field type */
1146 0x0A, /* field type */
1147 0xD0,
1148 0x0F, /* zig-zag varint field id */
1149 0x0A, /* field type */
1150 0xA2,
1151 0x1F, /* zig-zag varint field id */
1152 0x3A, /* field delta (3) | field type */
1153 0x00 /* field stop */,
1154 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001155
Allen George0e22c362017-01-30 07:15:00 -05001156 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001157 }
1158
Allen George7ddbcc02020-11-08 09:51:19 -05001159 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001160 #[test]
1161 fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001162 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001163
1164 // no bytes should be written however
1165 let struct_ident = TStructIdentifier::new("foo");
1166 assert_success!(o_prot.write_struct_begin(&struct_ident));
1167
1168 // write three fields with field ids that cannot be encoded as deltas
1169
1170 // since the delta is > 0 and < 15 it gets a delta write
1171 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1172 assert_success!(o_prot.write_field_begin(&field_ident_1));
1173 assert_success!(o_prot.write_field_end());
1174
1175 // since this delta > 0 and < 15 it gets a delta write
1176 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1177 assert_success!(o_prot.write_field_begin(&field_ident_2));
1178 assert_success!(o_prot.write_field_end());
1179
1180 // since this delta is > 15 it is encoded as a zig-zag varint
1181 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
1182 assert_success!(o_prot.write_field_begin(&field_ident_3));
1183 assert_success!(o_prot.write_field_end());
1184
1185 // since this delta is > 15 it is encoded as a zig-zag varint
1186 let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
1187 assert_success!(o_prot.write_field_begin(&field_ident_4));
1188 assert_success!(o_prot.write_field_end());
1189
1190 // since this is only 3 up from the previous it is recorded as a delta
1191 let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
1192 assert_success!(o_prot.write_field_begin(&field_ident_5));
1193 assert_success!(o_prot.write_field_end());
1194
1195 // now, finish the struct off
1196 assert_success!(o_prot.write_field_stop());
1197 assert_success!(o_prot.write_struct_end());
1198
Allen George0e22c362017-01-30 07:15:00 -05001199 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001200
1201 // read the struct back
1202 assert_success!(i_prot.read_struct_begin());
1203
1204 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001205 assert_eq!(
1206 read_ident_1,
1207 TFieldIdentifier {
1208 name: None,
1209 ..field_ident_1
1210 }
1211 );
Allen George8b96bfb2016-11-02 08:01:08 -04001212 assert_success!(i_prot.read_field_end());
1213
1214 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001215 assert_eq!(
1216 read_ident_2,
1217 TFieldIdentifier {
1218 name: None,
1219 ..field_ident_2
1220 }
1221 );
Allen George8b96bfb2016-11-02 08:01:08 -04001222 assert_success!(i_prot.read_field_end());
1223
1224 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001225 assert_eq!(
1226 read_ident_3,
1227 TFieldIdentifier {
1228 name: None,
1229 ..field_ident_3
1230 }
1231 );
Allen George8b96bfb2016-11-02 08:01:08 -04001232 assert_success!(i_prot.read_field_end());
1233
1234 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001235 assert_eq!(
1236 read_ident_4,
1237 TFieldIdentifier {
1238 name: None,
1239 ..field_ident_4
1240 }
1241 );
Allen George8b96bfb2016-11-02 08:01:08 -04001242 assert_success!(i_prot.read_field_end());
1243
1244 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001245 assert_eq!(
1246 read_ident_5,
1247 TFieldIdentifier {
1248 name: None,
1249 ..field_ident_5
1250 }
1251 );
Allen George8b96bfb2016-11-02 08:01:08 -04001252 assert_success!(i_prot.read_field_end());
1253
1254 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001255 assert_eq!(
1256 read_ident_6,
1257 TFieldIdentifier {
1258 name: None,
1259 field_type: TType::Stop,
1260 id: None,
1261 }
1262 );
Allen George8b96bfb2016-11-02 08:01:08 -04001263
1264 assert_success!(i_prot.read_struct_end());
1265 }
1266
1267 #[test]
1268 fn must_write_nested_structs_0() {
1269 // last field of the containing struct is a delta
1270 // first field of the the contained struct is a delta
1271
Allen George0e22c362017-01-30 07:15:00 -05001272 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001273
1274 // start containing struct
1275 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1276
1277 // containing struct
1278 // since the delta is > 0 and < 15 it gets a delta write
1279 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1280 assert_success!(o_prot.write_field_end());
1281
1282 // containing struct
1283 // since this delta > 0 and < 15 it gets a delta write
1284 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1285 assert_success!(o_prot.write_field_end());
1286
1287 // start contained struct
1288 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1289
1290 // contained struct
1291 // since the delta is > 0 and < 15 it gets a delta write
1292 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
1293 assert_success!(o_prot.write_field_end());
1294
1295 // contained struct
1296 // since this delta > 15 it gets a full write
1297 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1298 assert_success!(o_prot.write_field_end());
1299
1300 // end contained struct
1301 assert_success!(o_prot.write_field_stop());
1302 assert_success!(o_prot.write_struct_end());
1303
1304 // end containing struct
1305 assert_success!(o_prot.write_field_stop());
1306 assert_success!(o_prot.write_struct_end());
1307
Allen George7ddbcc02020-11-08 09:51:19 -05001308 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001309 let expected: [u8; 7] = [
1310 0x16, /* field delta (1) | field type */
1311 0x85, /* field delta (8) | field type */
1312 0x73, /* field delta (7) | field type */
1313 0x07, /* field type */
1314 0x30, /* zig-zag varint field id */
1315 0x00, /* field stop - contained */
1316 0x00 /* field stop - containing */,
1317 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001318
Allen George0e22c362017-01-30 07:15:00 -05001319 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001320 }
1321
Allen George7ddbcc02020-11-08 09:51:19 -05001322 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001323 #[test]
1324 fn must_round_trip_nested_structs_0() {
1325 // last field of the containing struct is a delta
1326 // first field of the the contained struct is a delta
1327
Allen George0e22c362017-01-30 07:15:00 -05001328 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001329
1330 // start containing struct
1331 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1332
1333 // containing struct
1334 // since the delta is > 0 and < 15 it gets a delta write
1335 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1336 assert_success!(o_prot.write_field_begin(&field_ident_1));
1337 assert_success!(o_prot.write_field_end());
1338
1339 // containing struct
1340 // since this delta > 0 and < 15 it gets a delta write
1341 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1342 assert_success!(o_prot.write_field_begin(&field_ident_2));
1343 assert_success!(o_prot.write_field_end());
1344
1345 // start contained struct
1346 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1347
1348 // contained struct
1349 // since the delta is > 0 and < 15 it gets a delta write
1350 let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
1351 assert_success!(o_prot.write_field_begin(&field_ident_3));
1352 assert_success!(o_prot.write_field_end());
1353
1354 // contained struct
1355 // since this delta > 15 it gets a full write
1356 let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
1357 assert_success!(o_prot.write_field_begin(&field_ident_4));
1358 assert_success!(o_prot.write_field_end());
1359
1360 // end contained struct
1361 assert_success!(o_prot.write_field_stop());
1362 assert_success!(o_prot.write_struct_end());
1363
1364 // end containing struct
1365 assert_success!(o_prot.write_field_stop());
1366 assert_success!(o_prot.write_struct_end());
1367
Allen George0e22c362017-01-30 07:15:00 -05001368 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001369
1370 // read containing struct back
1371 assert_success!(i_prot.read_struct_begin());
1372
1373 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001374 assert_eq!(
1375 read_ident_1,
1376 TFieldIdentifier {
1377 name: None,
1378 ..field_ident_1
1379 }
1380 );
Allen George8b96bfb2016-11-02 08:01:08 -04001381 assert_success!(i_prot.read_field_end());
1382
1383 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001384 assert_eq!(
1385 read_ident_2,
1386 TFieldIdentifier {
1387 name: None,
1388 ..field_ident_2
1389 }
1390 );
Allen George8b96bfb2016-11-02 08:01:08 -04001391 assert_success!(i_prot.read_field_end());
1392
1393 // read contained struct back
1394 assert_success!(i_prot.read_struct_begin());
1395
1396 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001397 assert_eq!(
1398 read_ident_3,
1399 TFieldIdentifier {
1400 name: None,
1401 ..field_ident_3
1402 }
1403 );
Allen George8b96bfb2016-11-02 08:01:08 -04001404 assert_success!(i_prot.read_field_end());
1405
1406 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001407 assert_eq!(
1408 read_ident_4,
1409 TFieldIdentifier {
1410 name: None,
1411 ..field_ident_4
1412 }
1413 );
Allen George8b96bfb2016-11-02 08:01:08 -04001414 assert_success!(i_prot.read_field_end());
1415
1416 // end contained struct
1417 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001418 assert_eq!(
1419 read_ident_6,
1420 TFieldIdentifier {
1421 name: None,
1422 field_type: TType::Stop,
1423 id: None,
1424 }
1425 );
Allen George8b96bfb2016-11-02 08:01:08 -04001426 assert_success!(i_prot.read_struct_end());
1427
1428 // end containing struct
1429 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001430 assert_eq!(
1431 read_ident_7,
1432 TFieldIdentifier {
1433 name: None,
1434 field_type: TType::Stop,
1435 id: None,
1436 }
1437 );
Allen George8b96bfb2016-11-02 08:01:08 -04001438 assert_success!(i_prot.read_struct_end());
1439 }
1440
1441 #[test]
1442 fn must_write_nested_structs_1() {
1443 // last field of the containing struct is a delta
1444 // first field of the the contained struct is a full write
1445
Allen George0e22c362017-01-30 07:15:00 -05001446 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001447
1448 // start containing struct
1449 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1450
1451 // containing struct
1452 // since the delta is > 0 and < 15 it gets a delta write
1453 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1454 assert_success!(o_prot.write_field_end());
1455
1456 // containing struct
1457 // since this delta > 0 and < 15 it gets a delta write
1458 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1459 assert_success!(o_prot.write_field_end());
1460
1461 // start contained struct
1462 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1463
1464 // contained struct
1465 // since this delta > 15 it gets a full write
1466 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1467 assert_success!(o_prot.write_field_end());
1468
1469 // contained struct
1470 // since the delta is > 0 and < 15 it gets a delta write
1471 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1472 assert_success!(o_prot.write_field_end());
1473
1474 // end contained struct
1475 assert_success!(o_prot.write_field_stop());
1476 assert_success!(o_prot.write_struct_end());
1477
1478 // end containing struct
1479 assert_success!(o_prot.write_field_stop());
1480 assert_success!(o_prot.write_struct_end());
1481
Allen George7ddbcc02020-11-08 09:51:19 -05001482 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001483 let expected: [u8; 7] = [
1484 0x16, /* field delta (1) | field type */
1485 0x85, /* field delta (8) | field type */
1486 0x07, /* field type */
1487 0x30, /* zig-zag varint field id */
1488 0x33, /* field delta (3) | field type */
1489 0x00, /* field stop - contained */
1490 0x00 /* field stop - containing */,
1491 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001492
Allen George0e22c362017-01-30 07:15:00 -05001493 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001494 }
1495
Allen George7ddbcc02020-11-08 09:51:19 -05001496 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001497 #[test]
1498 fn must_round_trip_nested_structs_1() {
1499 // last field of the containing struct is a delta
1500 // first field of the the contained struct is a full write
1501
Allen George0e22c362017-01-30 07:15:00 -05001502 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001503
1504 // start containing struct
1505 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1506
1507 // containing struct
1508 // since the delta is > 0 and < 15 it gets a delta write
1509 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1510 assert_success!(o_prot.write_field_begin(&field_ident_1));
1511 assert_success!(o_prot.write_field_end());
1512
1513 // containing struct
1514 // since this delta > 0 and < 15 it gets a delta write
1515 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1516 assert_success!(o_prot.write_field_begin(&field_ident_2));
1517 assert_success!(o_prot.write_field_end());
1518
1519 // start contained struct
1520 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1521
1522 // contained struct
1523 // since this delta > 15 it gets a full write
1524 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
1525 assert_success!(o_prot.write_field_begin(&field_ident_3));
1526 assert_success!(o_prot.write_field_end());
1527
1528 // contained struct
1529 // since the delta is > 0 and < 15 it gets a delta write
1530 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
1531 assert_success!(o_prot.write_field_begin(&field_ident_4));
1532 assert_success!(o_prot.write_field_end());
1533
1534 // end contained struct
1535 assert_success!(o_prot.write_field_stop());
1536 assert_success!(o_prot.write_struct_end());
1537
1538 // end containing struct
1539 assert_success!(o_prot.write_field_stop());
1540 assert_success!(o_prot.write_struct_end());
1541
Allen George0e22c362017-01-30 07:15:00 -05001542 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001543
1544 // read containing struct back
1545 assert_success!(i_prot.read_struct_begin());
1546
1547 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001548 assert_eq!(
1549 read_ident_1,
1550 TFieldIdentifier {
1551 name: None,
1552 ..field_ident_1
1553 }
1554 );
Allen George8b96bfb2016-11-02 08:01:08 -04001555 assert_success!(i_prot.read_field_end());
1556
1557 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001558 assert_eq!(
1559 read_ident_2,
1560 TFieldIdentifier {
1561 name: None,
1562 ..field_ident_2
1563 }
1564 );
Allen George8b96bfb2016-11-02 08:01:08 -04001565 assert_success!(i_prot.read_field_end());
1566
1567 // read contained struct back
1568 assert_success!(i_prot.read_struct_begin());
1569
1570 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001571 assert_eq!(
1572 read_ident_3,
1573 TFieldIdentifier {
1574 name: None,
1575 ..field_ident_3
1576 }
1577 );
Allen George8b96bfb2016-11-02 08:01:08 -04001578 assert_success!(i_prot.read_field_end());
1579
1580 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001581 assert_eq!(
1582 read_ident_4,
1583 TFieldIdentifier {
1584 name: None,
1585 ..field_ident_4
1586 }
1587 );
Allen George8b96bfb2016-11-02 08:01:08 -04001588 assert_success!(i_prot.read_field_end());
1589
1590 // end contained struct
1591 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001592 assert_eq!(
1593 read_ident_6,
1594 TFieldIdentifier {
1595 name: None,
1596 field_type: TType::Stop,
1597 id: None,
1598 }
1599 );
Allen George8b96bfb2016-11-02 08:01:08 -04001600 assert_success!(i_prot.read_struct_end());
1601
1602 // end containing struct
1603 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001604 assert_eq!(
1605 read_ident_7,
1606 TFieldIdentifier {
1607 name: None,
1608 field_type: TType::Stop,
1609 id: None,
1610 }
1611 );
Allen George8b96bfb2016-11-02 08:01:08 -04001612 assert_success!(i_prot.read_struct_end());
1613 }
1614
1615 #[test]
1616 fn must_write_nested_structs_2() {
1617 // last field of the containing struct is a full write
1618 // first field of the the contained struct is a delta write
1619
Allen George0e22c362017-01-30 07:15:00 -05001620 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001621
1622 // start containing struct
1623 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1624
1625 // containing struct
1626 // since the delta is > 0 and < 15 it gets a delta write
1627 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1628 assert_success!(o_prot.write_field_end());
1629
1630 // containing struct
1631 // since this delta > 15 it gets a full write
1632 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
1633 assert_success!(o_prot.write_field_end());
1634
1635 // start contained struct
1636 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1637
1638 // contained struct
1639 // since this delta > 0 and < 15 it gets a delta write
1640 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
1641 assert_success!(o_prot.write_field_end());
1642
1643 // contained struct
1644 // since the delta is > 0 and < 15 it gets a delta write
1645 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
1646 assert_success!(o_prot.write_field_end());
1647
1648 // end contained struct
1649 assert_success!(o_prot.write_field_stop());
1650 assert_success!(o_prot.write_struct_end());
1651
1652 // end containing struct
1653 assert_success!(o_prot.write_field_stop());
1654 assert_success!(o_prot.write_struct_end());
1655
Allen George7ddbcc02020-11-08 09:51:19 -05001656 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001657 let expected: [u8; 7] = [
1658 0x16, /* field delta (1) | field type */
1659 0x08, /* field type */
1660 0x2A, /* zig-zag varint field id */
1661 0x77, /* field delta(7) | field type */
1662 0x33, /* field delta (3) | field type */
1663 0x00, /* field stop - contained */
1664 0x00 /* field stop - containing */,
1665 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001666
Allen George0e22c362017-01-30 07:15:00 -05001667 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001668 }
1669
Allen George7ddbcc02020-11-08 09:51:19 -05001670 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001671 #[test]
1672 fn must_round_trip_nested_structs_2() {
Allen George0e22c362017-01-30 07:15:00 -05001673 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001674
1675 // start containing struct
1676 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1677
1678 // containing struct
1679 // since the delta is > 0 and < 15 it gets a delta write
1680 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1681 assert_success!(o_prot.write_field_begin(&field_ident_1));
1682 assert_success!(o_prot.write_field_end());
1683
1684 // containing struct
1685 // since this delta > 15 it gets a full write
1686 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
1687 assert_success!(o_prot.write_field_begin(&field_ident_2));
1688 assert_success!(o_prot.write_field_end());
1689
1690 // start contained struct
1691 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1692
1693 // contained struct
1694 // since this delta > 0 and < 15 it gets a delta write
1695 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
1696 assert_success!(o_prot.write_field_begin(&field_ident_3));
1697 assert_success!(o_prot.write_field_end());
1698
1699 // contained struct
1700 // since the delta is > 0 and < 15 it gets a delta write
1701 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
1702 assert_success!(o_prot.write_field_begin(&field_ident_4));
1703 assert_success!(o_prot.write_field_end());
1704
1705 // end contained struct
1706 assert_success!(o_prot.write_field_stop());
1707 assert_success!(o_prot.write_struct_end());
1708
1709 // end containing struct
1710 assert_success!(o_prot.write_field_stop());
1711 assert_success!(o_prot.write_struct_end());
1712
Allen George0e22c362017-01-30 07:15:00 -05001713 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001714
1715 // read containing struct back
1716 assert_success!(i_prot.read_struct_begin());
1717
1718 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001719 assert_eq!(
1720 read_ident_1,
1721 TFieldIdentifier {
1722 name: None,
1723 ..field_ident_1
1724 }
1725 );
Allen George8b96bfb2016-11-02 08:01:08 -04001726 assert_success!(i_prot.read_field_end());
1727
1728 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001729 assert_eq!(
1730 read_ident_2,
1731 TFieldIdentifier {
1732 name: None,
1733 ..field_ident_2
1734 }
1735 );
Allen George8b96bfb2016-11-02 08:01:08 -04001736 assert_success!(i_prot.read_field_end());
1737
1738 // read contained struct back
1739 assert_success!(i_prot.read_struct_begin());
1740
1741 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001742 assert_eq!(
1743 read_ident_3,
1744 TFieldIdentifier {
1745 name: None,
1746 ..field_ident_3
1747 }
1748 );
Allen George8b96bfb2016-11-02 08:01:08 -04001749 assert_success!(i_prot.read_field_end());
1750
1751 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001752 assert_eq!(
1753 read_ident_4,
1754 TFieldIdentifier {
1755 name: None,
1756 ..field_ident_4
1757 }
1758 );
Allen George8b96bfb2016-11-02 08:01:08 -04001759 assert_success!(i_prot.read_field_end());
1760
1761 // end contained struct
1762 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001763 assert_eq!(
1764 read_ident_6,
1765 TFieldIdentifier {
1766 name: None,
1767 field_type: TType::Stop,
1768 id: None,
1769 }
1770 );
Allen George8b96bfb2016-11-02 08:01:08 -04001771 assert_success!(i_prot.read_struct_end());
1772
1773 // end containing struct
1774 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001775 assert_eq!(
1776 read_ident_7,
1777 TFieldIdentifier {
1778 name: None,
1779 field_type: TType::Stop,
1780 id: None,
1781 }
1782 );
Allen George8b96bfb2016-11-02 08:01:08 -04001783 assert_success!(i_prot.read_struct_end());
1784 }
1785
1786 #[test]
1787 fn must_write_nested_structs_3() {
1788 // last field of the containing struct is a full write
1789 // first field of the the contained struct is a full write
1790
Allen George0e22c362017-01-30 07:15:00 -05001791 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001792
1793 // start containing struct
1794 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1795
1796 // containing struct
1797 // since the delta is > 0 and < 15 it gets a delta write
1798 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1799 assert_success!(o_prot.write_field_end());
1800
1801 // containing struct
1802 // since this delta > 15 it gets a full write
1803 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
1804 assert_success!(o_prot.write_field_end());
1805
1806 // start contained struct
1807 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1808
1809 // contained struct
1810 // since this delta > 15 it gets a full write
1811 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
1812 assert_success!(o_prot.write_field_end());
1813
1814 // contained struct
1815 // since the delta is > 0 and < 15 it gets a delta write
1816 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1817 assert_success!(o_prot.write_field_end());
1818
1819 // end contained struct
1820 assert_success!(o_prot.write_field_stop());
1821 assert_success!(o_prot.write_struct_end());
1822
1823 // end containing struct
1824 assert_success!(o_prot.write_field_stop());
1825 assert_success!(o_prot.write_struct_end());
1826
Allen George7ddbcc02020-11-08 09:51:19 -05001827 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001828 let expected: [u8; 8] = [
1829 0x16, /* field delta (1) | field type */
1830 0x08, /* field type */
1831 0x2A, /* zig-zag varint field id */
1832 0x07, /* field type */
1833 0x2A, /* zig-zag varint field id */
1834 0x63, /* field delta (6) | field type */
1835 0x00, /* field stop - contained */
1836 0x00 /* field stop - containing */,
1837 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001838
Allen George0e22c362017-01-30 07:15:00 -05001839 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001840 }
1841
Allen George7ddbcc02020-11-08 09:51:19 -05001842 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001843 #[test]
1844 fn must_round_trip_nested_structs_3() {
1845 // last field of the containing struct is a full write
1846 // first field of the the contained struct is a full write
1847
Allen George0e22c362017-01-30 07:15:00 -05001848 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001849
1850 // start containing struct
1851 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1852
1853 // containing struct
1854 // since the delta is > 0 and < 15 it gets a delta write
1855 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1856 assert_success!(o_prot.write_field_begin(&field_ident_1));
1857 assert_success!(o_prot.write_field_end());
1858
1859 // containing struct
1860 // since this delta > 15 it gets a full write
1861 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
1862 assert_success!(o_prot.write_field_begin(&field_ident_2));
1863 assert_success!(o_prot.write_field_end());
1864
1865 // start contained struct
1866 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1867
1868 // contained struct
1869 // since this delta > 15 it gets a full write
1870 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
1871 assert_success!(o_prot.write_field_begin(&field_ident_3));
1872 assert_success!(o_prot.write_field_end());
1873
1874 // contained struct
1875 // since the delta is > 0 and < 15 it gets a delta write
1876 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
1877 assert_success!(o_prot.write_field_begin(&field_ident_4));
1878 assert_success!(o_prot.write_field_end());
1879
1880 // end contained struct
1881 assert_success!(o_prot.write_field_stop());
1882 assert_success!(o_prot.write_struct_end());
1883
1884 // end containing struct
1885 assert_success!(o_prot.write_field_stop());
1886 assert_success!(o_prot.write_struct_end());
1887
Allen George0e22c362017-01-30 07:15:00 -05001888 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001889
1890 // read containing struct back
1891 assert_success!(i_prot.read_struct_begin());
1892
1893 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001894 assert_eq!(
1895 read_ident_1,
1896 TFieldIdentifier {
1897 name: None,
1898 ..field_ident_1
1899 }
1900 );
Allen George8b96bfb2016-11-02 08:01:08 -04001901 assert_success!(i_prot.read_field_end());
1902
1903 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001904 assert_eq!(
1905 read_ident_2,
1906 TFieldIdentifier {
1907 name: None,
1908 ..field_ident_2
1909 }
1910 );
Allen George8b96bfb2016-11-02 08:01:08 -04001911 assert_success!(i_prot.read_field_end());
1912
1913 // read contained struct back
1914 assert_success!(i_prot.read_struct_begin());
1915
1916 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001917 assert_eq!(
1918 read_ident_3,
1919 TFieldIdentifier {
1920 name: None,
1921 ..field_ident_3
1922 }
1923 );
Allen George8b96bfb2016-11-02 08:01:08 -04001924 assert_success!(i_prot.read_field_end());
1925
1926 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001927 assert_eq!(
1928 read_ident_4,
1929 TFieldIdentifier {
1930 name: None,
1931 ..field_ident_4
1932 }
1933 );
Allen George8b96bfb2016-11-02 08:01:08 -04001934 assert_success!(i_prot.read_field_end());
1935
1936 // end contained struct
1937 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001938 assert_eq!(
1939 read_ident_6,
1940 TFieldIdentifier {
1941 name: None,
1942 field_type: TType::Stop,
1943 id: None,
1944 }
1945 );
Allen George8b96bfb2016-11-02 08:01:08 -04001946 assert_success!(i_prot.read_struct_end());
1947
1948 // end containing struct
1949 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001950 assert_eq!(
1951 read_ident_7,
1952 TFieldIdentifier {
1953 name: None,
1954 field_type: TType::Stop,
1955 id: None,
1956 }
1957 );
Allen George8b96bfb2016-11-02 08:01:08 -04001958 assert_success!(i_prot.read_struct_end());
1959 }
1960
1961 #[test]
1962 fn must_write_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05001963 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001964
1965 // no bytes should be written however
1966 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1967
1968 // write three fields with field ids that cannot be encoded as deltas
1969
1970 // since the delta is > 0 and < 16 it gets a delta write
1971 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
1972 assert_success!(o_prot.write_bool(true));
1973 assert_success!(o_prot.write_field_end());
1974
1975 // since this delta > 0 and < 15 it gets a delta write
1976 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
1977 assert_success!(o_prot.write_bool(false));
1978 assert_success!(o_prot.write_field_end());
1979
1980 // since this delta > 15 it gets a full write
1981 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
1982 assert_success!(o_prot.write_bool(true));
1983 assert_success!(o_prot.write_field_end());
1984
1985 // since this delta > 15 it gets a full write
1986 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
1987 assert_success!(o_prot.write_bool(false));
1988 assert_success!(o_prot.write_field_end());
1989
1990 // now, finish the struct off
1991 assert_success!(o_prot.write_field_stop());
1992 assert_success!(o_prot.write_struct_end());
1993
Allen George7ddbcc02020-11-08 09:51:19 -05001994 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001995 let expected: [u8; 7] = [
1996 0x11, /* field delta (1) | true */
1997 0x82, /* field delta (8) | false */
1998 0x01, /* true */
1999 0x34, /* field id */
2000 0x02, /* false */
2001 0x5A, /* field id */
2002 0x00 /* stop field */,
2003 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002004
Allen George0e22c362017-01-30 07:15:00 -05002005 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002006 }
2007
Allen George7ddbcc02020-11-08 09:51:19 -05002008 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002009 #[test]
2010 fn must_round_trip_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002011 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002012
2013 // no bytes should be written however
2014 let struct_ident = TStructIdentifier::new("foo");
2015 assert_success!(o_prot.write_struct_begin(&struct_ident));
2016
2017 // write two fields
2018
2019 // since the delta is > 0 and < 16 it gets a delta write
2020 let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
2021 assert_success!(o_prot.write_field_begin(&field_ident_1));
2022 assert_success!(o_prot.write_bool(true));
2023 assert_success!(o_prot.write_field_end());
2024
2025 // since this delta > 0 and < 15 it gets a delta write
2026 let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
2027 assert_success!(o_prot.write_field_begin(&field_ident_2));
2028 assert_success!(o_prot.write_bool(false));
2029 assert_success!(o_prot.write_field_end());
2030
2031 // since this delta > 15 it gets a full write
2032 let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
2033 assert_success!(o_prot.write_field_begin(&field_ident_3));
2034 assert_success!(o_prot.write_bool(true));
2035 assert_success!(o_prot.write_field_end());
2036
2037 // since this delta > 15 it gets a full write
2038 let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
2039 assert_success!(o_prot.write_field_begin(&field_ident_4));
2040 assert_success!(o_prot.write_bool(false));
2041 assert_success!(o_prot.write_field_end());
2042
2043 // now, finish the struct off
2044 assert_success!(o_prot.write_field_stop());
2045 assert_success!(o_prot.write_struct_end());
2046
Allen George0e22c362017-01-30 07:15:00 -05002047 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002048
2049 // read the struct back
2050 assert_success!(i_prot.read_struct_begin());
2051
2052 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002053 assert_eq!(
2054 read_ident_1,
2055 TFieldIdentifier {
2056 name: None,
2057 ..field_ident_1
2058 }
2059 );
Allen George8b96bfb2016-11-02 08:01:08 -04002060 let read_value_1 = assert_success!(i_prot.read_bool());
2061 assert_eq!(read_value_1, true);
2062 assert_success!(i_prot.read_field_end());
2063
2064 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002065 assert_eq!(
2066 read_ident_2,
2067 TFieldIdentifier {
2068 name: None,
2069 ..field_ident_2
2070 }
2071 );
Allen George8b96bfb2016-11-02 08:01:08 -04002072 let read_value_2 = assert_success!(i_prot.read_bool());
2073 assert_eq!(read_value_2, false);
2074 assert_success!(i_prot.read_field_end());
2075
2076 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002077 assert_eq!(
2078 read_ident_3,
2079 TFieldIdentifier {
2080 name: None,
2081 ..field_ident_3
2082 }
2083 );
Allen George8b96bfb2016-11-02 08:01:08 -04002084 let read_value_3 = assert_success!(i_prot.read_bool());
2085 assert_eq!(read_value_3, true);
2086 assert_success!(i_prot.read_field_end());
2087
2088 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002089 assert_eq!(
2090 read_ident_4,
2091 TFieldIdentifier {
2092 name: None,
2093 ..field_ident_4
2094 }
2095 );
Allen George8b96bfb2016-11-02 08:01:08 -04002096 let read_value_4 = assert_success!(i_prot.read_bool());
2097 assert_eq!(read_value_4, false);
2098 assert_success!(i_prot.read_field_end());
2099
2100 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002101 assert_eq!(
2102 read_ident_5,
2103 TFieldIdentifier {
2104 name: None,
2105 field_type: TType::Stop,
2106 id: None,
2107 }
2108 );
Allen George8b96bfb2016-11-02 08:01:08 -04002109
2110 assert_success!(i_prot.read_struct_end());
2111 }
2112
2113 #[test]
2114 #[should_panic]
2115 fn must_fail_if_write_field_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002116 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002117 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2118 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2119 o_prot.write_field_end().unwrap();
2120 }
2121
2122 #[test]
2123 #[should_panic]
2124 fn must_fail_if_write_stop_field_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002125 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002126 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2127 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2128 o_prot.write_field_stop().unwrap();
2129 }
2130
2131 #[test]
2132 #[should_panic]
2133 fn must_fail_if_write_struct_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002134 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002135 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2136 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2137 o_prot.write_struct_end().unwrap();
2138 }
2139
2140 #[test]
2141 #[should_panic]
2142 fn must_fail_if_write_struct_end_without_any_fields() {
Allen George0e22c362017-01-30 07:15:00 -05002143 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002144 o_prot.write_struct_end().unwrap();
2145 }
2146
2147 #[test]
2148 fn must_write_field_end() {
2149 assert_no_write(|o| o.write_field_end());
2150 }
2151
2152 #[test]
2153 fn must_write_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002154 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002155
2156 assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
2157
2158 let expected: [u8; 1] = [0x46 /* size | elem_type */];
2159
Allen George0e22c362017-01-30 07:15:00 -05002160 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002161 }
2162
2163 #[test]
2164 fn must_round_trip_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002165 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002166
2167 let ident = TListIdentifier::new(TType::I08, 10);
2168
2169 assert_success!(o_prot.write_list_begin(&ident));
2170
Allen George0e22c362017-01-30 07:15:00 -05002171 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002172
2173 let res = assert_success!(i_prot.read_list_begin());
2174 assert_eq!(&res, &ident);
2175 }
2176
2177 #[test]
2178 fn must_write_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002179 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002180
2181 let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
2182 assert!(res.is_ok());
2183
Allen George0e22c362017-01-30 07:15:00 -05002184 let expected: [u8; 3] = [
2185 0xF9, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002186 0x8F, 0x4E, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002187 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002188
Allen George0e22c362017-01-30 07:15:00 -05002189 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002190 }
2191
2192 #[test]
2193 fn must_round_trip_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002194 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002195
2196 let ident = TListIdentifier::new(TType::Set, 47381);
2197
2198 assert_success!(o_prot.write_list_begin(&ident));
2199
Allen George0e22c362017-01-30 07:15:00 -05002200 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002201
2202 let res = assert_success!(i_prot.read_list_begin());
2203 assert_eq!(&res, &ident);
2204 }
2205
2206 #[test]
2207 fn must_write_list_end() {
2208 assert_no_write(|o| o.write_list_end());
2209 }
2210
2211 #[test]
2212 fn must_write_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002213 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002214
2215 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
2216
2217 let expected: [u8; 1] = [0x2C /* size | elem_type */];
2218
Allen George0e22c362017-01-30 07:15:00 -05002219 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002220 }
2221
2222 #[test]
2223 fn must_round_trip_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002224 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002225
2226 let ident = TSetIdentifier::new(TType::I16, 7);
2227
2228 assert_success!(o_prot.write_set_begin(&ident));
2229
Allen George0e22c362017-01-30 07:15:00 -05002230 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002231
2232 let res = assert_success!(i_prot.read_set_begin());
2233 assert_eq!(&res, &ident);
2234 }
2235
2236 #[test]
2237 fn must_write_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002238 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002239
2240 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
2241
Allen George0e22c362017-01-30 07:15:00 -05002242 let expected: [u8; 4] = [
2243 0xF7, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002244 0xD3, 0xBA, 0x01, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002245 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002246
Allen George0e22c362017-01-30 07:15:00 -05002247 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002248 }
2249
2250 #[test]
2251 fn must_round_trip_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002252 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002253
Allen George7ddbcc02020-11-08 09:51:19 -05002254 let ident = TSetIdentifier::new(TType::Map, 3_928_429);
Allen George8b96bfb2016-11-02 08:01:08 -04002255
2256 assert_success!(o_prot.write_set_begin(&ident));
2257
Allen George0e22c362017-01-30 07:15:00 -05002258 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002259
2260 let res = assert_success!(i_prot.read_set_begin());
2261 assert_eq!(&res, &ident);
2262 }
2263
2264 #[test]
2265 fn must_write_set_end() {
2266 assert_no_write(|o| o.write_set_end());
2267 }
2268
2269 #[test]
2270 fn must_write_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002271 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002272
2273 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
2274
2275 let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything
2276
Allen George0e22c362017-01-30 07:15:00 -05002277 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002278 }
2279
2280 #[test]
2281 fn must_read_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002282 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002283
2284 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
2285
Allen George0e22c362017-01-30 07:15:00 -05002286 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002287
2288 let res = assert_success!(i_prot.read_map_begin());
Allen George0e22c362017-01-30 07:15:00 -05002289 assert_eq!(
2290 &res,
2291 &TMapIdentifier {
Allen Georgeef7a1892018-12-16 18:01:37 -05002292 key_type: None,
2293 value_type: None,
2294 size: 0,
2295 }
Allen George0e22c362017-01-30 07:15:00 -05002296 );
Allen George8b96bfb2016-11-02 08:01:08 -04002297 }
2298
2299 #[test]
2300 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002301 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002302
Allen Georgeef7a1892018-12-16 18:01:37 -05002303 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
2304 TType::Double,
2305 TType::String,
2306 238
2307 )));
Allen George8b96bfb2016-11-02 08:01:08 -04002308
Allen George0e22c362017-01-30 07:15:00 -05002309 let expected: [u8; 3] = [
Allen Georgeef7a1892018-12-16 18:01:37 -05002310 0xEE, 0x01, /* size as varint */
2311 0x78, /* key type | val type */
Allen George0e22c362017-01-30 07:15:00 -05002312 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002313
Allen George0e22c362017-01-30 07:15:00 -05002314 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002315 }
2316
2317 #[test]
2318 fn must_round_trip_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002319 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002320
Allen George7ddbcc02020-11-08 09:51:19 -05002321 let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349);
Allen George8b96bfb2016-11-02 08:01:08 -04002322
2323 assert_success!(o_prot.write_map_begin(&ident));
2324
Allen George0e22c362017-01-30 07:15:00 -05002325 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002326
2327 let res = assert_success!(i_prot.read_map_begin());
2328 assert_eq!(&res, &ident);
2329 }
2330
2331 #[test]
2332 fn must_write_map_end() {
2333 assert_no_write(|o| o.write_map_end());
2334 }
2335
2336 #[test]
2337 fn must_write_map_with_bool_key_and_value() {
Allen George0e22c362017-01-30 07:15:00 -05002338 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002339
2340 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
2341 assert_success!(o_prot.write_bool(true));
2342 assert_success!(o_prot.write_bool(false));
2343 assert_success!(o_prot.write_map_end());
2344
Allen George0e22c362017-01-30 07:15:00 -05002345 let expected: [u8; 4] = [
2346 0x01, /* size as varint */
2347 0x11, /* key type | val type */
2348 0x01, /* key: true */
Allen Georgeef7a1892018-12-16 18:01:37 -05002349 0x02, /* val: false */
Allen George0e22c362017-01-30 07:15:00 -05002350 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002351
Allen George0e22c362017-01-30 07:15:00 -05002352 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002353 }
2354
2355 #[test]
2356 fn must_round_trip_map_with_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002357 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002358
2359 let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
2360 assert_success!(o_prot.write_map_begin(&map_ident));
2361 assert_success!(o_prot.write_bool(true));
2362 assert_success!(o_prot.write_bool(false));
2363 assert_success!(o_prot.write_bool(false));
2364 assert_success!(o_prot.write_bool(true));
2365 assert_success!(o_prot.write_map_end());
2366
Allen George0e22c362017-01-30 07:15:00 -05002367 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002368
2369 // map header
2370 let rcvd_ident = assert_success!(i_prot.read_map_begin());
2371 assert_eq!(&rcvd_ident, &map_ident);
2372 // key 1
2373 let b = assert_success!(i_prot.read_bool());
2374 assert_eq!(b, true);
2375 // val 1
2376 let b = assert_success!(i_prot.read_bool());
2377 assert_eq!(b, false);
2378 // key 2
2379 let b = assert_success!(i_prot.read_bool());
2380 assert_eq!(b, false);
2381 // val 2
2382 let b = assert_success!(i_prot.read_bool());
2383 assert_eq!(b, true);
2384 // map end
2385 assert_success!(i_prot.read_map_end());
2386 }
2387
2388 #[test]
2389 fn must_read_map_end() {
Allen George0e22c362017-01-30 07:15:00 -05002390 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002391 assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
2392 }
2393
Allen Georgeef7a1892018-12-16 18:01:37 -05002394 fn test_objects() -> (
2395 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2396 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2397 ) {
Allen George0e22c362017-01-30 07:15:00 -05002398 let mem = TBufferChannel::with_capacity(80, 80);
Allen George8b96bfb2016-11-02 08:01:08 -04002399
Allen George0e22c362017-01-30 07:15:00 -05002400 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -04002401
Allen George0e22c362017-01-30 07:15:00 -05002402 let i_prot = TCompactInputProtocol::new(r_mem);
2403 let o_prot = TCompactOutputProtocol::new(w_mem);
Allen George8b96bfb2016-11-02 08:01:08 -04002404
Allen George0e22c362017-01-30 07:15:00 -05002405 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -04002406 }
2407
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002408 #[test]
2409 fn must_read_write_double() {
2410 let (mut i_prot, mut o_prot) = test_objects();
2411
Allen George7ddbcc02020-11-08 09:51:19 -05002412 #[allow(clippy::approx_constant)]
2413 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002414 o_prot.write_double(double).unwrap();
2415 copy_write_buffer_to_read_buffer!(o_prot);
2416
Allen George7ddbcc02020-11-08 09:51:19 -05002417 let read_double = i_prot.read_double().unwrap();
2418 assert!(read_double - double < std::f64::EPSILON);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002419 }
2420
2421 #[test]
2422 fn must_encode_double_as_other_langs() {
2423 let (_, mut o_prot) = test_objects();
2424 let expected = [24, 45, 68, 84, 251, 33, 9, 64];
2425
Allen George7ddbcc02020-11-08 09:51:19 -05002426 #[allow(clippy::approx_constant)]
2427 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002428 o_prot.write_double(double).unwrap();
2429
2430 assert_eq_written_bytes!(o_prot, expected);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002431 }
2432
Allen George0e22c362017-01-30 07:15:00 -05002433 fn assert_no_write<F>(mut write_fn: F)
2434 where
Allen Georgeb0d14132020-03-29 11:48:55 -04002435 F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> crate::Result<()>,
Allen George0e22c362017-01-30 07:15:00 -05002436 {
2437 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002438 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -05002439 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -04002440 }
2441}