blob: 0fefca0acebe771125a40bdb520c3c8086addc28 [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)?;
Allen George48905102021-02-20 08:47:01 -0500131 // writing side wrote signed sequence number as u32 to avoid zigzag encoding
132 let sequence_number = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400133 let service_call_name = self.read_string()?;
134
135 self.last_read_field_id = 0;
136
Allen Georgeef7a1892018-12-16 18:01:37 -0500137 Ok(TMessageIdentifier::new(
138 service_call_name,
139 message_type,
140 sequence_number,
141 ))
Allen George8b96bfb2016-11-02 08:01:08 -0400142 }
143
Allen Georgeb0d14132020-03-29 11:48:55 -0400144 fn read_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400145 Ok(())
146 }
147
Allen Georgeb0d14132020-03-29 11:48:55 -0400148 fn read_struct_begin(&mut self) -> crate::Result<Option<TStructIdentifier>> {
Allen George8b96bfb2016-11-02 08:01:08 -0400149 self.read_field_id_stack.push(self.last_read_field_id);
150 self.last_read_field_id = 0;
151 Ok(None)
152 }
153
Allen Georgeb0d14132020-03-29 11:48:55 -0400154 fn read_struct_end(&mut self) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500155 self.last_read_field_id = self
156 .read_field_id_stack
Allen George8b96bfb2016-11-02 08:01:08 -0400157 .pop()
158 .expect("should have previous field ids");
159 Ok(())
160 }
161
Allen Georgeb0d14132020-03-29 11:48:55 -0400162 fn read_field_begin(&mut self) -> crate::Result<TFieldIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400163 // we can read at least one byte, which is:
164 // - the type
165 // - the field delta and the type
166 let field_type = self.read_byte()?;
167 let field_delta = (field_type & 0xF0) >> 4;
168 let field_type = match field_type & 0x0F {
169 0x01 => {
170 self.pending_read_bool_value = Some(true);
171 Ok(TType::Bool)
172 }
173 0x02 => {
174 self.pending_read_bool_value = Some(false);
175 Ok(TType::Bool)
176 }
177 ttu8 => u8_to_type(ttu8),
178 }?;
179
180 match field_type {
Allen Georgeef7a1892018-12-16 18:01:37 -0500181 TType::Stop => Ok(
182 TFieldIdentifier::new::<Option<String>, String, Option<i16>>(
183 None,
184 TType::Stop,
185 None,
186 ),
187 ),
Allen George8b96bfb2016-11-02 08:01:08 -0400188 _ => {
189 if field_delta != 0 {
190 self.last_read_field_id += field_delta as i16;
191 } else {
192 self.last_read_field_id = self.read_i16()?;
193 };
194
Allen Georgeef7a1892018-12-16 18:01:37 -0500195 Ok(TFieldIdentifier {
196 name: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500197 field_type,
Allen Georgeef7a1892018-12-16 18:01:37 -0500198 id: Some(self.last_read_field_id),
199 })
Allen George8b96bfb2016-11-02 08:01:08 -0400200 }
201 }
202 }
203
Allen Georgeb0d14132020-03-29 11:48:55 -0400204 fn read_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400205 Ok(())
206 }
207
Allen Georgeb0d14132020-03-29 11:48:55 -0400208 fn read_bool(&mut self) -> crate::Result<bool> {
Allen George8b96bfb2016-11-02 08:01:08 -0400209 match self.pending_read_bool_value.take() {
210 Some(b) => Ok(b),
211 None => {
212 let b = self.read_byte()?;
213 match b {
214 0x01 => Ok(true),
215 0x02 => Ok(false),
Allen Georgeb0d14132020-03-29 11:48:55 -0400216 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
217 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500218 message: format!("cannot convert {} into bool", unkn),
219 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400220 }
221 }
222 }
223 }
224
Allen Georgeb0d14132020-03-29 11:48:55 -0400225 fn read_bytes(&mut self) -> crate::Result<Vec<u8>> {
Allen George0e22c362017-01-30 07:15:00 -0500226 let len = self.transport.read_varint::<u32>()?;
Allen George8b96bfb2016-11-02 08:01:08 -0400227 let mut buf = vec![0u8; len as usize];
Allen George0e22c362017-01-30 07:15:00 -0500228 self.transport
229 .read_exact(&mut buf)
230 .map_err(From::from)
231 .map(|_| buf)
Allen George8b96bfb2016-11-02 08:01:08 -0400232 }
233
Allen Georgeb0d14132020-03-29 11:48:55 -0400234 fn read_i8(&mut self) -> crate::Result<i8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400235 self.read_byte().map(|i| i as i8)
236 }
237
Allen Georgeb0d14132020-03-29 11:48:55 -0400238 fn read_i16(&mut self) -> crate::Result<i16> {
Allen George0e22c362017-01-30 07:15:00 -0500239 self.transport.read_varint::<i16>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400240 }
241
Allen Georgeb0d14132020-03-29 11:48:55 -0400242 fn read_i32(&mut self) -> crate::Result<i32> {
Allen George0e22c362017-01-30 07:15:00 -0500243 self.transport.read_varint::<i32>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400244 }
245
Allen Georgeb0d14132020-03-29 11:48:55 -0400246 fn read_i64(&mut self) -> crate::Result<i64> {
Allen George0e22c362017-01-30 07:15:00 -0500247 self.transport.read_varint::<i64>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400248 }
249
Allen Georgeb0d14132020-03-29 11:48:55 -0400250 fn read_double(&mut self) -> crate::Result<f64> {
Allen George8a1743d2020-12-05 01:19:27 -0500251 self.transport
252 .read_f64::<LittleEndian>()
253 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400254 }
255
Allen Georgeb0d14132020-03-29 11:48:55 -0400256 fn read_string(&mut self) -> crate::Result<String> {
Allen George8b96bfb2016-11-02 08:01:08 -0400257 let bytes = self.read_bytes()?;
258 String::from_utf8(bytes).map_err(From::from)
259 }
260
Allen Georgeb0d14132020-03-29 11:48:55 -0400261 fn read_list_begin(&mut self) -> crate::Result<TListIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400262 let (element_type, element_count) = self.read_list_set_begin()?;
263 Ok(TListIdentifier::new(element_type, element_count))
264 }
265
Allen Georgeb0d14132020-03-29 11:48:55 -0400266 fn read_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400267 Ok(())
268 }
269
Allen Georgeb0d14132020-03-29 11:48:55 -0400270 fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400271 let (element_type, element_count) = self.read_list_set_begin()?;
272 Ok(TSetIdentifier::new(element_type, element_count))
273 }
274
Allen Georgeb0d14132020-03-29 11:48:55 -0400275 fn read_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400276 Ok(())
277 }
278
Allen Georgeb0d14132020-03-29 11:48:55 -0400279 fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier> {
Allen George0e22c362017-01-30 07:15:00 -0500280 let element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400281 if element_count == 0 {
282 Ok(TMapIdentifier::new(None, None, 0))
283 } else {
284 let type_header = self.read_byte()?;
285 let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
286 let val_type = collection_u8_to_type(type_header & 0x0F)?;
287 Ok(TMapIdentifier::new(key_type, val_type, element_count))
288 }
289 }
290
Allen Georgeb0d14132020-03-29 11:48:55 -0400291 fn read_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400292 Ok(())
293 }
294
295 // utility
296 //
297
Allen Georgeb0d14132020-03-29 11:48:55 -0400298 fn read_byte(&mut self) -> crate::Result<u8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400299 let mut buf = [0u8; 1];
Allen George0e22c362017-01-30 07:15:00 -0500300 self.transport
301 .read_exact(&mut buf)
302 .map_err(From::from)
303 .map(|_| buf[0])
Allen George8b96bfb2016-11-02 08:01:08 -0400304 }
305}
306
Vadim Chekand3355af2018-01-05 23:12:47 -0500307impl<T> io::Seek for TCompactInputProtocol<T>
308where
309 T: io::Seek + TReadTransport,
310{
311 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
312 self.transport.seek(pos)
313 }
314}
315
Allen George8b96bfb2016-11-02 08:01:08 -0400316/// Factory for creating instances of `TCompactInputProtocol`.
317#[derive(Default)]
318pub struct TCompactInputProtocolFactory;
319
320impl TCompactInputProtocolFactory {
321 /// Create a `TCompactInputProtocolFactory`.
322 pub fn new() -> TCompactInputProtocolFactory {
323 TCompactInputProtocolFactory {}
324 }
325}
326
327impl TInputProtocolFactory for TCompactInputProtocolFactory {
Danny Browning77d96c12019-08-21 13:41:07 -0600328 fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500329 Box::new(TCompactInputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400330 }
331}
332
333/// Write messages using the Thrift compact protocol.
334///
335/// # Examples
336///
337/// Create and use a `TCompactOutputProtocol`.
338///
339/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -0400340/// use thrift::protocol::{TCompactOutputProtocol, TOutputProtocol};
Allen George0e22c362017-01-30 07:15:00 -0500341/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -0400342///
Allen George0e22c362017-01-30 07:15:00 -0500343/// let mut channel = TTcpChannel::new();
344/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400345///
Allen George0e22c362017-01-30 07:15:00 -0500346/// let mut protocol = TCompactOutputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -0400347///
Allen George0e22c362017-01-30 07:15:00 -0500348/// protocol.write_bool(true).unwrap();
349/// protocol.write_string("test_string").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400350/// ```
Allen George0e22c362017-01-30 07:15:00 -0500351#[derive(Debug)]
352pub struct TCompactOutputProtocol<T>
353where
354 T: TWriteTransport,
355{
Allen George8b96bfb2016-11-02 08:01:08 -0400356 // Identifier of the last field serialized for a struct.
357 last_write_field_id: i16,
Allen George0e22c362017-01-30 07:15:00 -0500358 // Stack of the last written field ids (new entry added each time a nested struct is written).
Allen George8b96bfb2016-11-02 08:01:08 -0400359 write_field_id_stack: Vec<i16>,
360 // Field identifier of the boolean field to be written.
361 // Saved because boolean fields and their value are encoded in a single byte
362 pending_write_bool_field_identifier: Option<TFieldIdentifier>,
363 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -0500364 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -0400365}
366
Allen George0e22c362017-01-30 07:15:00 -0500367impl<T> TCompactOutputProtocol<T>
368where
369 T: TWriteTransport,
370{
Allen George8b96bfb2016-11-02 08:01:08 -0400371 /// Create a `TCompactOutputProtocol` that writes bytes to `transport`.
Allen George0e22c362017-01-30 07:15:00 -0500372 pub fn new(transport: T) -> TCompactOutputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -0400373 TCompactOutputProtocol {
374 last_write_field_id: 0,
375 write_field_id_stack: Vec::new(),
376 pending_write_bool_field_identifier: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500377 transport,
Allen George8b96bfb2016-11-02 08:01:08 -0400378 }
379 }
380
381 // FIXME: field_type as unconstrained u8 is bad
Allen Georgeb0d14132020-03-29 11:48:55 -0400382 fn write_field_header(&mut self, field_type: u8, field_id: i16) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400383 let field_delta = field_id - self.last_write_field_id;
384 if field_delta > 0 && field_delta < 15 {
385 self.write_byte(((field_delta as u8) << 4) | field_type)?;
386 } else {
387 self.write_byte(field_type)?;
388 self.write_i16(field_id)?;
389 }
390 self.last_write_field_id = field_id;
391 Ok(())
392 }
393
Allen George8a1743d2020-12-05 01:19:27 -0500394 fn write_list_set_begin(
395 &mut self,
396 element_type: TType,
397 element_count: i32,
398 ) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400399 let elem_identifier = collection_type_to_u8(element_type);
400 if element_count <= 14 {
401 let header = (element_count as u8) << 4 | elem_identifier;
402 self.write_byte(header)
403 } else {
404 let header = 0xF0 | elem_identifier;
405 self.write_byte(header)?;
Allen George48905102021-02-20 08:47:01 -0500406 // element count is strictly positive as per the spec, so
407 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George8b96bfb2016-11-02 08:01:08 -0400408 self.transport
Allen George8b96bfb2016-11-02 08:01:08 -0400409 .write_varint(element_count as u32)
410 .map_err(From::from)
411 .map(|_| ())
412 }
413 }
414
415 fn assert_no_pending_bool_write(&self) {
416 if let Some(ref f) = self.pending_write_bool_field_identifier {
417 panic!("pending bool field {:?} not written", f)
418 }
419 }
420}
421
Allen George0e22c362017-01-30 07:15:00 -0500422impl<T> TOutputProtocol for TCompactOutputProtocol<T>
423where
424 T: TWriteTransport,
425{
Allen Georgeb0d14132020-03-29 11:48:55 -0400426 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400427 self.write_byte(COMPACT_PROTOCOL_ID)?;
428 self.write_byte((u8::from(identifier.message_type) << 5) | COMPACT_VERSION)?;
Allen George48905102021-02-20 08:47:01 -0500429 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George55c3e4c2021-03-01 23:19:52 -0500430 self.transport
431 .write_varint(identifier.sequence_number as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400432 self.write_string(&identifier.name)?;
433 Ok(())
434 }
435
Allen Georgeb0d14132020-03-29 11:48:55 -0400436 fn write_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400437 self.assert_no_pending_bool_write();
438 Ok(())
439 }
440
Allen Georgeb0d14132020-03-29 11:48:55 -0400441 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400442 self.write_field_id_stack.push(self.last_write_field_id);
443 self.last_write_field_id = 0;
444 Ok(())
445 }
446
Allen Georgeb0d14132020-03-29 11:48:55 -0400447 fn write_struct_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400448 self.assert_no_pending_bool_write();
Allen Georgeef7a1892018-12-16 18:01:37 -0500449 self.last_write_field_id = self
450 .write_field_id_stack
Allen George0e22c362017-01-30 07:15:00 -0500451 .pop()
452 .expect("should have previous field ids");
Allen George8b96bfb2016-11-02 08:01:08 -0400453 Ok(())
454 }
455
Allen Georgeb0d14132020-03-29 11:48:55 -0400456 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400457 match identifier.field_type {
458 TType::Bool => {
459 if self.pending_write_bool_field_identifier.is_some() {
Allen George0e22c362017-01-30 07:15:00 -0500460 panic!(
461 "should not have a pending bool while writing another bool with id: \
Allen Georgeef7a1892018-12-16 18:01:37 -0500462 {:?}",
Allen George0e22c362017-01-30 07:15:00 -0500463 identifier
464 )
Allen George8b96bfb2016-11-02 08:01:08 -0400465 }
466 self.pending_write_bool_field_identifier = Some(identifier.clone());
467 Ok(())
468 }
469 _ => {
470 let field_type = type_to_u8(identifier.field_type);
Allen Georgeef7a1892018-12-16 18:01:37 -0500471 let field_id = identifier.id.expect("non-stop field should have field id");
Allen George8b96bfb2016-11-02 08:01:08 -0400472 self.write_field_header(field_type, field_id)
473 }
474 }
475 }
476
Allen Georgeb0d14132020-03-29 11:48:55 -0400477 fn write_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400478 self.assert_no_pending_bool_write();
479 Ok(())
480 }
481
Allen Georgeb0d14132020-03-29 11:48:55 -0400482 fn write_field_stop(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400483 self.assert_no_pending_bool_write();
484 self.write_byte(type_to_u8(TType::Stop))
485 }
486
Allen Georgeb0d14132020-03-29 11:48:55 -0400487 fn write_bool(&mut self, b: bool) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400488 match self.pending_write_bool_field_identifier.take() {
489 Some(pending) => {
490 let field_id = pending.id.expect("bool field should have a field id");
491 let field_type_as_u8 = if b { 0x01 } else { 0x02 };
492 self.write_field_header(field_type_as_u8, field_id)
493 }
494 None => {
495 if b {
496 self.write_byte(0x01)
497 } else {
498 self.write_byte(0x02)
499 }
500 }
501 }
502 }
503
Allen Georgeb0d14132020-03-29 11:48:55 -0400504 fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> {
Allen George48905102021-02-20 08:47:01 -0500505 // length is strictly positive as per the spec, so
506 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500507 self.transport.write_varint(b.len() as u32)?;
508 self.transport.write_all(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400509 }
510
Allen Georgeb0d14132020-03-29 11:48:55 -0400511 fn write_i8(&mut self, i: i8) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400512 self.write_byte(i as u8)
513 }
514
Allen Georgeb0d14132020-03-29 11:48:55 -0400515 fn write_i16(&mut self, i: i16) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500516 self.transport
Allen George48905102021-02-20 08:47:01 -0500517 .write_varint(i)
Allen George0e22c362017-01-30 07:15:00 -0500518 .map_err(From::from)
519 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400520 }
521
Allen Georgeb0d14132020-03-29 11:48:55 -0400522 fn write_i32(&mut self, i: i32) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500523 self.transport
524 .write_varint(i)
525 .map_err(From::from)
526 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400527 }
528
Allen Georgeb0d14132020-03-29 11:48:55 -0400529 fn write_i64(&mut self, i: i64) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500530 self.transport
531 .write_varint(i)
532 .map_err(From::from)
533 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400534 }
535
Allen Georgeb0d14132020-03-29 11:48:55 -0400536 fn write_double(&mut self, d: f64) -> crate::Result<()> {
Allen George8a1743d2020-12-05 01:19:27 -0500537 self.transport
538 .write_f64::<LittleEndian>(d)
539 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400540 }
541
Allen Georgeb0d14132020-03-29 11:48:55 -0400542 fn write_string(&mut self, s: &str) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400543 self.write_bytes(s.as_bytes())
544 }
545
Allen Georgeb0d14132020-03-29 11:48:55 -0400546 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400547 self.write_list_set_begin(identifier.element_type, identifier.size)
548 }
549
Allen Georgeb0d14132020-03-29 11:48:55 -0400550 fn write_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400551 Ok(())
552 }
553
Allen Georgeb0d14132020-03-29 11:48:55 -0400554 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400555 self.write_list_set_begin(identifier.element_type, identifier.size)
556 }
557
Allen Georgeb0d14132020-03-29 11:48:55 -0400558 fn write_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400559 Ok(())
560 }
561
Allen Georgeb0d14132020-03-29 11:48:55 -0400562 fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400563 if identifier.size == 0 {
564 self.write_byte(0)
565 } else {
Allen George48905102021-02-20 08:47:01 -0500566 // element count is strictly positive as per the spec, so
567 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500568 self.transport.write_varint(identifier.size as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400569
Allen George0e22c362017-01-30 07:15:00 -0500570 let key_type = identifier
571 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400572 .expect("map identifier to write should contain key type");
573 let key_type_byte = collection_type_to_u8(key_type) << 4;
574
Allen George0e22c362017-01-30 07:15:00 -0500575 let val_type = identifier
576 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400577 .expect("map identifier to write should contain value type");
578 let val_type_byte = collection_type_to_u8(val_type);
579
580 let map_type_header = key_type_byte | val_type_byte;
581 self.write_byte(map_type_header)
582 }
583 }
584
Allen Georgeb0d14132020-03-29 11:48:55 -0400585 fn write_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400586 Ok(())
587 }
588
Allen Georgeb0d14132020-03-29 11:48:55 -0400589 fn flush(&mut self) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500590 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400591 }
592
593 // utility
594 //
595
Allen Georgeb0d14132020-03-29 11:48:55 -0400596 fn write_byte(&mut self, b: u8) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500597 self.transport.write(&[b]).map_err(From::from).map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400598 }
599}
600
601/// Factory for creating instances of `TCompactOutputProtocol`.
602#[derive(Default)]
603pub struct TCompactOutputProtocolFactory;
604
605impl TCompactOutputProtocolFactory {
606 /// Create a `TCompactOutputProtocolFactory`.
607 pub fn new() -> TCompactOutputProtocolFactory {
608 TCompactOutputProtocolFactory {}
609 }
610}
611
612impl TOutputProtocolFactory for TCompactOutputProtocolFactory {
Allen George8a1743d2020-12-05 01:19:27 -0500613 fn create(
614 &self,
615 transport: Box<dyn TWriteTransport + Send>,
616 ) -> Box<dyn TOutputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500617 Box::new(TCompactOutputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400618 }
619}
620
621fn collection_type_to_u8(field_type: TType) -> u8 {
622 match field_type {
623 TType::Bool => 0x01,
624 f => type_to_u8(f),
625 }
626}
627
628fn type_to_u8(field_type: TType) -> u8 {
629 match field_type {
630 TType::Stop => 0x00,
631 TType::I08 => 0x03, // equivalent to TType::Byte
632 TType::I16 => 0x04,
633 TType::I32 => 0x05,
634 TType::I64 => 0x06,
635 TType::Double => 0x07,
636 TType::String => 0x08,
637 TType::List => 0x09,
638 TType::Set => 0x0A,
639 TType::Map => 0x0B,
640 TType::Struct => 0x0C,
xiexiaoqun0cc06502021-09-09 10:43:00 +0800641 _ => panic!(
Allen Georgeef7a1892018-12-16 18:01:37 -0500642 "should not have attempted to convert {} to u8",
643 field_type
xiexiaoqun0cc06502021-09-09 10:43:00 +0800644 ),
Allen George8b96bfb2016-11-02 08:01:08 -0400645 }
646}
647
Allen Georgeb0d14132020-03-29 11:48:55 -0400648fn collection_u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400649 match b {
650 0x01 => Ok(TType::Bool),
651 o => u8_to_type(o),
652 }
653}
654
Allen Georgeb0d14132020-03-29 11:48:55 -0400655fn u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400656 match b {
657 0x00 => Ok(TType::Stop),
658 0x03 => Ok(TType::I08), // equivalent to TType::Byte
659 0x04 => Ok(TType::I16),
660 0x05 => Ok(TType::I32),
661 0x06 => Ok(TType::I64),
662 0x07 => Ok(TType::Double),
663 0x08 => Ok(TType::String),
664 0x09 => Ok(TType::List),
665 0x0A => Ok(TType::Set),
666 0x0B => Ok(TType::Map),
667 0x0C => Ok(TType::Struct),
Allen Georgeb0d14132020-03-29 11:48:55 -0400668 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
669 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500670 message: format!("cannot convert {} into TType", unkn),
671 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400672 }
673}
674
675#[cfg(test)]
676mod tests {
677
Allen George8a1743d2020-12-05 01:19:27 -0500678 use std::i32;
679
Allen Georgeb0d14132020-03-29 11:48:55 -0400680 use crate::protocol::{
Allen Georgeef7a1892018-12-16 18:01:37 -0500681 TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
682 TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
683 };
Allen Georgeb0d14132020-03-29 11:48:55 -0400684 use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400685
686 use super::*;
687
688 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500689 fn must_write_message_begin_largest_maximum_positive_sequence_number() {
690 let (_, mut o_prot) = test_objects();
691
692 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
693 "bar",
694 TMessageType::Reply,
695 i32::MAX
696 )));
697
698 #[rustfmt::skip]
699 let expected: [u8; 11] = [
700 0x82, /* protocol ID */
701 0x41, /* message type | protocol version */
702 0xFF,
703 0xFF,
704 0xFF,
705 0xFF,
706 0x07, /* non-zig-zag varint sequence number */
707 0x03, /* message-name length */
708 0x62,
709 0x61,
710 0x72 /* "bar" */,
711 ];
712
713 assert_eq_written_bytes!(o_prot, expected);
714 }
715
716 #[test]
717 fn must_read_message_begin_largest_maximum_positive_sequence_number() {
718 let (mut i_prot, _) = test_objects();
719
720 #[rustfmt::skip]
721 let source_bytes: [u8; 11] = [
722 0x82, /* protocol ID */
723 0x41, /* message type | protocol version */
724 0xFF,
725 0xFF,
726 0xFF,
727 0xFF,
728 0x07, /* non-zig-zag varint sequence number */
729 0x03, /* message-name length */
730 0x62,
731 0x61,
732 0x72 /* "bar" */,
733 ];
734
735 i_prot.transport.set_readable_bytes(&source_bytes);
736
737 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MAX);
738 let res = assert_success!(i_prot.read_message_begin());
739
740 assert_eq!(&expected, &res);
741 }
742
743 #[test]
744 fn must_write_message_begin_positive_sequence_number_0() {
Allen George0e22c362017-01-30 07:15:00 -0500745 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400746
Allen Georgeef7a1892018-12-16 18:01:37 -0500747 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
748 "foo",
749 TMessageType::Call,
750 431
751 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400752
Allen George7ddbcc02020-11-08 09:51:19 -0500753 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500754 let expected: [u8; 8] = [
755 0x82, /* protocol ID */
756 0x21, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500757 0xAF,
758 0x03, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500759 0x03, /* message-name length */
760 0x66,
761 0x6F,
762 0x6F /* "foo" */,
763 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400764
Allen George0e22c362017-01-30 07:15:00 -0500765 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400766 }
767
768 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500769 fn must_read_message_begin_positive_sequence_number_0() {
770 let (mut i_prot, _) = test_objects();
771
772 #[rustfmt::skip]
773 let source_bytes: [u8; 8] = [
774 0x82, /* protocol ID */
775 0x21, /* message type | protocol version */
776 0xAF,
777 0x03, /* non-zig-zag varint sequence number */
778 0x03, /* message-name length */
779 0x66,
780 0x6F,
781 0x6F /* "foo" */,
782 ];
783
784 i_prot.transport.set_readable_bytes(&source_bytes);
785
786 let expected = TMessageIdentifier::new("foo", TMessageType::Call, 431);
787 let res = assert_success!(i_prot.read_message_begin());
788
789 assert_eq!(&expected, &res);
790 }
791
792 #[test]
793 fn must_write_message_begin_positive_sequence_number_1() {
Allen George0e22c362017-01-30 07:15:00 -0500794 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400795
Allen Georgeef7a1892018-12-16 18:01:37 -0500796 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
797 "bar",
798 TMessageType::Reply,
Allen George7ddbcc02020-11-08 09:51:19 -0500799 991_828
Allen Georgeef7a1892018-12-16 18:01:37 -0500800 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400801
Allen George7ddbcc02020-11-08 09:51:19 -0500802 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500803 let expected: [u8; 9] = [
804 0x82, /* protocol ID */
805 0x41, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500806 0xD4,
807 0xC4,
808 0x3C, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500809 0x03, /* message-name length */
810 0x62,
811 0x61,
812 0x72 /* "bar" */,
813 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400814
Allen George0e22c362017-01-30 07:15:00 -0500815 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400816 }
817
818 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500819 fn must_read_message_begin_positive_sequence_number_1() {
820 let (mut i_prot, _) = test_objects();
821
822 #[rustfmt::skip]
823 let source_bytes: [u8; 9] = [
824 0x82, /* protocol ID */
825 0x41, /* message type | protocol version */
826 0xD4,
827 0xC4,
828 0x3C, /* non-zig-zag varint sequence number */
829 0x03, /* message-name length */
830 0x62,
831 0x61,
832 0x72 /* "bar" */,
833 ];
834
835 i_prot.transport.set_readable_bytes(&source_bytes);
836
837 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 991_828);
838 let res = assert_success!(i_prot.read_message_begin());
839
840 assert_eq!(&expected, &res);
841 }
842
843 #[test]
844 fn must_write_message_begin_zero_sequence_number() {
845 let (_, mut o_prot) = test_objects();
846
847 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
848 "bar",
849 TMessageType::Reply,
850 0
851 )));
852
853 #[rustfmt::skip]
854 let expected: [u8; 7] = [
855 0x82, /* protocol ID */
856 0x41, /* message type | protocol version */
857 0x00, /* non-zig-zag varint sequence number */
858 0x03, /* message-name length */
859 0x62,
860 0x61,
861 0x72 /* "bar" */,
862 ];
863
864 assert_eq_written_bytes!(o_prot, expected);
865 }
866
867 #[test]
868 fn must_read_message_begin_zero_sequence_number() {
869 let (mut i_prot, _) = test_objects();
870
871 #[rustfmt::skip]
872 let source_bytes: [u8; 7] = [
873 0x82, /* protocol ID */
874 0x41, /* message type | protocol version */
875 0x00, /* non-zig-zag varint sequence number */
876 0x03, /* message-name length */
877 0x62,
878 0x61,
879 0x72 /* "bar" */,
880 ];
881
882 i_prot.transport.set_readable_bytes(&source_bytes);
883
884 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 0);
885 let res = assert_success!(i_prot.read_message_begin());
886
887 assert_eq!(&expected, &res);
888 }
889
890 #[test]
891 fn must_write_message_begin_largest_minimum_negative_sequence_number() {
892 let (_, mut o_prot) = test_objects();
893
894 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
895 "bar",
896 TMessageType::Reply,
897 i32::MIN
898 )));
899
900 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
901 #[rustfmt::skip]
902 let expected: [u8; 11] = [
903 0x82, /* protocol ID */
904 0x41, /* message type | protocol version */
905 0x80,
906 0x80,
907 0x80,
908 0x80,
909 0x08, /* non-zig-zag varint sequence number */
910 0x03, /* message-name length */
911 0x62,
912 0x61,
913 0x72 /* "bar" */,
914 ];
915
916 assert_eq_written_bytes!(o_prot, expected);
917 }
918
919 #[test]
920 fn must_read_message_begin_largest_minimum_negative_sequence_number() {
921 let (mut i_prot, _) = test_objects();
922
923 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
924 #[rustfmt::skip]
925 let source_bytes: [u8; 11] = [
926 0x82, /* protocol ID */
927 0x41, /* message type | protocol version */
928 0x80,
929 0x80,
930 0x80,
931 0x80,
932 0x08, /* non-zig-zag varint sequence number */
933 0x03, /* message-name length */
934 0x62,
935 0x61,
936 0x72 /* "bar" */,
937 ];
938
939 i_prot.transport.set_readable_bytes(&source_bytes);
940
941 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MIN);
942 let res = assert_success!(i_prot.read_message_begin());
943
944 assert_eq!(&expected, &res);
945 }
946
947 #[test]
948 fn must_write_message_begin_negative_sequence_number_0() {
949 let (_, mut o_prot) = test_objects();
950
951 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
952 "foo",
953 TMessageType::Call,
954 -431
955 )));
956
957 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
958 #[rustfmt::skip]
959 let expected: [u8; 11] = [
960 0x82, /* protocol ID */
961 0x21, /* message type | protocol version */
962 0xD1,
963 0xFC,
964 0xFF,
965 0xFF,
966 0x0F, /* non-zig-zag varint sequence number */
967 0x03, /* message-name length */
968 0x66,
969 0x6F,
970 0x6F /* "foo" */,
971 ];
972
973 assert_eq_written_bytes!(o_prot, expected);
974 }
975
976 #[test]
977 fn must_read_message_begin_negative_sequence_number_0() {
978 let (mut i_prot, _) = test_objects();
979
980 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
981 #[rustfmt::skip]
982 let source_bytes: [u8; 11] = [
983 0x82, /* protocol ID */
984 0x21, /* message type | protocol version */
985 0xD1,
986 0xFC,
987 0xFF,
988 0xFF,
989 0x0F, /* non-zig-zag varint sequence number */
990 0x03, /* message-name length */
991 0x66,
992 0x6F,
993 0x6F /* "foo" */,
994 ];
995
996 i_prot.transport.set_readable_bytes(&source_bytes);
997
998 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -431);
999 let res = assert_success!(i_prot.read_message_begin());
1000
1001 assert_eq!(&expected, &res);
1002 }
1003
1004 #[test]
1005 fn must_write_message_begin_negative_sequence_number_1() {
1006 let (_, mut o_prot) = test_objects();
1007
1008 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1009 "foo",
1010 TMessageType::Call,
1011 -73_184_125
1012 )));
1013
1014 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1015 #[rustfmt::skip]
1016 let expected: [u8; 11] = [
1017 0x82, /* protocol ID */
1018 0x21, /* message type | protocol version */
1019 0x83,
1020 0x99,
1021 0x8D,
1022 0xDD,
1023 0x0F, /* non-zig-zag varint sequence number */
1024 0x03, /* message-name length */
1025 0x66,
1026 0x6F,
1027 0x6F /* "foo" */,
1028 ];
1029
1030 assert_eq_written_bytes!(o_prot, expected);
1031 }
1032
1033 #[test]
1034 fn must_read_message_begin_negative_sequence_number_1() {
1035 let (mut i_prot, _) = test_objects();
1036
1037 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1038 #[rustfmt::skip]
1039 let source_bytes: [u8; 11] = [
1040 0x82, /* protocol ID */
1041 0x21, /* message type | protocol version */
1042 0x83,
1043 0x99,
1044 0x8D,
1045 0xDD,
1046 0x0F, /* non-zig-zag varint sequence number */
1047 0x03, /* message-name length */
1048 0x66,
1049 0x6F,
1050 0x6F /* "foo" */,
1051 ];
1052
1053 i_prot.transport.set_readable_bytes(&source_bytes);
1054
1055 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -73_184_125);
1056 let res = assert_success!(i_prot.read_message_begin());
1057
1058 assert_eq!(&expected, &res);
1059 }
1060
1061 #[test]
1062 fn must_write_message_begin_negative_sequence_number_2() {
1063 let (_, mut o_prot) = test_objects();
1064
1065 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1066 "foo",
1067 TMessageType::Call,
1068 -1_073_741_823
1069 )));
1070
1071 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
1072 #[rustfmt::skip]
1073 let expected: [u8; 11] = [
1074 0x82, /* protocol ID */
1075 0x21, /* message type | protocol version */
1076 0x81,
1077 0x80,
1078 0x80,
1079 0x80,
1080 0x0C, /* non-zig-zag varint sequence number */
1081 0x03, /* message-name length */
1082 0x66,
1083 0x6F,
1084 0x6F /* "foo" */,
1085 ];
1086
1087 assert_eq_written_bytes!(o_prot, expected);
1088 }
1089
1090 #[test]
1091 fn must_read_message_begin_negative_sequence_number_2() {
1092 let (mut i_prot, _) = test_objects();
1093
1094 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
Allen George55c3e4c2021-03-01 23:19:52 -05001095 #[rustfmt::skip]
Allen George8a1743d2020-12-05 01:19:27 -05001096 let source_bytes: [u8; 11] = [
1097 0x82, /* protocol ID */
1098 0x21, /* message type | protocol version */
1099 0x81,
1100 0x80,
1101 0x80,
1102 0x80,
1103 0x0C, /* non-zig-zag varint sequence number */
1104 0x03, /* message-name length */
1105 0x66,
1106 0x6F,
Allen George55c3e4c2021-03-01 23:19:52 -05001107 0x6F, /* "foo" */
Allen George8a1743d2020-12-05 01:19:27 -05001108 ];
1109
1110 i_prot.transport.set_readable_bytes(&source_bytes);
1111
1112 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -1_073_741_823);
1113 let res = assert_success!(i_prot.read_message_begin());
1114
1115 assert_eq!(&expected, &res);
1116 }
1117
1118 #[test]
Nik Claytone7917602020-03-05 11:51:15 +01001119 fn must_round_trip_upto_i64_maxvalue() {
1120 // See https://issues.apache.org/jira/browse/THRIFT-5131
1121 for i in 0..64 {
1122 let (mut i_prot, mut o_prot) = test_objects();
1123 let val: i64 = ((1u64 << i) - 1) as i64;
1124
1125 o_prot
Allen George8a1743d2020-12-05 01:19:27 -05001126 .write_field_begin(&TFieldIdentifier::new("val", TType::I64, 1))
Nik Claytone7917602020-03-05 11:51:15 +01001127 .unwrap();
1128 o_prot.write_i64(val).unwrap();
1129 o_prot.write_field_end().unwrap();
1130 o_prot.flush().unwrap();
1131
1132 copy_write_buffer_to_read_buffer!(o_prot);
1133
1134 i_prot.read_field_begin().unwrap();
1135 assert_eq!(val, i_prot.read_i64().unwrap());
1136 }
1137 }
1138
1139 #[test]
Allen George8b96bfb2016-11-02 08:01:08 -04001140 fn must_round_trip_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -05001141 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001142
Allen George7ddbcc02020-11-08 09:51:19 -05001143 let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948);
Allen George8b96bfb2016-11-02 08:01:08 -04001144
1145 assert_success!(o_prot.write_message_begin(&ident));
1146
Allen George0e22c362017-01-30 07:15:00 -05001147 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001148
1149 let res = assert_success!(i_prot.read_message_begin());
1150 assert_eq!(&res, &ident);
1151 }
1152
1153 #[test]
1154 fn must_write_message_end() {
1155 assert_no_write(|o| o.write_message_end());
1156 }
1157
1158 // NOTE: structs and fields are tested together
1159 //
1160
1161 #[test]
1162 fn must_write_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001163 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001164
1165 // no bytes should be written however
1166 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1167
1168 // write three fields with tiny field ids
1169 // since they're small the field ids will be encoded as deltas
1170
1171 // since this is the first field (and it's zero) it gets the full varint write
1172 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
1173 assert_success!(o_prot.write_field_end());
1174
1175 // since this delta > 0 and < 15 it can be encoded as a delta
1176 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
1177 assert_success!(o_prot.write_field_end());
1178
1179 // since this delta > 0 and < 15 it can be encoded as a delta
1180 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
1181 assert_success!(o_prot.write_field_end());
1182
1183 // now, finish the struct off
1184 assert_success!(o_prot.write_field_stop());
1185 assert_success!(o_prot.write_struct_end());
1186
Allen George7ddbcc02020-11-08 09:51:19 -05001187 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001188 let expected: [u8; 5] = [
1189 0x03, /* field type */
1190 0x00, /* first field id */
1191 0x44, /* field delta (4) | field type */
1192 0x59, /* field delta (5) | field type */
1193 0x00 /* field stop */,
1194 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001195
Allen George0e22c362017-01-30 07:15:00 -05001196 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001197 }
1198
1199 #[test]
1200 fn must_round_trip_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001201 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001202
1203 // no bytes should be written however
1204 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1205
1206 // write three fields with tiny field ids
1207 // since they're small the field ids will be encoded as deltas
1208
1209 // since this is the first field (and it's zero) it gets the full varint write
1210 let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
1211 assert_success!(o_prot.write_field_begin(&field_ident_1));
1212 assert_success!(o_prot.write_field_end());
1213
1214 // since this delta > 0 and < 15 it can be encoded as a delta
1215 let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
1216 assert_success!(o_prot.write_field_begin(&field_ident_2));
1217 assert_success!(o_prot.write_field_end());
1218
1219 // since this delta > 0 and < 15 it can be encoded as a delta
1220 let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
1221 assert_success!(o_prot.write_field_begin(&field_ident_3));
1222 assert_success!(o_prot.write_field_end());
1223
1224 // now, finish the struct off
1225 assert_success!(o_prot.write_field_stop());
1226 assert_success!(o_prot.write_struct_end());
1227
Allen George0e22c362017-01-30 07:15:00 -05001228 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001229
1230 // read the struct back
1231 assert_success!(i_prot.read_struct_begin());
1232
1233 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001234 assert_eq!(
1235 read_ident_1,
1236 TFieldIdentifier {
1237 name: None,
1238 ..field_ident_1
1239 }
1240 );
Allen George8b96bfb2016-11-02 08:01:08 -04001241 assert_success!(i_prot.read_field_end());
1242
1243 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001244 assert_eq!(
1245 read_ident_2,
1246 TFieldIdentifier {
1247 name: None,
1248 ..field_ident_2
1249 }
1250 );
Allen George8b96bfb2016-11-02 08:01:08 -04001251 assert_success!(i_prot.read_field_end());
1252
1253 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001254 assert_eq!(
1255 read_ident_3,
1256 TFieldIdentifier {
1257 name: None,
1258 ..field_ident_3
1259 }
1260 );
Allen George8b96bfb2016-11-02 08:01:08 -04001261 assert_success!(i_prot.read_field_end());
1262
1263 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001264 assert_eq!(
1265 read_ident_4,
1266 TFieldIdentifier {
1267 name: None,
1268 field_type: TType::Stop,
1269 id: None,
1270 }
1271 );
Allen George8b96bfb2016-11-02 08:01:08 -04001272
1273 assert_success!(i_prot.read_struct_end());
1274 }
1275
1276 #[test]
1277 fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001278 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001279
1280 // no bytes should be written however
1281 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1282
1283 // write three fields with tiny field ids
1284 // since they're small the field ids will be encoded as deltas
1285
1286 // gets a delta write
1287 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
1288 assert_success!(o_prot.write_field_end());
1289
1290 // since this delta > 0 and < 15 it can be encoded as a delta
1291 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
1292 assert_success!(o_prot.write_field_end());
1293
1294 // since this delta > 0 and < 15 it can be encoded as a delta
1295 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
1296 assert_success!(o_prot.write_field_end());
1297
1298 // now, finish the struct off
1299 assert_success!(o_prot.write_field_stop());
1300 assert_success!(o_prot.write_struct_end());
1301
Allen George7ddbcc02020-11-08 09:51:19 -05001302 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001303 let expected: [u8; 4] = [
1304 0x15, /* field delta (1) | field type */
1305 0x1A, /* field delta (1) | field type */
1306 0x48, /* field delta (4) | field type */
1307 0x00 /* field stop */,
1308 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001309
Allen George0e22c362017-01-30 07:15:00 -05001310 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001311 }
1312
1313 #[test]
1314 fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001315 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001316
1317 // no bytes should be written however
1318 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1319
1320 // write three fields with tiny field ids
1321 // since they're small the field ids will be encoded as deltas
1322
1323 // gets a delta write
1324 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
1325 assert_success!(o_prot.write_field_begin(&field_ident_1));
1326 assert_success!(o_prot.write_field_end());
1327
1328 // since this delta > 0 and < 15 it can be encoded as a delta
1329 let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
1330 assert_success!(o_prot.write_field_begin(&field_ident_2));
1331 assert_success!(o_prot.write_field_end());
1332
1333 // since this delta > 0 and < 15 it can be encoded as a delta
1334 let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
1335 assert_success!(o_prot.write_field_begin(&field_ident_3));
1336 assert_success!(o_prot.write_field_end());
1337
1338 // now, finish the struct off
1339 assert_success!(o_prot.write_field_stop());
1340 assert_success!(o_prot.write_struct_end());
1341
Allen George0e22c362017-01-30 07:15:00 -05001342 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001343
1344 // read the struct back
1345 assert_success!(i_prot.read_struct_begin());
1346
1347 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001348 assert_eq!(
1349 read_ident_1,
1350 TFieldIdentifier {
1351 name: None,
1352 ..field_ident_1
1353 }
1354 );
Allen George8b96bfb2016-11-02 08:01:08 -04001355 assert_success!(i_prot.read_field_end());
1356
1357 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001358 assert_eq!(
1359 read_ident_2,
1360 TFieldIdentifier {
1361 name: None,
1362 ..field_ident_2
1363 }
1364 );
Allen George8b96bfb2016-11-02 08:01:08 -04001365 assert_success!(i_prot.read_field_end());
1366
1367 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001368 assert_eq!(
1369 read_ident_3,
1370 TFieldIdentifier {
1371 name: None,
1372 ..field_ident_3
1373 }
1374 );
Allen George8b96bfb2016-11-02 08:01:08 -04001375 assert_success!(i_prot.read_field_end());
1376
1377 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001378 assert_eq!(
1379 read_ident_4,
1380 TFieldIdentifier {
1381 name: None,
1382 field_type: TType::Stop,
1383 id: None,
1384 }
1385 );
Allen George8b96bfb2016-11-02 08:01:08 -04001386
1387 assert_success!(i_prot.read_struct_end());
1388 }
1389
1390 #[test]
1391 fn must_write_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001392 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001393
1394 // no bytes should be written however
1395 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1396
1397 // write three fields with field ids that cannot be encoded as deltas
1398
1399 // since this is the first field (and it's zero) it gets the full varint write
1400 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
1401 assert_success!(o_prot.write_field_end());
1402
1403 // since this delta is > 15 it is encoded as a zig-zag varint
1404 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
1405 assert_success!(o_prot.write_field_end());
1406
1407 // since this delta is > 15 it is encoded as a zig-zag varint
1408 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
1409 assert_success!(o_prot.write_field_end());
1410
1411 // now, finish the struct off
1412 assert_success!(o_prot.write_field_stop());
1413 assert_success!(o_prot.write_struct_end());
1414
Allen George7ddbcc02020-11-08 09:51:19 -05001415 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001416 let expected: [u8; 8] = [
1417 0x05, /* field type */
1418 0x00, /* first field id */
1419 0x06, /* field type */
1420 0x20, /* zig-zag varint field id */
1421 0x0A, /* field type */
1422 0xC6,
1423 0x01, /* zig-zag varint field id */
1424 0x00 /* field stop */,
1425 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001426
Allen George0e22c362017-01-30 07:15:00 -05001427 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001428 }
1429
1430 #[test]
1431 fn must_round_trip_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001432 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001433
1434 // no bytes should be written however
1435 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1436
1437 // write three fields with field ids that cannot be encoded as deltas
1438
1439 // since this is the first field (and it's zero) it gets the full varint write
1440 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
1441 assert_success!(o_prot.write_field_begin(&field_ident_1));
1442 assert_success!(o_prot.write_field_end());
1443
1444 // since this delta is > 15 it is encoded as a zig-zag varint
1445 let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
1446 assert_success!(o_prot.write_field_begin(&field_ident_2));
1447 assert_success!(o_prot.write_field_end());
1448
1449 // since this delta is > 15 it is encoded as a zig-zag varint
1450 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
1451 assert_success!(o_prot.write_field_begin(&field_ident_3));
1452 assert_success!(o_prot.write_field_end());
1453
1454 // now, finish the struct off
1455 assert_success!(o_prot.write_field_stop());
1456 assert_success!(o_prot.write_struct_end());
1457
Allen George0e22c362017-01-30 07:15:00 -05001458 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001459
1460 // read the struct back
1461 assert_success!(i_prot.read_struct_begin());
1462
1463 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001464 assert_eq!(
1465 read_ident_1,
1466 TFieldIdentifier {
1467 name: None,
1468 ..field_ident_1
1469 }
1470 );
Allen George8b96bfb2016-11-02 08:01:08 -04001471 assert_success!(i_prot.read_field_end());
1472
1473 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001474 assert_eq!(
1475 read_ident_2,
1476 TFieldIdentifier {
1477 name: None,
1478 ..field_ident_2
1479 }
1480 );
Allen George8b96bfb2016-11-02 08:01:08 -04001481 assert_success!(i_prot.read_field_end());
1482
1483 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001484 assert_eq!(
1485 read_ident_3,
1486 TFieldIdentifier {
1487 name: None,
1488 ..field_ident_3
1489 }
1490 );
Allen George8b96bfb2016-11-02 08:01:08 -04001491 assert_success!(i_prot.read_field_end());
1492
1493 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001494 assert_eq!(
1495 read_ident_4,
1496 TFieldIdentifier {
1497 name: None,
1498 field_type: TType::Stop,
1499 id: None,
1500 }
1501 );
Allen George8b96bfb2016-11-02 08:01:08 -04001502
1503 assert_success!(i_prot.read_struct_end());
1504 }
1505
1506 #[test]
1507 fn must_write_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001508 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001509
1510 // no bytes should be written however
1511 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1512
1513 // write three fields with field ids that cannot be encoded as deltas
1514
1515 // since the delta is > 0 and < 15 it gets a delta write
1516 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1517 assert_success!(o_prot.write_field_end());
1518
1519 // since this delta > 0 and < 15 it gets a delta write
1520 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1521 assert_success!(o_prot.write_field_end());
1522
1523 // since this delta is > 15 it is encoded as a zig-zag varint
1524 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
1525 assert_success!(o_prot.write_field_end());
1526
1527 // since this delta is > 15 it is encoded as a zig-zag varint
1528 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
1529 assert_success!(o_prot.write_field_end());
1530
1531 // since this is only 3 up from the previous it is recorded as a delta
1532 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
1533 assert_success!(o_prot.write_field_end());
1534
1535 // now, finish the struct off
1536 assert_success!(o_prot.write_field_stop());
1537 assert_success!(o_prot.write_struct_end());
1538
Allen George7ddbcc02020-11-08 09:51:19 -05001539 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001540 let expected: [u8; 10] = [
1541 0x16, /* field delta (1) | field type */
1542 0x85, /* field delta (8) | field type */
1543 0x0A, /* field type */
1544 0xD0,
1545 0x0F, /* zig-zag varint field id */
1546 0x0A, /* field type */
1547 0xA2,
1548 0x1F, /* zig-zag varint field id */
1549 0x3A, /* field delta (3) | field type */
1550 0x00 /* field stop */,
1551 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001552
Allen George0e22c362017-01-30 07:15:00 -05001553 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001554 }
1555
Allen George7ddbcc02020-11-08 09:51:19 -05001556 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001557 #[test]
1558 fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001559 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001560
1561 // no bytes should be written however
1562 let struct_ident = TStructIdentifier::new("foo");
1563 assert_success!(o_prot.write_struct_begin(&struct_ident));
1564
1565 // write three fields with field ids that cannot be encoded as deltas
1566
1567 // since the delta is > 0 and < 15 it gets a delta write
1568 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1569 assert_success!(o_prot.write_field_begin(&field_ident_1));
1570 assert_success!(o_prot.write_field_end());
1571
1572 // since this delta > 0 and < 15 it gets a delta write
1573 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1574 assert_success!(o_prot.write_field_begin(&field_ident_2));
1575 assert_success!(o_prot.write_field_end());
1576
1577 // since this delta is > 15 it is encoded as a zig-zag varint
1578 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
1579 assert_success!(o_prot.write_field_begin(&field_ident_3));
1580 assert_success!(o_prot.write_field_end());
1581
1582 // since this delta is > 15 it is encoded as a zig-zag varint
1583 let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
1584 assert_success!(o_prot.write_field_begin(&field_ident_4));
1585 assert_success!(o_prot.write_field_end());
1586
1587 // since this is only 3 up from the previous it is recorded as a delta
1588 let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
1589 assert_success!(o_prot.write_field_begin(&field_ident_5));
1590 assert_success!(o_prot.write_field_end());
1591
1592 // now, finish the struct off
1593 assert_success!(o_prot.write_field_stop());
1594 assert_success!(o_prot.write_struct_end());
1595
Allen George0e22c362017-01-30 07:15:00 -05001596 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001597
1598 // read the struct back
1599 assert_success!(i_prot.read_struct_begin());
1600
1601 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001602 assert_eq!(
1603 read_ident_1,
1604 TFieldIdentifier {
1605 name: None,
1606 ..field_ident_1
1607 }
1608 );
Allen George8b96bfb2016-11-02 08:01:08 -04001609 assert_success!(i_prot.read_field_end());
1610
1611 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001612 assert_eq!(
1613 read_ident_2,
1614 TFieldIdentifier {
1615 name: None,
1616 ..field_ident_2
1617 }
1618 );
Allen George8b96bfb2016-11-02 08:01:08 -04001619 assert_success!(i_prot.read_field_end());
1620
1621 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001622 assert_eq!(
1623 read_ident_3,
1624 TFieldIdentifier {
1625 name: None,
1626 ..field_ident_3
1627 }
1628 );
Allen George8b96bfb2016-11-02 08:01:08 -04001629 assert_success!(i_prot.read_field_end());
1630
1631 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001632 assert_eq!(
1633 read_ident_4,
1634 TFieldIdentifier {
1635 name: None,
1636 ..field_ident_4
1637 }
1638 );
Allen George8b96bfb2016-11-02 08:01:08 -04001639 assert_success!(i_prot.read_field_end());
1640
1641 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001642 assert_eq!(
1643 read_ident_5,
1644 TFieldIdentifier {
1645 name: None,
1646 ..field_ident_5
1647 }
1648 );
Allen George8b96bfb2016-11-02 08:01:08 -04001649 assert_success!(i_prot.read_field_end());
1650
1651 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001652 assert_eq!(
1653 read_ident_6,
1654 TFieldIdentifier {
1655 name: None,
1656 field_type: TType::Stop,
1657 id: None,
1658 }
1659 );
Allen George8b96bfb2016-11-02 08:01:08 -04001660
1661 assert_success!(i_prot.read_struct_end());
1662 }
1663
1664 #[test]
1665 fn must_write_nested_structs_0() {
1666 // last field of the containing struct is a delta
1667 // first field of the the contained struct is a delta
1668
Allen George0e22c362017-01-30 07:15:00 -05001669 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001670
1671 // start containing struct
1672 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1673
1674 // containing struct
1675 // since the delta is > 0 and < 15 it gets a delta write
1676 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1677 assert_success!(o_prot.write_field_end());
1678
1679 // containing struct
1680 // since this delta > 0 and < 15 it gets a delta write
1681 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1682 assert_success!(o_prot.write_field_end());
1683
1684 // start contained struct
1685 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1686
1687 // contained struct
1688 // since the delta is > 0 and < 15 it gets a delta write
1689 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
1690 assert_success!(o_prot.write_field_end());
1691
1692 // contained struct
1693 // since this delta > 15 it gets a full write
1694 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1695 assert_success!(o_prot.write_field_end());
1696
1697 // end contained struct
1698 assert_success!(o_prot.write_field_stop());
1699 assert_success!(o_prot.write_struct_end());
1700
1701 // end containing struct
1702 assert_success!(o_prot.write_field_stop());
1703 assert_success!(o_prot.write_struct_end());
1704
Allen George7ddbcc02020-11-08 09:51:19 -05001705 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001706 let expected: [u8; 7] = [
1707 0x16, /* field delta (1) | field type */
1708 0x85, /* field delta (8) | field type */
1709 0x73, /* field delta (7) | field type */
1710 0x07, /* field type */
1711 0x30, /* zig-zag varint field id */
1712 0x00, /* field stop - contained */
1713 0x00 /* field stop - containing */,
1714 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001715
Allen George0e22c362017-01-30 07:15:00 -05001716 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001717 }
1718
Allen George7ddbcc02020-11-08 09:51:19 -05001719 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001720 #[test]
1721 fn must_round_trip_nested_structs_0() {
1722 // last field of the containing struct is a delta
1723 // first field of the the contained struct is a delta
1724
Allen George0e22c362017-01-30 07:15:00 -05001725 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001726
1727 // start containing struct
1728 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1729
1730 // containing struct
1731 // since the delta is > 0 and < 15 it gets a delta write
1732 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1733 assert_success!(o_prot.write_field_begin(&field_ident_1));
1734 assert_success!(o_prot.write_field_end());
1735
1736 // containing struct
1737 // since this delta > 0 and < 15 it gets a delta write
1738 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1739 assert_success!(o_prot.write_field_begin(&field_ident_2));
1740 assert_success!(o_prot.write_field_end());
1741
1742 // start contained struct
1743 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1744
1745 // contained struct
1746 // since the delta is > 0 and < 15 it gets a delta write
1747 let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
1748 assert_success!(o_prot.write_field_begin(&field_ident_3));
1749 assert_success!(o_prot.write_field_end());
1750
1751 // contained struct
1752 // since this delta > 15 it gets a full write
1753 let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
1754 assert_success!(o_prot.write_field_begin(&field_ident_4));
1755 assert_success!(o_prot.write_field_end());
1756
1757 // end contained struct
1758 assert_success!(o_prot.write_field_stop());
1759 assert_success!(o_prot.write_struct_end());
1760
1761 // end containing struct
1762 assert_success!(o_prot.write_field_stop());
1763 assert_success!(o_prot.write_struct_end());
1764
Allen George0e22c362017-01-30 07:15:00 -05001765 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001766
1767 // read containing struct back
1768 assert_success!(i_prot.read_struct_begin());
1769
1770 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001771 assert_eq!(
1772 read_ident_1,
1773 TFieldIdentifier {
1774 name: None,
1775 ..field_ident_1
1776 }
1777 );
Allen George8b96bfb2016-11-02 08:01:08 -04001778 assert_success!(i_prot.read_field_end());
1779
1780 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001781 assert_eq!(
1782 read_ident_2,
1783 TFieldIdentifier {
1784 name: None,
1785 ..field_ident_2
1786 }
1787 );
Allen George8b96bfb2016-11-02 08:01:08 -04001788 assert_success!(i_prot.read_field_end());
1789
1790 // read contained struct back
1791 assert_success!(i_prot.read_struct_begin());
1792
1793 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001794 assert_eq!(
1795 read_ident_3,
1796 TFieldIdentifier {
1797 name: None,
1798 ..field_ident_3
1799 }
1800 );
Allen George8b96bfb2016-11-02 08:01:08 -04001801 assert_success!(i_prot.read_field_end());
1802
1803 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001804 assert_eq!(
1805 read_ident_4,
1806 TFieldIdentifier {
1807 name: None,
1808 ..field_ident_4
1809 }
1810 );
Allen George8b96bfb2016-11-02 08:01:08 -04001811 assert_success!(i_prot.read_field_end());
1812
1813 // end contained struct
1814 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001815 assert_eq!(
1816 read_ident_6,
1817 TFieldIdentifier {
1818 name: None,
1819 field_type: TType::Stop,
1820 id: None,
1821 }
1822 );
Allen George8b96bfb2016-11-02 08:01:08 -04001823 assert_success!(i_prot.read_struct_end());
1824
1825 // end containing struct
1826 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001827 assert_eq!(
1828 read_ident_7,
1829 TFieldIdentifier {
1830 name: None,
1831 field_type: TType::Stop,
1832 id: None,
1833 }
1834 );
Allen George8b96bfb2016-11-02 08:01:08 -04001835 assert_success!(i_prot.read_struct_end());
1836 }
1837
1838 #[test]
1839 fn must_write_nested_structs_1() {
1840 // last field of the containing struct is a delta
1841 // first field of the the contained struct is a full write
1842
Allen George0e22c362017-01-30 07:15:00 -05001843 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001844
1845 // start containing struct
1846 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1847
1848 // containing struct
1849 // since the delta is > 0 and < 15 it gets a delta write
1850 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1851 assert_success!(o_prot.write_field_end());
1852
1853 // containing struct
1854 // since this delta > 0 and < 15 it gets a delta write
1855 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1856 assert_success!(o_prot.write_field_end());
1857
1858 // start contained struct
1859 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1860
1861 // contained struct
1862 // since this delta > 15 it gets a full write
1863 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1864 assert_success!(o_prot.write_field_end());
1865
1866 // contained struct
1867 // since the delta is > 0 and < 15 it gets a delta write
1868 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1869 assert_success!(o_prot.write_field_end());
1870
1871 // end contained struct
1872 assert_success!(o_prot.write_field_stop());
1873 assert_success!(o_prot.write_struct_end());
1874
1875 // end containing struct
1876 assert_success!(o_prot.write_field_stop());
1877 assert_success!(o_prot.write_struct_end());
1878
Allen George7ddbcc02020-11-08 09:51:19 -05001879 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001880 let expected: [u8; 7] = [
1881 0x16, /* field delta (1) | field type */
1882 0x85, /* field delta (8) | field type */
1883 0x07, /* field type */
1884 0x30, /* zig-zag varint field id */
1885 0x33, /* field delta (3) | field type */
1886 0x00, /* field stop - contained */
1887 0x00 /* field stop - containing */,
1888 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001889
Allen George0e22c362017-01-30 07:15:00 -05001890 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001891 }
1892
Allen George7ddbcc02020-11-08 09:51:19 -05001893 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001894 #[test]
1895 fn must_round_trip_nested_structs_1() {
1896 // last field of the containing struct is a delta
1897 // first field of the the contained struct is a full write
1898
Allen George0e22c362017-01-30 07:15:00 -05001899 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001900
1901 // start containing struct
1902 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1903
1904 // containing struct
1905 // since the delta is > 0 and < 15 it gets a delta write
1906 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1907 assert_success!(o_prot.write_field_begin(&field_ident_1));
1908 assert_success!(o_prot.write_field_end());
1909
1910 // containing struct
1911 // since this delta > 0 and < 15 it gets a delta write
1912 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1913 assert_success!(o_prot.write_field_begin(&field_ident_2));
1914 assert_success!(o_prot.write_field_end());
1915
1916 // start contained struct
1917 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1918
1919 // contained struct
1920 // since this delta > 15 it gets a full write
1921 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
1922 assert_success!(o_prot.write_field_begin(&field_ident_3));
1923 assert_success!(o_prot.write_field_end());
1924
1925 // contained struct
1926 // since the delta is > 0 and < 15 it gets a delta write
1927 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
1928 assert_success!(o_prot.write_field_begin(&field_ident_4));
1929 assert_success!(o_prot.write_field_end());
1930
1931 // end contained struct
1932 assert_success!(o_prot.write_field_stop());
1933 assert_success!(o_prot.write_struct_end());
1934
1935 // end containing struct
1936 assert_success!(o_prot.write_field_stop());
1937 assert_success!(o_prot.write_struct_end());
1938
Allen George0e22c362017-01-30 07:15:00 -05001939 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001940
1941 // read containing struct back
1942 assert_success!(i_prot.read_struct_begin());
1943
1944 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001945 assert_eq!(
1946 read_ident_1,
1947 TFieldIdentifier {
1948 name: None,
1949 ..field_ident_1
1950 }
1951 );
Allen George8b96bfb2016-11-02 08:01:08 -04001952 assert_success!(i_prot.read_field_end());
1953
1954 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001955 assert_eq!(
1956 read_ident_2,
1957 TFieldIdentifier {
1958 name: None,
1959 ..field_ident_2
1960 }
1961 );
Allen George8b96bfb2016-11-02 08:01:08 -04001962 assert_success!(i_prot.read_field_end());
1963
1964 // read contained struct back
1965 assert_success!(i_prot.read_struct_begin());
1966
1967 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001968 assert_eq!(
1969 read_ident_3,
1970 TFieldIdentifier {
1971 name: None,
1972 ..field_ident_3
1973 }
1974 );
Allen George8b96bfb2016-11-02 08:01:08 -04001975 assert_success!(i_prot.read_field_end());
1976
1977 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001978 assert_eq!(
1979 read_ident_4,
1980 TFieldIdentifier {
1981 name: None,
1982 ..field_ident_4
1983 }
1984 );
Allen George8b96bfb2016-11-02 08:01:08 -04001985 assert_success!(i_prot.read_field_end());
1986
1987 // end contained struct
1988 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001989 assert_eq!(
1990 read_ident_6,
1991 TFieldIdentifier {
1992 name: None,
1993 field_type: TType::Stop,
1994 id: None,
1995 }
1996 );
Allen George8b96bfb2016-11-02 08:01:08 -04001997 assert_success!(i_prot.read_struct_end());
1998
1999 // end containing struct
2000 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002001 assert_eq!(
2002 read_ident_7,
2003 TFieldIdentifier {
2004 name: None,
2005 field_type: TType::Stop,
2006 id: None,
2007 }
2008 );
Allen George8b96bfb2016-11-02 08:01:08 -04002009 assert_success!(i_prot.read_struct_end());
2010 }
2011
2012 #[test]
2013 fn must_write_nested_structs_2() {
2014 // last field of the containing struct is a full write
2015 // first field of the the contained struct is a delta write
2016
Allen George0e22c362017-01-30 07:15:00 -05002017 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002018
2019 // start containing struct
2020 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2021
2022 // containing struct
2023 // since the delta is > 0 and < 15 it gets a delta write
2024 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2025 assert_success!(o_prot.write_field_end());
2026
2027 // containing struct
2028 // since this delta > 15 it gets a full write
2029 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2030 assert_success!(o_prot.write_field_end());
2031
2032 // start contained struct
2033 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2034
2035 // contained struct
2036 // since this delta > 0 and < 15 it gets a delta write
2037 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
2038 assert_success!(o_prot.write_field_end());
2039
2040 // contained struct
2041 // since the delta is > 0 and < 15 it gets a delta write
2042 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
2043 assert_success!(o_prot.write_field_end());
2044
2045 // end contained struct
2046 assert_success!(o_prot.write_field_stop());
2047 assert_success!(o_prot.write_struct_end());
2048
2049 // end containing struct
2050 assert_success!(o_prot.write_field_stop());
2051 assert_success!(o_prot.write_struct_end());
2052
Allen George7ddbcc02020-11-08 09:51:19 -05002053 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002054 let expected: [u8; 7] = [
2055 0x16, /* field delta (1) | field type */
2056 0x08, /* field type */
2057 0x2A, /* zig-zag varint field id */
2058 0x77, /* field delta(7) | field type */
2059 0x33, /* field delta (3) | field type */
2060 0x00, /* field stop - contained */
2061 0x00 /* field stop - containing */,
2062 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002063
Allen George0e22c362017-01-30 07:15:00 -05002064 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002065 }
2066
Allen George7ddbcc02020-11-08 09:51:19 -05002067 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002068 #[test]
2069 fn must_round_trip_nested_structs_2() {
Allen George0e22c362017-01-30 07:15:00 -05002070 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002071
2072 // start containing struct
2073 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2074
2075 // containing struct
2076 // since the delta is > 0 and < 15 it gets a delta write
2077 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2078 assert_success!(o_prot.write_field_begin(&field_ident_1));
2079 assert_success!(o_prot.write_field_end());
2080
2081 // containing struct
2082 // since this delta > 15 it gets a full write
2083 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2084 assert_success!(o_prot.write_field_begin(&field_ident_2));
2085 assert_success!(o_prot.write_field_end());
2086
2087 // start contained struct
2088 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2089
2090 // contained struct
2091 // since this delta > 0 and < 15 it gets a delta write
2092 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
2093 assert_success!(o_prot.write_field_begin(&field_ident_3));
2094 assert_success!(o_prot.write_field_end());
2095
2096 // contained struct
2097 // since the delta is > 0 and < 15 it gets a delta write
2098 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
2099 assert_success!(o_prot.write_field_begin(&field_ident_4));
2100 assert_success!(o_prot.write_field_end());
2101
2102 // end contained struct
2103 assert_success!(o_prot.write_field_stop());
2104 assert_success!(o_prot.write_struct_end());
2105
2106 // end containing struct
2107 assert_success!(o_prot.write_field_stop());
2108 assert_success!(o_prot.write_struct_end());
2109
Allen George0e22c362017-01-30 07:15:00 -05002110 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002111
2112 // read containing struct back
2113 assert_success!(i_prot.read_struct_begin());
2114
2115 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002116 assert_eq!(
2117 read_ident_1,
2118 TFieldIdentifier {
2119 name: None,
2120 ..field_ident_1
2121 }
2122 );
Allen George8b96bfb2016-11-02 08:01:08 -04002123 assert_success!(i_prot.read_field_end());
2124
2125 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002126 assert_eq!(
2127 read_ident_2,
2128 TFieldIdentifier {
2129 name: None,
2130 ..field_ident_2
2131 }
2132 );
Allen George8b96bfb2016-11-02 08:01:08 -04002133 assert_success!(i_prot.read_field_end());
2134
2135 // read contained struct back
2136 assert_success!(i_prot.read_struct_begin());
2137
2138 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002139 assert_eq!(
2140 read_ident_3,
2141 TFieldIdentifier {
2142 name: None,
2143 ..field_ident_3
2144 }
2145 );
Allen George8b96bfb2016-11-02 08:01:08 -04002146 assert_success!(i_prot.read_field_end());
2147
2148 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002149 assert_eq!(
2150 read_ident_4,
2151 TFieldIdentifier {
2152 name: None,
2153 ..field_ident_4
2154 }
2155 );
Allen George8b96bfb2016-11-02 08:01:08 -04002156 assert_success!(i_prot.read_field_end());
2157
2158 // end contained struct
2159 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002160 assert_eq!(
2161 read_ident_6,
2162 TFieldIdentifier {
2163 name: None,
2164 field_type: TType::Stop,
2165 id: None,
2166 }
2167 );
Allen George8b96bfb2016-11-02 08:01:08 -04002168 assert_success!(i_prot.read_struct_end());
2169
2170 // end containing struct
2171 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002172 assert_eq!(
2173 read_ident_7,
2174 TFieldIdentifier {
2175 name: None,
2176 field_type: TType::Stop,
2177 id: None,
2178 }
2179 );
Allen George8b96bfb2016-11-02 08:01:08 -04002180 assert_success!(i_prot.read_struct_end());
2181 }
2182
2183 #[test]
2184 fn must_write_nested_structs_3() {
2185 // last field of the containing struct is a full write
2186 // first field of the the contained struct is a full write
2187
Allen George0e22c362017-01-30 07:15:00 -05002188 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002189
2190 // start containing struct
2191 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2192
2193 // containing struct
2194 // since the delta is > 0 and < 15 it gets a delta write
2195 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2196 assert_success!(o_prot.write_field_end());
2197
2198 // containing struct
2199 // since this delta > 15 it gets a full write
2200 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2201 assert_success!(o_prot.write_field_end());
2202
2203 // start contained struct
2204 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2205
2206 // contained struct
2207 // since this delta > 15 it gets a full write
2208 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
2209 assert_success!(o_prot.write_field_end());
2210
2211 // contained struct
2212 // since the delta is > 0 and < 15 it gets a delta write
2213 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
2214 assert_success!(o_prot.write_field_end());
2215
2216 // end contained struct
2217 assert_success!(o_prot.write_field_stop());
2218 assert_success!(o_prot.write_struct_end());
2219
2220 // end containing struct
2221 assert_success!(o_prot.write_field_stop());
2222 assert_success!(o_prot.write_struct_end());
2223
Allen George7ddbcc02020-11-08 09:51:19 -05002224 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002225 let expected: [u8; 8] = [
2226 0x16, /* field delta (1) | field type */
2227 0x08, /* field type */
2228 0x2A, /* zig-zag varint field id */
2229 0x07, /* field type */
2230 0x2A, /* zig-zag varint field id */
2231 0x63, /* field delta (6) | field type */
2232 0x00, /* field stop - contained */
2233 0x00 /* field stop - containing */,
2234 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002235
Allen George0e22c362017-01-30 07:15:00 -05002236 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002237 }
2238
Allen George7ddbcc02020-11-08 09:51:19 -05002239 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002240 #[test]
2241 fn must_round_trip_nested_structs_3() {
2242 // last field of the containing struct is a full write
2243 // first field of the the contained struct is a full write
2244
Allen George0e22c362017-01-30 07:15:00 -05002245 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002246
2247 // start containing struct
2248 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2249
2250 // containing struct
2251 // since the delta is > 0 and < 15 it gets a delta write
2252 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2253 assert_success!(o_prot.write_field_begin(&field_ident_1));
2254 assert_success!(o_prot.write_field_end());
2255
2256 // containing struct
2257 // since this delta > 15 it gets a full write
2258 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2259 assert_success!(o_prot.write_field_begin(&field_ident_2));
2260 assert_success!(o_prot.write_field_end());
2261
2262 // start contained struct
2263 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2264
2265 // contained struct
2266 // since this delta > 15 it gets a full write
2267 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
2268 assert_success!(o_prot.write_field_begin(&field_ident_3));
2269 assert_success!(o_prot.write_field_end());
2270
2271 // contained struct
2272 // since the delta is > 0 and < 15 it gets a delta write
2273 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2274 assert_success!(o_prot.write_field_begin(&field_ident_4));
2275 assert_success!(o_prot.write_field_end());
2276
2277 // end contained struct
2278 assert_success!(o_prot.write_field_stop());
2279 assert_success!(o_prot.write_struct_end());
2280
2281 // end containing struct
2282 assert_success!(o_prot.write_field_stop());
2283 assert_success!(o_prot.write_struct_end());
2284
Allen George0e22c362017-01-30 07:15:00 -05002285 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002286
2287 // read containing struct back
2288 assert_success!(i_prot.read_struct_begin());
2289
2290 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002291 assert_eq!(
2292 read_ident_1,
2293 TFieldIdentifier {
2294 name: None,
2295 ..field_ident_1
2296 }
2297 );
Allen George8b96bfb2016-11-02 08:01:08 -04002298 assert_success!(i_prot.read_field_end());
2299
2300 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002301 assert_eq!(
2302 read_ident_2,
2303 TFieldIdentifier {
2304 name: None,
2305 ..field_ident_2
2306 }
2307 );
Allen George8b96bfb2016-11-02 08:01:08 -04002308 assert_success!(i_prot.read_field_end());
2309
2310 // read contained struct back
2311 assert_success!(i_prot.read_struct_begin());
2312
2313 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002314 assert_eq!(
2315 read_ident_3,
2316 TFieldIdentifier {
2317 name: None,
2318 ..field_ident_3
2319 }
2320 );
Allen George8b96bfb2016-11-02 08:01:08 -04002321 assert_success!(i_prot.read_field_end());
2322
2323 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002324 assert_eq!(
2325 read_ident_4,
2326 TFieldIdentifier {
2327 name: None,
2328 ..field_ident_4
2329 }
2330 );
Allen George8b96bfb2016-11-02 08:01:08 -04002331 assert_success!(i_prot.read_field_end());
2332
2333 // end contained struct
2334 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002335 assert_eq!(
2336 read_ident_6,
2337 TFieldIdentifier {
2338 name: None,
2339 field_type: TType::Stop,
2340 id: None,
2341 }
2342 );
Allen George8b96bfb2016-11-02 08:01:08 -04002343 assert_success!(i_prot.read_struct_end());
2344
2345 // end containing struct
2346 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002347 assert_eq!(
2348 read_ident_7,
2349 TFieldIdentifier {
2350 name: None,
2351 field_type: TType::Stop,
2352 id: None,
2353 }
2354 );
Allen George8b96bfb2016-11-02 08:01:08 -04002355 assert_success!(i_prot.read_struct_end());
2356 }
2357
2358 #[test]
2359 fn must_write_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002360 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002361
2362 // no bytes should be written however
2363 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2364
2365 // write three fields with field ids that cannot be encoded as deltas
2366
2367 // since the delta is > 0 and < 16 it gets a delta write
2368 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2369 assert_success!(o_prot.write_bool(true));
2370 assert_success!(o_prot.write_field_end());
2371
2372 // since this delta > 0 and < 15 it gets a delta write
2373 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
2374 assert_success!(o_prot.write_bool(false));
2375 assert_success!(o_prot.write_field_end());
2376
2377 // since this delta > 15 it gets a full write
2378 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
2379 assert_success!(o_prot.write_bool(true));
2380 assert_success!(o_prot.write_field_end());
2381
2382 // since this delta > 15 it gets a full write
2383 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
2384 assert_success!(o_prot.write_bool(false));
2385 assert_success!(o_prot.write_field_end());
2386
2387 // now, finish the struct off
2388 assert_success!(o_prot.write_field_stop());
2389 assert_success!(o_prot.write_struct_end());
2390
Allen George7ddbcc02020-11-08 09:51:19 -05002391 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002392 let expected: [u8; 7] = [
2393 0x11, /* field delta (1) | true */
2394 0x82, /* field delta (8) | false */
2395 0x01, /* true */
2396 0x34, /* field id */
2397 0x02, /* false */
2398 0x5A, /* field id */
2399 0x00 /* stop field */,
2400 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002401
Allen George0e22c362017-01-30 07:15:00 -05002402 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002403 }
2404
Allen George7ddbcc02020-11-08 09:51:19 -05002405 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002406 #[test]
2407 fn must_round_trip_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002408 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002409
2410 // no bytes should be written however
2411 let struct_ident = TStructIdentifier::new("foo");
2412 assert_success!(o_prot.write_struct_begin(&struct_ident));
2413
2414 // write two fields
2415
2416 // since the delta is > 0 and < 16 it gets a delta write
2417 let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
2418 assert_success!(o_prot.write_field_begin(&field_ident_1));
2419 assert_success!(o_prot.write_bool(true));
2420 assert_success!(o_prot.write_field_end());
2421
2422 // since this delta > 0 and < 15 it gets a delta write
2423 let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
2424 assert_success!(o_prot.write_field_begin(&field_ident_2));
2425 assert_success!(o_prot.write_bool(false));
2426 assert_success!(o_prot.write_field_end());
2427
2428 // since this delta > 15 it gets a full write
2429 let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
2430 assert_success!(o_prot.write_field_begin(&field_ident_3));
2431 assert_success!(o_prot.write_bool(true));
2432 assert_success!(o_prot.write_field_end());
2433
2434 // since this delta > 15 it gets a full write
2435 let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
2436 assert_success!(o_prot.write_field_begin(&field_ident_4));
2437 assert_success!(o_prot.write_bool(false));
2438 assert_success!(o_prot.write_field_end());
2439
2440 // now, finish the struct off
2441 assert_success!(o_prot.write_field_stop());
2442 assert_success!(o_prot.write_struct_end());
2443
Allen George0e22c362017-01-30 07:15:00 -05002444 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002445
2446 // read the struct back
2447 assert_success!(i_prot.read_struct_begin());
2448
2449 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002450 assert_eq!(
2451 read_ident_1,
2452 TFieldIdentifier {
2453 name: None,
2454 ..field_ident_1
2455 }
2456 );
Allen George8b96bfb2016-11-02 08:01:08 -04002457 let read_value_1 = assert_success!(i_prot.read_bool());
2458 assert_eq!(read_value_1, true);
2459 assert_success!(i_prot.read_field_end());
2460
2461 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002462 assert_eq!(
2463 read_ident_2,
2464 TFieldIdentifier {
2465 name: None,
2466 ..field_ident_2
2467 }
2468 );
Allen George8b96bfb2016-11-02 08:01:08 -04002469 let read_value_2 = assert_success!(i_prot.read_bool());
2470 assert_eq!(read_value_2, false);
2471 assert_success!(i_prot.read_field_end());
2472
2473 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002474 assert_eq!(
2475 read_ident_3,
2476 TFieldIdentifier {
2477 name: None,
2478 ..field_ident_3
2479 }
2480 );
Allen George8b96bfb2016-11-02 08:01:08 -04002481 let read_value_3 = assert_success!(i_prot.read_bool());
2482 assert_eq!(read_value_3, true);
2483 assert_success!(i_prot.read_field_end());
2484
2485 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002486 assert_eq!(
2487 read_ident_4,
2488 TFieldIdentifier {
2489 name: None,
2490 ..field_ident_4
2491 }
2492 );
Allen George8b96bfb2016-11-02 08:01:08 -04002493 let read_value_4 = assert_success!(i_prot.read_bool());
2494 assert_eq!(read_value_4, false);
2495 assert_success!(i_prot.read_field_end());
2496
2497 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002498 assert_eq!(
2499 read_ident_5,
2500 TFieldIdentifier {
2501 name: None,
2502 field_type: TType::Stop,
2503 id: None,
2504 }
2505 );
Allen George8b96bfb2016-11-02 08:01:08 -04002506
2507 assert_success!(i_prot.read_struct_end());
2508 }
2509
2510 #[test]
2511 #[should_panic]
2512 fn must_fail_if_write_field_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002513 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002514 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2515 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2516 o_prot.write_field_end().unwrap();
2517 }
2518
2519 #[test]
2520 #[should_panic]
2521 fn must_fail_if_write_stop_field_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002522 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002523 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2524 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2525 o_prot.write_field_stop().unwrap();
2526 }
2527
2528 #[test]
2529 #[should_panic]
2530 fn must_fail_if_write_struct_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002531 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002532 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2533 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2534 o_prot.write_struct_end().unwrap();
2535 }
2536
2537 #[test]
2538 #[should_panic]
2539 fn must_fail_if_write_struct_end_without_any_fields() {
Allen George0e22c362017-01-30 07:15:00 -05002540 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002541 o_prot.write_struct_end().unwrap();
2542 }
2543
2544 #[test]
2545 fn must_write_field_end() {
2546 assert_no_write(|o| o.write_field_end());
2547 }
2548
2549 #[test]
2550 fn must_write_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002551 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002552
2553 assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
2554
2555 let expected: [u8; 1] = [0x46 /* size | elem_type */];
2556
Allen George0e22c362017-01-30 07:15:00 -05002557 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002558 }
2559
2560 #[test]
2561 fn must_round_trip_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002562 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002563
2564 let ident = TListIdentifier::new(TType::I08, 10);
2565
2566 assert_success!(o_prot.write_list_begin(&ident));
2567
Allen George0e22c362017-01-30 07:15:00 -05002568 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002569
2570 let res = assert_success!(i_prot.read_list_begin());
2571 assert_eq!(&res, &ident);
2572 }
2573
2574 #[test]
2575 fn must_write_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002576 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002577
2578 let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
2579 assert!(res.is_ok());
2580
Allen George0e22c362017-01-30 07:15:00 -05002581 let expected: [u8; 3] = [
2582 0xF9, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002583 0x8F, 0x4E, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002584 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002585
Allen George0e22c362017-01-30 07:15:00 -05002586 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002587 }
2588
2589 #[test]
2590 fn must_round_trip_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002591 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002592
2593 let ident = TListIdentifier::new(TType::Set, 47381);
2594
2595 assert_success!(o_prot.write_list_begin(&ident));
2596
Allen George0e22c362017-01-30 07:15:00 -05002597 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002598
2599 let res = assert_success!(i_prot.read_list_begin());
2600 assert_eq!(&res, &ident);
2601 }
2602
2603 #[test]
2604 fn must_write_list_end() {
2605 assert_no_write(|o| o.write_list_end());
2606 }
2607
2608 #[test]
2609 fn must_write_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002610 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002611
2612 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
2613
2614 let expected: [u8; 1] = [0x2C /* size | elem_type */];
2615
Allen George0e22c362017-01-30 07:15:00 -05002616 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002617 }
2618
2619 #[test]
2620 fn must_round_trip_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002621 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002622
2623 let ident = TSetIdentifier::new(TType::I16, 7);
2624
2625 assert_success!(o_prot.write_set_begin(&ident));
2626
Allen George0e22c362017-01-30 07:15:00 -05002627 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002628
2629 let res = assert_success!(i_prot.read_set_begin());
2630 assert_eq!(&res, &ident);
2631 }
2632
2633 #[test]
2634 fn must_write_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002635 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002636
2637 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
2638
Allen George0e22c362017-01-30 07:15:00 -05002639 let expected: [u8; 4] = [
2640 0xF7, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002641 0xD3, 0xBA, 0x01, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002642 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002643
Allen George0e22c362017-01-30 07:15:00 -05002644 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002645 }
2646
2647 #[test]
2648 fn must_round_trip_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002649 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002650
Allen George7ddbcc02020-11-08 09:51:19 -05002651 let ident = TSetIdentifier::new(TType::Map, 3_928_429);
Allen George8b96bfb2016-11-02 08:01:08 -04002652
2653 assert_success!(o_prot.write_set_begin(&ident));
2654
Allen George0e22c362017-01-30 07:15:00 -05002655 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002656
2657 let res = assert_success!(i_prot.read_set_begin());
2658 assert_eq!(&res, &ident);
2659 }
2660
2661 #[test]
2662 fn must_write_set_end() {
2663 assert_no_write(|o| o.write_set_end());
2664 }
2665
2666 #[test]
2667 fn must_write_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002668 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002669
2670 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
2671
2672 let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything
2673
Allen George0e22c362017-01-30 07:15:00 -05002674 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002675 }
2676
2677 #[test]
2678 fn must_read_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002679 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002680
2681 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
2682
Allen George0e22c362017-01-30 07:15:00 -05002683 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002684
2685 let res = assert_success!(i_prot.read_map_begin());
Allen George0e22c362017-01-30 07:15:00 -05002686 assert_eq!(
2687 &res,
2688 &TMapIdentifier {
Allen Georgeef7a1892018-12-16 18:01:37 -05002689 key_type: None,
2690 value_type: None,
2691 size: 0,
2692 }
Allen George0e22c362017-01-30 07:15:00 -05002693 );
Allen George8b96bfb2016-11-02 08:01:08 -04002694 }
2695
2696 #[test]
2697 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002698 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002699
Allen Georgeef7a1892018-12-16 18:01:37 -05002700 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
2701 TType::Double,
2702 TType::String,
2703 238
2704 )));
Allen George8b96bfb2016-11-02 08:01:08 -04002705
Allen George0e22c362017-01-30 07:15:00 -05002706 let expected: [u8; 3] = [
Allen Georgeef7a1892018-12-16 18:01:37 -05002707 0xEE, 0x01, /* size as varint */
2708 0x78, /* key type | val type */
Allen George0e22c362017-01-30 07:15:00 -05002709 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002710
Allen George0e22c362017-01-30 07:15:00 -05002711 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002712 }
2713
2714 #[test]
2715 fn must_round_trip_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002716 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002717
Allen George7ddbcc02020-11-08 09:51:19 -05002718 let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349);
Allen George8b96bfb2016-11-02 08:01:08 -04002719
2720 assert_success!(o_prot.write_map_begin(&ident));
2721
Allen George0e22c362017-01-30 07:15:00 -05002722 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002723
2724 let res = assert_success!(i_prot.read_map_begin());
2725 assert_eq!(&res, &ident);
2726 }
2727
2728 #[test]
2729 fn must_write_map_end() {
2730 assert_no_write(|o| o.write_map_end());
2731 }
2732
2733 #[test]
2734 fn must_write_map_with_bool_key_and_value() {
Allen George0e22c362017-01-30 07:15:00 -05002735 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002736
2737 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
2738 assert_success!(o_prot.write_bool(true));
2739 assert_success!(o_prot.write_bool(false));
2740 assert_success!(o_prot.write_map_end());
2741
Allen George0e22c362017-01-30 07:15:00 -05002742 let expected: [u8; 4] = [
2743 0x01, /* size as varint */
2744 0x11, /* key type | val type */
2745 0x01, /* key: true */
Allen Georgeef7a1892018-12-16 18:01:37 -05002746 0x02, /* val: false */
Allen George0e22c362017-01-30 07:15:00 -05002747 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002748
Allen George0e22c362017-01-30 07:15:00 -05002749 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002750 }
2751
2752 #[test]
2753 fn must_round_trip_map_with_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002754 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002755
2756 let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
2757 assert_success!(o_prot.write_map_begin(&map_ident));
2758 assert_success!(o_prot.write_bool(true));
2759 assert_success!(o_prot.write_bool(false));
2760 assert_success!(o_prot.write_bool(false));
2761 assert_success!(o_prot.write_bool(true));
2762 assert_success!(o_prot.write_map_end());
2763
Allen George0e22c362017-01-30 07:15:00 -05002764 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002765
2766 // map header
2767 let rcvd_ident = assert_success!(i_prot.read_map_begin());
2768 assert_eq!(&rcvd_ident, &map_ident);
2769 // key 1
2770 let b = assert_success!(i_prot.read_bool());
2771 assert_eq!(b, true);
2772 // val 1
2773 let b = assert_success!(i_prot.read_bool());
2774 assert_eq!(b, false);
2775 // key 2
2776 let b = assert_success!(i_prot.read_bool());
2777 assert_eq!(b, false);
2778 // val 2
2779 let b = assert_success!(i_prot.read_bool());
2780 assert_eq!(b, true);
2781 // map end
2782 assert_success!(i_prot.read_map_end());
2783 }
2784
2785 #[test]
2786 fn must_read_map_end() {
Allen George0e22c362017-01-30 07:15:00 -05002787 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002788 assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
2789 }
2790
Allen Georgeef7a1892018-12-16 18:01:37 -05002791 fn test_objects() -> (
2792 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2793 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2794 ) {
Allen George0e22c362017-01-30 07:15:00 -05002795 let mem = TBufferChannel::with_capacity(80, 80);
Allen George8b96bfb2016-11-02 08:01:08 -04002796
Allen George0e22c362017-01-30 07:15:00 -05002797 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -04002798
Allen George0e22c362017-01-30 07:15:00 -05002799 let i_prot = TCompactInputProtocol::new(r_mem);
2800 let o_prot = TCompactOutputProtocol::new(w_mem);
Allen George8b96bfb2016-11-02 08:01:08 -04002801
Allen George0e22c362017-01-30 07:15:00 -05002802 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -04002803 }
2804
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002805 #[test]
2806 fn must_read_write_double() {
2807 let (mut i_prot, mut o_prot) = test_objects();
2808
Allen George7ddbcc02020-11-08 09:51:19 -05002809 #[allow(clippy::approx_constant)]
2810 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002811 o_prot.write_double(double).unwrap();
2812 copy_write_buffer_to_read_buffer!(o_prot);
2813
Allen George7ddbcc02020-11-08 09:51:19 -05002814 let read_double = i_prot.read_double().unwrap();
2815 assert!(read_double - double < std::f64::EPSILON);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002816 }
2817
2818 #[test]
2819 fn must_encode_double_as_other_langs() {
2820 let (_, mut o_prot) = test_objects();
2821 let expected = [24, 45, 68, 84, 251, 33, 9, 64];
2822
Allen George7ddbcc02020-11-08 09:51:19 -05002823 #[allow(clippy::approx_constant)]
2824 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002825 o_prot.write_double(double).unwrap();
2826
2827 assert_eq_written_bytes!(o_prot, expected);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002828 }
2829
Allen George0e22c362017-01-30 07:15:00 -05002830 fn assert_no_write<F>(mut write_fn: F)
2831 where
Allen Georgeb0d14132020-03-29 11:48:55 -04002832 F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> crate::Result<()>,
Allen George0e22c362017-01-30 07:15:00 -05002833 {
2834 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002835 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -05002836 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -04002837 }
2838}