blob: f885e40228217203920a15e5e64be8fa464395d1 [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
430 self.transport.write_varint(identifier.sequence_number as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400431 self.write_string(&identifier.name)?;
432 Ok(())
433 }
434
Allen Georgeb0d14132020-03-29 11:48:55 -0400435 fn write_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400436 self.assert_no_pending_bool_write();
437 Ok(())
438 }
439
Allen Georgeb0d14132020-03-29 11:48:55 -0400440 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400441 self.write_field_id_stack.push(self.last_write_field_id);
442 self.last_write_field_id = 0;
443 Ok(())
444 }
445
Allen Georgeb0d14132020-03-29 11:48:55 -0400446 fn write_struct_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400447 self.assert_no_pending_bool_write();
Allen Georgeef7a1892018-12-16 18:01:37 -0500448 self.last_write_field_id = self
449 .write_field_id_stack
Allen George0e22c362017-01-30 07:15:00 -0500450 .pop()
451 .expect("should have previous field ids");
Allen George8b96bfb2016-11-02 08:01:08 -0400452 Ok(())
453 }
454
Allen Georgeb0d14132020-03-29 11:48:55 -0400455 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400456 match identifier.field_type {
457 TType::Bool => {
458 if self.pending_write_bool_field_identifier.is_some() {
Allen George0e22c362017-01-30 07:15:00 -0500459 panic!(
460 "should not have a pending bool while writing another bool with id: \
Allen Georgeef7a1892018-12-16 18:01:37 -0500461 {:?}",
Allen George0e22c362017-01-30 07:15:00 -0500462 identifier
463 )
Allen George8b96bfb2016-11-02 08:01:08 -0400464 }
465 self.pending_write_bool_field_identifier = Some(identifier.clone());
466 Ok(())
467 }
468 _ => {
469 let field_type = type_to_u8(identifier.field_type);
Allen Georgeef7a1892018-12-16 18:01:37 -0500470 let field_id = identifier.id.expect("non-stop field should have field id");
Allen George8b96bfb2016-11-02 08:01:08 -0400471 self.write_field_header(field_type, field_id)
472 }
473 }
474 }
475
Allen Georgeb0d14132020-03-29 11:48:55 -0400476 fn write_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400477 self.assert_no_pending_bool_write();
478 Ok(())
479 }
480
Allen Georgeb0d14132020-03-29 11:48:55 -0400481 fn write_field_stop(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400482 self.assert_no_pending_bool_write();
483 self.write_byte(type_to_u8(TType::Stop))
484 }
485
Allen Georgeb0d14132020-03-29 11:48:55 -0400486 fn write_bool(&mut self, b: bool) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400487 match self.pending_write_bool_field_identifier.take() {
488 Some(pending) => {
489 let field_id = pending.id.expect("bool field should have a field id");
490 let field_type_as_u8 = if b { 0x01 } else { 0x02 };
491 self.write_field_header(field_type_as_u8, field_id)
492 }
493 None => {
494 if b {
495 self.write_byte(0x01)
496 } else {
497 self.write_byte(0x02)
498 }
499 }
500 }
501 }
502
Allen Georgeb0d14132020-03-29 11:48:55 -0400503 fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> {
Allen George48905102021-02-20 08:47:01 -0500504 // length is strictly positive as per the spec, so
505 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500506 self.transport.write_varint(b.len() as u32)?;
507 self.transport.write_all(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400508 }
509
Allen Georgeb0d14132020-03-29 11:48:55 -0400510 fn write_i8(&mut self, i: i8) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400511 self.write_byte(i as u8)
512 }
513
Allen Georgeb0d14132020-03-29 11:48:55 -0400514 fn write_i16(&mut self, i: i16) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500515 self.transport
Allen George48905102021-02-20 08:47:01 -0500516 .write_varint(i)
Allen George0e22c362017-01-30 07:15:00 -0500517 .map_err(From::from)
518 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400519 }
520
Allen Georgeb0d14132020-03-29 11:48:55 -0400521 fn write_i32(&mut self, i: i32) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500522 self.transport
523 .write_varint(i)
524 .map_err(From::from)
525 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400526 }
527
Allen Georgeb0d14132020-03-29 11:48:55 -0400528 fn write_i64(&mut self, i: i64) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500529 self.transport
530 .write_varint(i)
531 .map_err(From::from)
532 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400533 }
534
Allen Georgeb0d14132020-03-29 11:48:55 -0400535 fn write_double(&mut self, d: f64) -> crate::Result<()> {
Allen George8a1743d2020-12-05 01:19:27 -0500536 self.transport
537 .write_f64::<LittleEndian>(d)
538 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400539 }
540
Allen Georgeb0d14132020-03-29 11:48:55 -0400541 fn write_string(&mut self, s: &str) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400542 self.write_bytes(s.as_bytes())
543 }
544
Allen Georgeb0d14132020-03-29 11:48:55 -0400545 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400546 self.write_list_set_begin(identifier.element_type, identifier.size)
547 }
548
Allen Georgeb0d14132020-03-29 11:48:55 -0400549 fn write_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400550 Ok(())
551 }
552
Allen Georgeb0d14132020-03-29 11:48:55 -0400553 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400554 self.write_list_set_begin(identifier.element_type, identifier.size)
555 }
556
Allen Georgeb0d14132020-03-29 11:48:55 -0400557 fn write_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400558 Ok(())
559 }
560
Allen Georgeb0d14132020-03-29 11:48:55 -0400561 fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400562 if identifier.size == 0 {
563 self.write_byte(0)
564 } else {
Allen George48905102021-02-20 08:47:01 -0500565 // element count is strictly positive as per the spec, so
566 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500567 self.transport.write_varint(identifier.size as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400568
Allen George0e22c362017-01-30 07:15:00 -0500569 let key_type = identifier
570 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400571 .expect("map identifier to write should contain key type");
572 let key_type_byte = collection_type_to_u8(key_type) << 4;
573
Allen George0e22c362017-01-30 07:15:00 -0500574 let val_type = identifier
575 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400576 .expect("map identifier to write should contain value type");
577 let val_type_byte = collection_type_to_u8(val_type);
578
579 let map_type_header = key_type_byte | val_type_byte;
580 self.write_byte(map_type_header)
581 }
582 }
583
Allen Georgeb0d14132020-03-29 11:48:55 -0400584 fn write_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400585 Ok(())
586 }
587
Allen Georgeb0d14132020-03-29 11:48:55 -0400588 fn flush(&mut self) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500589 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400590 }
591
592 // utility
593 //
594
Allen Georgeb0d14132020-03-29 11:48:55 -0400595 fn write_byte(&mut self, b: u8) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500596 self.transport.write(&[b]).map_err(From::from).map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400597 }
598}
599
600/// Factory for creating instances of `TCompactOutputProtocol`.
601#[derive(Default)]
602pub struct TCompactOutputProtocolFactory;
603
604impl TCompactOutputProtocolFactory {
605 /// Create a `TCompactOutputProtocolFactory`.
606 pub fn new() -> TCompactOutputProtocolFactory {
607 TCompactOutputProtocolFactory {}
608 }
609}
610
611impl TOutputProtocolFactory for TCompactOutputProtocolFactory {
Allen George8a1743d2020-12-05 01:19:27 -0500612 fn create(
613 &self,
614 transport: Box<dyn TWriteTransport + Send>,
615 ) -> Box<dyn TOutputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500616 Box::new(TCompactOutputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400617 }
618}
619
620fn collection_type_to_u8(field_type: TType) -> u8 {
621 match field_type {
622 TType::Bool => 0x01,
623 f => type_to_u8(f),
624 }
625}
626
627fn type_to_u8(field_type: TType) -> u8 {
628 match field_type {
629 TType::Stop => 0x00,
630 TType::I08 => 0x03, // equivalent to TType::Byte
631 TType::I16 => 0x04,
632 TType::I32 => 0x05,
633 TType::I64 => 0x06,
634 TType::Double => 0x07,
635 TType::String => 0x08,
636 TType::List => 0x09,
637 TType::Set => 0x0A,
638 TType::Map => 0x0B,
639 TType::Struct => 0x0C,
Allen Georgeef7a1892018-12-16 18:01:37 -0500640 _ => panic!(format!(
641 "should not have attempted to convert {} to u8",
642 field_type
643 )),
Allen George8b96bfb2016-11-02 08:01:08 -0400644 }
645}
646
Allen Georgeb0d14132020-03-29 11:48:55 -0400647fn collection_u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400648 match b {
649 0x01 => Ok(TType::Bool),
650 o => u8_to_type(o),
651 }
652}
653
Allen Georgeb0d14132020-03-29 11:48:55 -0400654fn u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400655 match b {
656 0x00 => Ok(TType::Stop),
657 0x03 => Ok(TType::I08), // equivalent to TType::Byte
658 0x04 => Ok(TType::I16),
659 0x05 => Ok(TType::I32),
660 0x06 => Ok(TType::I64),
661 0x07 => Ok(TType::Double),
662 0x08 => Ok(TType::String),
663 0x09 => Ok(TType::List),
664 0x0A => Ok(TType::Set),
665 0x0B => Ok(TType::Map),
666 0x0C => Ok(TType::Struct),
Allen Georgeb0d14132020-03-29 11:48:55 -0400667 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
668 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500669 message: format!("cannot convert {} into TType", unkn),
670 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400671 }
672}
673
674#[cfg(test)]
675mod tests {
676
Allen George8a1743d2020-12-05 01:19:27 -0500677 use std::i32;
678
Allen Georgeb0d14132020-03-29 11:48:55 -0400679 use crate::protocol::{
Allen Georgeef7a1892018-12-16 18:01:37 -0500680 TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
681 TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
682 };
Allen Georgeb0d14132020-03-29 11:48:55 -0400683 use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400684
685 use super::*;
686
687 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500688 fn must_write_message_begin_largest_maximum_positive_sequence_number() {
689 let (_, mut o_prot) = test_objects();
690
691 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
692 "bar",
693 TMessageType::Reply,
694 i32::MAX
695 )));
696
697 #[rustfmt::skip]
698 let expected: [u8; 11] = [
699 0x82, /* protocol ID */
700 0x41, /* message type | protocol version */
701 0xFF,
702 0xFF,
703 0xFF,
704 0xFF,
705 0x07, /* non-zig-zag varint sequence number */
706 0x03, /* message-name length */
707 0x62,
708 0x61,
709 0x72 /* "bar" */,
710 ];
711
712 assert_eq_written_bytes!(o_prot, expected);
713 }
714
715 #[test]
716 fn must_read_message_begin_largest_maximum_positive_sequence_number() {
717 let (mut i_prot, _) = test_objects();
718
719 #[rustfmt::skip]
720 let source_bytes: [u8; 11] = [
721 0x82, /* protocol ID */
722 0x41, /* message type | protocol version */
723 0xFF,
724 0xFF,
725 0xFF,
726 0xFF,
727 0x07, /* non-zig-zag varint sequence number */
728 0x03, /* message-name length */
729 0x62,
730 0x61,
731 0x72 /* "bar" */,
732 ];
733
734 i_prot.transport.set_readable_bytes(&source_bytes);
735
736 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MAX);
737 let res = assert_success!(i_prot.read_message_begin());
738
739 assert_eq!(&expected, &res);
740 }
741
742 #[test]
743 fn must_write_message_begin_positive_sequence_number_0() {
Allen George0e22c362017-01-30 07:15:00 -0500744 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400745
Allen Georgeef7a1892018-12-16 18:01:37 -0500746 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
747 "foo",
748 TMessageType::Call,
749 431
750 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400751
Allen George7ddbcc02020-11-08 09:51:19 -0500752 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500753 let expected: [u8; 8] = [
754 0x82, /* protocol ID */
755 0x21, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500756 0xAF,
757 0x03, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500758 0x03, /* message-name length */
759 0x66,
760 0x6F,
761 0x6F /* "foo" */,
762 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400763
Allen George0e22c362017-01-30 07:15:00 -0500764 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400765 }
766
767 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500768 fn must_read_message_begin_positive_sequence_number_0() {
769 let (mut i_prot, _) = test_objects();
770
771 #[rustfmt::skip]
772 let source_bytes: [u8; 8] = [
773 0x82, /* protocol ID */
774 0x21, /* message type | protocol version */
775 0xAF,
776 0x03, /* non-zig-zag varint sequence number */
777 0x03, /* message-name length */
778 0x66,
779 0x6F,
780 0x6F /* "foo" */,
781 ];
782
783 i_prot.transport.set_readable_bytes(&source_bytes);
784
785 let expected = TMessageIdentifier::new("foo", TMessageType::Call, 431);
786 let res = assert_success!(i_prot.read_message_begin());
787
788 assert_eq!(&expected, &res);
789 }
790
791 #[test]
792 fn must_write_message_begin_positive_sequence_number_1() {
Allen George0e22c362017-01-30 07:15:00 -0500793 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400794
Allen Georgeef7a1892018-12-16 18:01:37 -0500795 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
796 "bar",
797 TMessageType::Reply,
Allen George7ddbcc02020-11-08 09:51:19 -0500798 991_828
Allen Georgeef7a1892018-12-16 18:01:37 -0500799 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400800
Allen George7ddbcc02020-11-08 09:51:19 -0500801 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500802 let expected: [u8; 9] = [
803 0x82, /* protocol ID */
804 0x41, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500805 0xD4,
806 0xC4,
807 0x3C, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500808 0x03, /* message-name length */
809 0x62,
810 0x61,
811 0x72 /* "bar" */,
812 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400813
Allen George0e22c362017-01-30 07:15:00 -0500814 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400815 }
816
817 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500818 fn must_read_message_begin_positive_sequence_number_1() {
819 let (mut i_prot, _) = test_objects();
820
821 #[rustfmt::skip]
822 let source_bytes: [u8; 9] = [
823 0x82, /* protocol ID */
824 0x41, /* message type | protocol version */
825 0xD4,
826 0xC4,
827 0x3C, /* non-zig-zag varint sequence number */
828 0x03, /* message-name length */
829 0x62,
830 0x61,
831 0x72 /* "bar" */,
832 ];
833
834 i_prot.transport.set_readable_bytes(&source_bytes);
835
836 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 991_828);
837 let res = assert_success!(i_prot.read_message_begin());
838
839 assert_eq!(&expected, &res);
840 }
841
842 #[test]
843 fn must_write_message_begin_zero_sequence_number() {
844 let (_, mut o_prot) = test_objects();
845
846 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
847 "bar",
848 TMessageType::Reply,
849 0
850 )));
851
852 #[rustfmt::skip]
853 let expected: [u8; 7] = [
854 0x82, /* protocol ID */
855 0x41, /* message type | protocol version */
856 0x00, /* non-zig-zag varint sequence number */
857 0x03, /* message-name length */
858 0x62,
859 0x61,
860 0x72 /* "bar" */,
861 ];
862
863 assert_eq_written_bytes!(o_prot, expected);
864 }
865
866 #[test]
867 fn must_read_message_begin_zero_sequence_number() {
868 let (mut i_prot, _) = test_objects();
869
870 #[rustfmt::skip]
871 let source_bytes: [u8; 7] = [
872 0x82, /* protocol ID */
873 0x41, /* message type | protocol version */
874 0x00, /* non-zig-zag varint sequence number */
875 0x03, /* message-name length */
876 0x62,
877 0x61,
878 0x72 /* "bar" */,
879 ];
880
881 i_prot.transport.set_readable_bytes(&source_bytes);
882
883 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 0);
884 let res = assert_success!(i_prot.read_message_begin());
885
886 assert_eq!(&expected, &res);
887 }
888
889 #[test]
890 fn must_write_message_begin_largest_minimum_negative_sequence_number() {
891 let (_, mut o_prot) = test_objects();
892
893 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
894 "bar",
895 TMessageType::Reply,
896 i32::MIN
897 )));
898
899 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
900 #[rustfmt::skip]
901 let expected: [u8; 11] = [
902 0x82, /* protocol ID */
903 0x41, /* message type | protocol version */
904 0x80,
905 0x80,
906 0x80,
907 0x80,
908 0x08, /* non-zig-zag varint sequence number */
909 0x03, /* message-name length */
910 0x62,
911 0x61,
912 0x72 /* "bar" */,
913 ];
914
915 assert_eq_written_bytes!(o_prot, expected);
916 }
917
918 #[test]
919 fn must_read_message_begin_largest_minimum_negative_sequence_number() {
920 let (mut i_prot, _) = test_objects();
921
922 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
923 #[rustfmt::skip]
924 let source_bytes: [u8; 11] = [
925 0x82, /* protocol ID */
926 0x41, /* message type | protocol version */
927 0x80,
928 0x80,
929 0x80,
930 0x80,
931 0x08, /* non-zig-zag varint sequence number */
932 0x03, /* message-name length */
933 0x62,
934 0x61,
935 0x72 /* "bar" */,
936 ];
937
938 i_prot.transport.set_readable_bytes(&source_bytes);
939
940 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MIN);
941 let res = assert_success!(i_prot.read_message_begin());
942
943 assert_eq!(&expected, &res);
944 }
945
946 #[test]
947 fn must_write_message_begin_negative_sequence_number_0() {
948 let (_, mut o_prot) = test_objects();
949
950 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
951 "foo",
952 TMessageType::Call,
953 -431
954 )));
955
956 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
957 #[rustfmt::skip]
958 let expected: [u8; 11] = [
959 0x82, /* protocol ID */
960 0x21, /* message type | protocol version */
961 0xD1,
962 0xFC,
963 0xFF,
964 0xFF,
965 0x0F, /* non-zig-zag varint sequence number */
966 0x03, /* message-name length */
967 0x66,
968 0x6F,
969 0x6F /* "foo" */,
970 ];
971
972 assert_eq_written_bytes!(o_prot, expected);
973 }
974
975 #[test]
976 fn must_read_message_begin_negative_sequence_number_0() {
977 let (mut i_prot, _) = test_objects();
978
979 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
980 #[rustfmt::skip]
981 let source_bytes: [u8; 11] = [
982 0x82, /* protocol ID */
983 0x21, /* message type | protocol version */
984 0xD1,
985 0xFC,
986 0xFF,
987 0xFF,
988 0x0F, /* non-zig-zag varint sequence number */
989 0x03, /* message-name length */
990 0x66,
991 0x6F,
992 0x6F /* "foo" */,
993 ];
994
995 i_prot.transport.set_readable_bytes(&source_bytes);
996
997 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -431);
998 let res = assert_success!(i_prot.read_message_begin());
999
1000 assert_eq!(&expected, &res);
1001 }
1002
1003 #[test]
1004 fn must_write_message_begin_negative_sequence_number_1() {
1005 let (_, mut o_prot) = test_objects();
1006
1007 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1008 "foo",
1009 TMessageType::Call,
1010 -73_184_125
1011 )));
1012
1013 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1014 #[rustfmt::skip]
1015 let expected: [u8; 11] = [
1016 0x82, /* protocol ID */
1017 0x21, /* message type | protocol version */
1018 0x83,
1019 0x99,
1020 0x8D,
1021 0xDD,
1022 0x0F, /* non-zig-zag varint sequence number */
1023 0x03, /* message-name length */
1024 0x66,
1025 0x6F,
1026 0x6F /* "foo" */,
1027 ];
1028
1029 assert_eq_written_bytes!(o_prot, expected);
1030 }
1031
1032 #[test]
1033 fn must_read_message_begin_negative_sequence_number_1() {
1034 let (mut i_prot, _) = test_objects();
1035
1036 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1037 #[rustfmt::skip]
1038 let source_bytes: [u8; 11] = [
1039 0x82, /* protocol ID */
1040 0x21, /* message type | protocol version */
1041 0x83,
1042 0x99,
1043 0x8D,
1044 0xDD,
1045 0x0F, /* non-zig-zag varint sequence number */
1046 0x03, /* message-name length */
1047 0x66,
1048 0x6F,
1049 0x6F /* "foo" */,
1050 ];
1051
1052 i_prot.transport.set_readable_bytes(&source_bytes);
1053
1054 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -73_184_125);
1055 let res = assert_success!(i_prot.read_message_begin());
1056
1057 assert_eq!(&expected, &res);
1058 }
1059
1060 #[test]
1061 fn must_write_message_begin_negative_sequence_number_2() {
1062 let (_, mut o_prot) = test_objects();
1063
1064 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1065 "foo",
1066 TMessageType::Call,
1067 -1_073_741_823
1068 )));
1069
1070 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
1071 #[rustfmt::skip]
1072 let expected: [u8; 11] = [
1073 0x82, /* protocol ID */
1074 0x21, /* message type | protocol version */
1075 0x81,
1076 0x80,
1077 0x80,
1078 0x80,
1079 0x0C, /* non-zig-zag varint sequence number */
1080 0x03, /* message-name length */
1081 0x66,
1082 0x6F,
1083 0x6F /* "foo" */,
1084 ];
1085
1086 assert_eq_written_bytes!(o_prot, expected);
1087 }
1088
1089 #[test]
1090 fn must_read_message_begin_negative_sequence_number_2() {
1091 let (mut i_prot, _) = test_objects();
1092
1093 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
1094 let source_bytes: [u8; 11] = [
1095 0x82, /* protocol ID */
1096 0x21, /* message type | protocol version */
1097 0x81,
1098 0x80,
1099 0x80,
1100 0x80,
1101 0x0C, /* non-zig-zag varint sequence number */
1102 0x03, /* message-name length */
1103 0x66,
1104 0x6F,
1105 0x6F /* "foo" */,
1106 ];
1107
1108 i_prot.transport.set_readable_bytes(&source_bytes);
1109
1110 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -1_073_741_823);
1111 let res = assert_success!(i_prot.read_message_begin());
1112
1113 assert_eq!(&expected, &res);
1114 }
1115
1116 #[test]
Nik Claytone7917602020-03-05 11:51:15 +01001117 fn must_round_trip_upto_i64_maxvalue() {
1118 // See https://issues.apache.org/jira/browse/THRIFT-5131
1119 for i in 0..64 {
1120 let (mut i_prot, mut o_prot) = test_objects();
1121 let val: i64 = ((1u64 << i) - 1) as i64;
1122
1123 o_prot
Allen George8a1743d2020-12-05 01:19:27 -05001124 .write_field_begin(&TFieldIdentifier::new("val", TType::I64, 1))
Nik Claytone7917602020-03-05 11:51:15 +01001125 .unwrap();
1126 o_prot.write_i64(val).unwrap();
1127 o_prot.write_field_end().unwrap();
1128 o_prot.flush().unwrap();
1129
1130 copy_write_buffer_to_read_buffer!(o_prot);
1131
1132 i_prot.read_field_begin().unwrap();
1133 assert_eq!(val, i_prot.read_i64().unwrap());
1134 }
1135 }
1136
1137 #[test]
Allen George8b96bfb2016-11-02 08:01:08 -04001138 fn must_round_trip_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -05001139 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001140
Allen George7ddbcc02020-11-08 09:51:19 -05001141 let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948);
Allen George8b96bfb2016-11-02 08:01:08 -04001142
1143 assert_success!(o_prot.write_message_begin(&ident));
1144
Allen George0e22c362017-01-30 07:15:00 -05001145 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001146
1147 let res = assert_success!(i_prot.read_message_begin());
1148 assert_eq!(&res, &ident);
1149 }
1150
1151 #[test]
1152 fn must_write_message_end() {
1153 assert_no_write(|o| o.write_message_end());
1154 }
1155
1156 // NOTE: structs and fields are tested together
1157 //
1158
1159 #[test]
1160 fn must_write_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001161 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001162
1163 // no bytes should be written however
1164 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1165
1166 // write three fields with tiny field ids
1167 // since they're small the field ids will be encoded as deltas
1168
1169 // since this is the first field (and it's zero) it gets the full varint write
1170 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
1171 assert_success!(o_prot.write_field_end());
1172
1173 // since this delta > 0 and < 15 it can be encoded as a delta
1174 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
1175 assert_success!(o_prot.write_field_end());
1176
1177 // since this delta > 0 and < 15 it can be encoded as a delta
1178 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
1179 assert_success!(o_prot.write_field_end());
1180
1181 // now, finish the struct off
1182 assert_success!(o_prot.write_field_stop());
1183 assert_success!(o_prot.write_struct_end());
1184
Allen George7ddbcc02020-11-08 09:51:19 -05001185 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001186 let expected: [u8; 5] = [
1187 0x03, /* field type */
1188 0x00, /* first field id */
1189 0x44, /* field delta (4) | field type */
1190 0x59, /* field delta (5) | field type */
1191 0x00 /* field stop */,
1192 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001193
Allen George0e22c362017-01-30 07:15:00 -05001194 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001195 }
1196
1197 #[test]
1198 fn must_round_trip_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001199 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001200
1201 // no bytes should be written however
1202 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1203
1204 // write three fields with tiny field ids
1205 // since they're small the field ids will be encoded as deltas
1206
1207 // since this is the first field (and it's zero) it gets the full varint write
1208 let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
1209 assert_success!(o_prot.write_field_begin(&field_ident_1));
1210 assert_success!(o_prot.write_field_end());
1211
1212 // since this delta > 0 and < 15 it can be encoded as a delta
1213 let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
1214 assert_success!(o_prot.write_field_begin(&field_ident_2));
1215 assert_success!(o_prot.write_field_end());
1216
1217 // since this delta > 0 and < 15 it can be encoded as a delta
1218 let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
1219 assert_success!(o_prot.write_field_begin(&field_ident_3));
1220 assert_success!(o_prot.write_field_end());
1221
1222 // now, finish the struct off
1223 assert_success!(o_prot.write_field_stop());
1224 assert_success!(o_prot.write_struct_end());
1225
Allen George0e22c362017-01-30 07:15:00 -05001226 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001227
1228 // read the struct back
1229 assert_success!(i_prot.read_struct_begin());
1230
1231 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001232 assert_eq!(
1233 read_ident_1,
1234 TFieldIdentifier {
1235 name: None,
1236 ..field_ident_1
1237 }
1238 );
Allen George8b96bfb2016-11-02 08:01:08 -04001239 assert_success!(i_prot.read_field_end());
1240
1241 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001242 assert_eq!(
1243 read_ident_2,
1244 TFieldIdentifier {
1245 name: None,
1246 ..field_ident_2
1247 }
1248 );
Allen George8b96bfb2016-11-02 08:01:08 -04001249 assert_success!(i_prot.read_field_end());
1250
1251 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001252 assert_eq!(
1253 read_ident_3,
1254 TFieldIdentifier {
1255 name: None,
1256 ..field_ident_3
1257 }
1258 );
Allen George8b96bfb2016-11-02 08:01:08 -04001259 assert_success!(i_prot.read_field_end());
1260
1261 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001262 assert_eq!(
1263 read_ident_4,
1264 TFieldIdentifier {
1265 name: None,
1266 field_type: TType::Stop,
1267 id: None,
1268 }
1269 );
Allen George8b96bfb2016-11-02 08:01:08 -04001270
1271 assert_success!(i_prot.read_struct_end());
1272 }
1273
1274 #[test]
1275 fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001276 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001277
1278 // no bytes should be written however
1279 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1280
1281 // write three fields with tiny field ids
1282 // since they're small the field ids will be encoded as deltas
1283
1284 // gets a delta write
1285 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
1286 assert_success!(o_prot.write_field_end());
1287
1288 // since this delta > 0 and < 15 it can be encoded as a delta
1289 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
1290 assert_success!(o_prot.write_field_end());
1291
1292 // since this delta > 0 and < 15 it can be encoded as a delta
1293 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
1294 assert_success!(o_prot.write_field_end());
1295
1296 // now, finish the struct off
1297 assert_success!(o_prot.write_field_stop());
1298 assert_success!(o_prot.write_struct_end());
1299
Allen George7ddbcc02020-11-08 09:51:19 -05001300 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001301 let expected: [u8; 4] = [
1302 0x15, /* field delta (1) | field type */
1303 0x1A, /* field delta (1) | field type */
1304 0x48, /* field delta (4) | field type */
1305 0x00 /* field stop */,
1306 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001307
Allen George0e22c362017-01-30 07:15:00 -05001308 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001309 }
1310
1311 #[test]
1312 fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001313 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001314
1315 // no bytes should be written however
1316 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1317
1318 // write three fields with tiny field ids
1319 // since they're small the field ids will be encoded as deltas
1320
1321 // gets a delta write
1322 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
1323 assert_success!(o_prot.write_field_begin(&field_ident_1));
1324 assert_success!(o_prot.write_field_end());
1325
1326 // since this delta > 0 and < 15 it can be encoded as a delta
1327 let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
1328 assert_success!(o_prot.write_field_begin(&field_ident_2));
1329 assert_success!(o_prot.write_field_end());
1330
1331 // since this delta > 0 and < 15 it can be encoded as a delta
1332 let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
1333 assert_success!(o_prot.write_field_begin(&field_ident_3));
1334 assert_success!(o_prot.write_field_end());
1335
1336 // now, finish the struct off
1337 assert_success!(o_prot.write_field_stop());
1338 assert_success!(o_prot.write_struct_end());
1339
Allen George0e22c362017-01-30 07:15:00 -05001340 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001341
1342 // read the struct back
1343 assert_success!(i_prot.read_struct_begin());
1344
1345 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001346 assert_eq!(
1347 read_ident_1,
1348 TFieldIdentifier {
1349 name: None,
1350 ..field_ident_1
1351 }
1352 );
Allen George8b96bfb2016-11-02 08:01:08 -04001353 assert_success!(i_prot.read_field_end());
1354
1355 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001356 assert_eq!(
1357 read_ident_2,
1358 TFieldIdentifier {
1359 name: None,
1360 ..field_ident_2
1361 }
1362 );
Allen George8b96bfb2016-11-02 08:01:08 -04001363 assert_success!(i_prot.read_field_end());
1364
1365 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001366 assert_eq!(
1367 read_ident_3,
1368 TFieldIdentifier {
1369 name: None,
1370 ..field_ident_3
1371 }
1372 );
Allen George8b96bfb2016-11-02 08:01:08 -04001373 assert_success!(i_prot.read_field_end());
1374
1375 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001376 assert_eq!(
1377 read_ident_4,
1378 TFieldIdentifier {
1379 name: None,
1380 field_type: TType::Stop,
1381 id: None,
1382 }
1383 );
Allen George8b96bfb2016-11-02 08:01:08 -04001384
1385 assert_success!(i_prot.read_struct_end());
1386 }
1387
1388 #[test]
1389 fn must_write_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001390 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001391
1392 // no bytes should be written however
1393 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1394
1395 // write three fields with field ids that cannot be encoded as deltas
1396
1397 // since this is the first field (and it's zero) it gets the full varint write
1398 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
1399 assert_success!(o_prot.write_field_end());
1400
1401 // since this delta is > 15 it is encoded as a zig-zag varint
1402 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
1403 assert_success!(o_prot.write_field_end());
1404
1405 // since this delta is > 15 it is encoded as a zig-zag varint
1406 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
1407 assert_success!(o_prot.write_field_end());
1408
1409 // now, finish the struct off
1410 assert_success!(o_prot.write_field_stop());
1411 assert_success!(o_prot.write_struct_end());
1412
Allen George7ddbcc02020-11-08 09:51:19 -05001413 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001414 let expected: [u8; 8] = [
1415 0x05, /* field type */
1416 0x00, /* first field id */
1417 0x06, /* field type */
1418 0x20, /* zig-zag varint field id */
1419 0x0A, /* field type */
1420 0xC6,
1421 0x01, /* zig-zag varint field id */
1422 0x00 /* field stop */,
1423 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001424
Allen George0e22c362017-01-30 07:15:00 -05001425 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001426 }
1427
1428 #[test]
1429 fn must_round_trip_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001430 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001431
1432 // no bytes should be written however
1433 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1434
1435 // write three fields with field ids that cannot be encoded as deltas
1436
1437 // since this is the first field (and it's zero) it gets the full varint write
1438 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
1439 assert_success!(o_prot.write_field_begin(&field_ident_1));
1440 assert_success!(o_prot.write_field_end());
1441
1442 // since this delta is > 15 it is encoded as a zig-zag varint
1443 let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
1444 assert_success!(o_prot.write_field_begin(&field_ident_2));
1445 assert_success!(o_prot.write_field_end());
1446
1447 // since this delta is > 15 it is encoded as a zig-zag varint
1448 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
1449 assert_success!(o_prot.write_field_begin(&field_ident_3));
1450 assert_success!(o_prot.write_field_end());
1451
1452 // now, finish the struct off
1453 assert_success!(o_prot.write_field_stop());
1454 assert_success!(o_prot.write_struct_end());
1455
Allen George0e22c362017-01-30 07:15:00 -05001456 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001457
1458 // read the struct back
1459 assert_success!(i_prot.read_struct_begin());
1460
1461 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001462 assert_eq!(
1463 read_ident_1,
1464 TFieldIdentifier {
1465 name: None,
1466 ..field_ident_1
1467 }
1468 );
Allen George8b96bfb2016-11-02 08:01:08 -04001469 assert_success!(i_prot.read_field_end());
1470
1471 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001472 assert_eq!(
1473 read_ident_2,
1474 TFieldIdentifier {
1475 name: None,
1476 ..field_ident_2
1477 }
1478 );
Allen George8b96bfb2016-11-02 08:01:08 -04001479 assert_success!(i_prot.read_field_end());
1480
1481 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001482 assert_eq!(
1483 read_ident_3,
1484 TFieldIdentifier {
1485 name: None,
1486 ..field_ident_3
1487 }
1488 );
Allen George8b96bfb2016-11-02 08:01:08 -04001489 assert_success!(i_prot.read_field_end());
1490
1491 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001492 assert_eq!(
1493 read_ident_4,
1494 TFieldIdentifier {
1495 name: None,
1496 field_type: TType::Stop,
1497 id: None,
1498 }
1499 );
Allen George8b96bfb2016-11-02 08:01:08 -04001500
1501 assert_success!(i_prot.read_struct_end());
1502 }
1503
1504 #[test]
1505 fn must_write_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001506 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001507
1508 // no bytes should be written however
1509 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1510
1511 // write three fields with field ids that cannot be encoded as deltas
1512
1513 // since the delta is > 0 and < 15 it gets a delta write
1514 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1515 assert_success!(o_prot.write_field_end());
1516
1517 // since this delta > 0 and < 15 it gets a delta write
1518 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1519 assert_success!(o_prot.write_field_end());
1520
1521 // since this delta is > 15 it is encoded as a zig-zag varint
1522 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
1523 assert_success!(o_prot.write_field_end());
1524
1525 // since this delta is > 15 it is encoded as a zig-zag varint
1526 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
1527 assert_success!(o_prot.write_field_end());
1528
1529 // since this is only 3 up from the previous it is recorded as a delta
1530 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
1531 assert_success!(o_prot.write_field_end());
1532
1533 // now, finish the struct off
1534 assert_success!(o_prot.write_field_stop());
1535 assert_success!(o_prot.write_struct_end());
1536
Allen George7ddbcc02020-11-08 09:51:19 -05001537 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001538 let expected: [u8; 10] = [
1539 0x16, /* field delta (1) | field type */
1540 0x85, /* field delta (8) | field type */
1541 0x0A, /* field type */
1542 0xD0,
1543 0x0F, /* zig-zag varint field id */
1544 0x0A, /* field type */
1545 0xA2,
1546 0x1F, /* zig-zag varint field id */
1547 0x3A, /* field delta (3) | field type */
1548 0x00 /* field stop */,
1549 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001550
Allen George0e22c362017-01-30 07:15:00 -05001551 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001552 }
1553
Allen George7ddbcc02020-11-08 09:51:19 -05001554 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001555 #[test]
1556 fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001557 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001558
1559 // no bytes should be written however
1560 let struct_ident = TStructIdentifier::new("foo");
1561 assert_success!(o_prot.write_struct_begin(&struct_ident));
1562
1563 // write three fields with field ids that cannot be encoded as deltas
1564
1565 // since the delta is > 0 and < 15 it gets a delta write
1566 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1567 assert_success!(o_prot.write_field_begin(&field_ident_1));
1568 assert_success!(o_prot.write_field_end());
1569
1570 // since this delta > 0 and < 15 it gets a delta write
1571 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1572 assert_success!(o_prot.write_field_begin(&field_ident_2));
1573 assert_success!(o_prot.write_field_end());
1574
1575 // since this delta is > 15 it is encoded as a zig-zag varint
1576 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
1577 assert_success!(o_prot.write_field_begin(&field_ident_3));
1578 assert_success!(o_prot.write_field_end());
1579
1580 // since this delta is > 15 it is encoded as a zig-zag varint
1581 let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
1582 assert_success!(o_prot.write_field_begin(&field_ident_4));
1583 assert_success!(o_prot.write_field_end());
1584
1585 // since this is only 3 up from the previous it is recorded as a delta
1586 let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
1587 assert_success!(o_prot.write_field_begin(&field_ident_5));
1588 assert_success!(o_prot.write_field_end());
1589
1590 // now, finish the struct off
1591 assert_success!(o_prot.write_field_stop());
1592 assert_success!(o_prot.write_struct_end());
1593
Allen George0e22c362017-01-30 07:15:00 -05001594 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001595
1596 // read the struct back
1597 assert_success!(i_prot.read_struct_begin());
1598
1599 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001600 assert_eq!(
1601 read_ident_1,
1602 TFieldIdentifier {
1603 name: None,
1604 ..field_ident_1
1605 }
1606 );
Allen George8b96bfb2016-11-02 08:01:08 -04001607 assert_success!(i_prot.read_field_end());
1608
1609 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001610 assert_eq!(
1611 read_ident_2,
1612 TFieldIdentifier {
1613 name: None,
1614 ..field_ident_2
1615 }
1616 );
Allen George8b96bfb2016-11-02 08:01:08 -04001617 assert_success!(i_prot.read_field_end());
1618
1619 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001620 assert_eq!(
1621 read_ident_3,
1622 TFieldIdentifier {
1623 name: None,
1624 ..field_ident_3
1625 }
1626 );
Allen George8b96bfb2016-11-02 08:01:08 -04001627 assert_success!(i_prot.read_field_end());
1628
1629 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001630 assert_eq!(
1631 read_ident_4,
1632 TFieldIdentifier {
1633 name: None,
1634 ..field_ident_4
1635 }
1636 );
Allen George8b96bfb2016-11-02 08:01:08 -04001637 assert_success!(i_prot.read_field_end());
1638
1639 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001640 assert_eq!(
1641 read_ident_5,
1642 TFieldIdentifier {
1643 name: None,
1644 ..field_ident_5
1645 }
1646 );
Allen George8b96bfb2016-11-02 08:01:08 -04001647 assert_success!(i_prot.read_field_end());
1648
1649 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001650 assert_eq!(
1651 read_ident_6,
1652 TFieldIdentifier {
1653 name: None,
1654 field_type: TType::Stop,
1655 id: None,
1656 }
1657 );
Allen George8b96bfb2016-11-02 08:01:08 -04001658
1659 assert_success!(i_prot.read_struct_end());
1660 }
1661
1662 #[test]
1663 fn must_write_nested_structs_0() {
1664 // last field of the containing struct is a delta
1665 // first field of the the contained struct is a delta
1666
Allen George0e22c362017-01-30 07:15:00 -05001667 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001668
1669 // start containing struct
1670 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1671
1672 // containing struct
1673 // since the delta is > 0 and < 15 it gets a delta write
1674 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1675 assert_success!(o_prot.write_field_end());
1676
1677 // containing struct
1678 // since this delta > 0 and < 15 it gets a delta write
1679 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1680 assert_success!(o_prot.write_field_end());
1681
1682 // start contained struct
1683 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1684
1685 // contained struct
1686 // since the delta is > 0 and < 15 it gets a delta write
1687 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
1688 assert_success!(o_prot.write_field_end());
1689
1690 // contained struct
1691 // since this delta > 15 it gets a full write
1692 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1693 assert_success!(o_prot.write_field_end());
1694
1695 // end contained struct
1696 assert_success!(o_prot.write_field_stop());
1697 assert_success!(o_prot.write_struct_end());
1698
1699 // end containing struct
1700 assert_success!(o_prot.write_field_stop());
1701 assert_success!(o_prot.write_struct_end());
1702
Allen George7ddbcc02020-11-08 09:51:19 -05001703 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001704 let expected: [u8; 7] = [
1705 0x16, /* field delta (1) | field type */
1706 0x85, /* field delta (8) | field type */
1707 0x73, /* field delta (7) | field type */
1708 0x07, /* field type */
1709 0x30, /* zig-zag varint field id */
1710 0x00, /* field stop - contained */
1711 0x00 /* field stop - containing */,
1712 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001713
Allen George0e22c362017-01-30 07:15:00 -05001714 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001715 }
1716
Allen George7ddbcc02020-11-08 09:51:19 -05001717 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001718 #[test]
1719 fn must_round_trip_nested_structs_0() {
1720 // last field of the containing struct is a delta
1721 // first field of the the contained struct is a delta
1722
Allen George0e22c362017-01-30 07:15:00 -05001723 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001724
1725 // start containing struct
1726 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1727
1728 // containing struct
1729 // since the delta is > 0 and < 15 it gets a delta write
1730 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1731 assert_success!(o_prot.write_field_begin(&field_ident_1));
1732 assert_success!(o_prot.write_field_end());
1733
1734 // containing struct
1735 // since this delta > 0 and < 15 it gets a delta write
1736 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1737 assert_success!(o_prot.write_field_begin(&field_ident_2));
1738 assert_success!(o_prot.write_field_end());
1739
1740 // start contained struct
1741 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1742
1743 // contained struct
1744 // since the delta is > 0 and < 15 it gets a delta write
1745 let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
1746 assert_success!(o_prot.write_field_begin(&field_ident_3));
1747 assert_success!(o_prot.write_field_end());
1748
1749 // contained struct
1750 // since this delta > 15 it gets a full write
1751 let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
1752 assert_success!(o_prot.write_field_begin(&field_ident_4));
1753 assert_success!(o_prot.write_field_end());
1754
1755 // end contained struct
1756 assert_success!(o_prot.write_field_stop());
1757 assert_success!(o_prot.write_struct_end());
1758
1759 // end containing struct
1760 assert_success!(o_prot.write_field_stop());
1761 assert_success!(o_prot.write_struct_end());
1762
Allen George0e22c362017-01-30 07:15:00 -05001763 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001764
1765 // read containing struct back
1766 assert_success!(i_prot.read_struct_begin());
1767
1768 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001769 assert_eq!(
1770 read_ident_1,
1771 TFieldIdentifier {
1772 name: None,
1773 ..field_ident_1
1774 }
1775 );
Allen George8b96bfb2016-11-02 08:01:08 -04001776 assert_success!(i_prot.read_field_end());
1777
1778 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001779 assert_eq!(
1780 read_ident_2,
1781 TFieldIdentifier {
1782 name: None,
1783 ..field_ident_2
1784 }
1785 );
Allen George8b96bfb2016-11-02 08:01:08 -04001786 assert_success!(i_prot.read_field_end());
1787
1788 // read contained struct back
1789 assert_success!(i_prot.read_struct_begin());
1790
1791 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001792 assert_eq!(
1793 read_ident_3,
1794 TFieldIdentifier {
1795 name: None,
1796 ..field_ident_3
1797 }
1798 );
Allen George8b96bfb2016-11-02 08:01:08 -04001799 assert_success!(i_prot.read_field_end());
1800
1801 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001802 assert_eq!(
1803 read_ident_4,
1804 TFieldIdentifier {
1805 name: None,
1806 ..field_ident_4
1807 }
1808 );
Allen George8b96bfb2016-11-02 08:01:08 -04001809 assert_success!(i_prot.read_field_end());
1810
1811 // end contained struct
1812 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001813 assert_eq!(
1814 read_ident_6,
1815 TFieldIdentifier {
1816 name: None,
1817 field_type: TType::Stop,
1818 id: None,
1819 }
1820 );
Allen George8b96bfb2016-11-02 08:01:08 -04001821 assert_success!(i_prot.read_struct_end());
1822
1823 // end containing struct
1824 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001825 assert_eq!(
1826 read_ident_7,
1827 TFieldIdentifier {
1828 name: None,
1829 field_type: TType::Stop,
1830 id: None,
1831 }
1832 );
Allen George8b96bfb2016-11-02 08:01:08 -04001833 assert_success!(i_prot.read_struct_end());
1834 }
1835
1836 #[test]
1837 fn must_write_nested_structs_1() {
1838 // last field of the containing struct is a delta
1839 // first field of the the contained struct is a full write
1840
Allen George0e22c362017-01-30 07:15:00 -05001841 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001842
1843 // start containing struct
1844 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1845
1846 // containing struct
1847 // since the delta is > 0 and < 15 it gets a delta write
1848 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1849 assert_success!(o_prot.write_field_end());
1850
1851 // containing struct
1852 // since this delta > 0 and < 15 it gets a delta write
1853 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1854 assert_success!(o_prot.write_field_end());
1855
1856 // start contained struct
1857 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1858
1859 // contained struct
1860 // since this delta > 15 it gets a full write
1861 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1862 assert_success!(o_prot.write_field_end());
1863
1864 // contained struct
1865 // since the delta is > 0 and < 15 it gets a delta write
1866 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1867 assert_success!(o_prot.write_field_end());
1868
1869 // end contained struct
1870 assert_success!(o_prot.write_field_stop());
1871 assert_success!(o_prot.write_struct_end());
1872
1873 // end containing struct
1874 assert_success!(o_prot.write_field_stop());
1875 assert_success!(o_prot.write_struct_end());
1876
Allen George7ddbcc02020-11-08 09:51:19 -05001877 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001878 let expected: [u8; 7] = [
1879 0x16, /* field delta (1) | field type */
1880 0x85, /* field delta (8) | field type */
1881 0x07, /* field type */
1882 0x30, /* zig-zag varint field id */
1883 0x33, /* field delta (3) | field type */
1884 0x00, /* field stop - contained */
1885 0x00 /* field stop - containing */,
1886 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001887
Allen George0e22c362017-01-30 07:15:00 -05001888 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001889 }
1890
Allen George7ddbcc02020-11-08 09:51:19 -05001891 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001892 #[test]
1893 fn must_round_trip_nested_structs_1() {
1894 // last field of the containing struct is a delta
1895 // first field of the the contained struct is a full write
1896
Allen George0e22c362017-01-30 07:15:00 -05001897 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001898
1899 // start containing struct
1900 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1901
1902 // containing struct
1903 // since the delta is > 0 and < 15 it gets a delta write
1904 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1905 assert_success!(o_prot.write_field_begin(&field_ident_1));
1906 assert_success!(o_prot.write_field_end());
1907
1908 // containing struct
1909 // since this delta > 0 and < 15 it gets a delta write
1910 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1911 assert_success!(o_prot.write_field_begin(&field_ident_2));
1912 assert_success!(o_prot.write_field_end());
1913
1914 // start contained struct
1915 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1916
1917 // contained struct
1918 // since this delta > 15 it gets a full write
1919 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
1920 assert_success!(o_prot.write_field_begin(&field_ident_3));
1921 assert_success!(o_prot.write_field_end());
1922
1923 // contained struct
1924 // since the delta is > 0 and < 15 it gets a delta write
1925 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
1926 assert_success!(o_prot.write_field_begin(&field_ident_4));
1927 assert_success!(o_prot.write_field_end());
1928
1929 // end contained struct
1930 assert_success!(o_prot.write_field_stop());
1931 assert_success!(o_prot.write_struct_end());
1932
1933 // end containing struct
1934 assert_success!(o_prot.write_field_stop());
1935 assert_success!(o_prot.write_struct_end());
1936
Allen George0e22c362017-01-30 07:15:00 -05001937 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001938
1939 // read containing struct back
1940 assert_success!(i_prot.read_struct_begin());
1941
1942 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001943 assert_eq!(
1944 read_ident_1,
1945 TFieldIdentifier {
1946 name: None,
1947 ..field_ident_1
1948 }
1949 );
Allen George8b96bfb2016-11-02 08:01:08 -04001950 assert_success!(i_prot.read_field_end());
1951
1952 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001953 assert_eq!(
1954 read_ident_2,
1955 TFieldIdentifier {
1956 name: None,
1957 ..field_ident_2
1958 }
1959 );
Allen George8b96bfb2016-11-02 08:01:08 -04001960 assert_success!(i_prot.read_field_end());
1961
1962 // read contained struct back
1963 assert_success!(i_prot.read_struct_begin());
1964
1965 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001966 assert_eq!(
1967 read_ident_3,
1968 TFieldIdentifier {
1969 name: None,
1970 ..field_ident_3
1971 }
1972 );
Allen George8b96bfb2016-11-02 08:01:08 -04001973 assert_success!(i_prot.read_field_end());
1974
1975 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001976 assert_eq!(
1977 read_ident_4,
1978 TFieldIdentifier {
1979 name: None,
1980 ..field_ident_4
1981 }
1982 );
Allen George8b96bfb2016-11-02 08:01:08 -04001983 assert_success!(i_prot.read_field_end());
1984
1985 // end contained struct
1986 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001987 assert_eq!(
1988 read_ident_6,
1989 TFieldIdentifier {
1990 name: None,
1991 field_type: TType::Stop,
1992 id: None,
1993 }
1994 );
Allen George8b96bfb2016-11-02 08:01:08 -04001995 assert_success!(i_prot.read_struct_end());
1996
1997 // end containing struct
1998 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001999 assert_eq!(
2000 read_ident_7,
2001 TFieldIdentifier {
2002 name: None,
2003 field_type: TType::Stop,
2004 id: None,
2005 }
2006 );
Allen George8b96bfb2016-11-02 08:01:08 -04002007 assert_success!(i_prot.read_struct_end());
2008 }
2009
2010 #[test]
2011 fn must_write_nested_structs_2() {
2012 // last field of the containing struct is a full write
2013 // first field of the the contained struct is a delta write
2014
Allen George0e22c362017-01-30 07:15:00 -05002015 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002016
2017 // start containing struct
2018 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2019
2020 // containing struct
2021 // since the delta is > 0 and < 15 it gets a delta write
2022 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2023 assert_success!(o_prot.write_field_end());
2024
2025 // containing struct
2026 // since this delta > 15 it gets a full write
2027 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2028 assert_success!(o_prot.write_field_end());
2029
2030 // start contained struct
2031 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2032
2033 // contained struct
2034 // since this delta > 0 and < 15 it gets a delta write
2035 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
2036 assert_success!(o_prot.write_field_end());
2037
2038 // contained struct
2039 // since the delta is > 0 and < 15 it gets a delta write
2040 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
2041 assert_success!(o_prot.write_field_end());
2042
2043 // end contained struct
2044 assert_success!(o_prot.write_field_stop());
2045 assert_success!(o_prot.write_struct_end());
2046
2047 // end containing struct
2048 assert_success!(o_prot.write_field_stop());
2049 assert_success!(o_prot.write_struct_end());
2050
Allen George7ddbcc02020-11-08 09:51:19 -05002051 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002052 let expected: [u8; 7] = [
2053 0x16, /* field delta (1) | field type */
2054 0x08, /* field type */
2055 0x2A, /* zig-zag varint field id */
2056 0x77, /* field delta(7) | field type */
2057 0x33, /* field delta (3) | field type */
2058 0x00, /* field stop - contained */
2059 0x00 /* field stop - containing */,
2060 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002061
Allen George0e22c362017-01-30 07:15:00 -05002062 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002063 }
2064
Allen George7ddbcc02020-11-08 09:51:19 -05002065 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002066 #[test]
2067 fn must_round_trip_nested_structs_2() {
Allen George0e22c362017-01-30 07:15:00 -05002068 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002069
2070 // start containing struct
2071 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2072
2073 // containing struct
2074 // since the delta is > 0 and < 15 it gets a delta write
2075 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2076 assert_success!(o_prot.write_field_begin(&field_ident_1));
2077 assert_success!(o_prot.write_field_end());
2078
2079 // containing struct
2080 // since this delta > 15 it gets a full write
2081 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2082 assert_success!(o_prot.write_field_begin(&field_ident_2));
2083 assert_success!(o_prot.write_field_end());
2084
2085 // start contained struct
2086 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2087
2088 // contained struct
2089 // since this delta > 0 and < 15 it gets a delta write
2090 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
2091 assert_success!(o_prot.write_field_begin(&field_ident_3));
2092 assert_success!(o_prot.write_field_end());
2093
2094 // contained struct
2095 // since the delta is > 0 and < 15 it gets a delta write
2096 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
2097 assert_success!(o_prot.write_field_begin(&field_ident_4));
2098 assert_success!(o_prot.write_field_end());
2099
2100 // end contained struct
2101 assert_success!(o_prot.write_field_stop());
2102 assert_success!(o_prot.write_struct_end());
2103
2104 // end containing struct
2105 assert_success!(o_prot.write_field_stop());
2106 assert_success!(o_prot.write_struct_end());
2107
Allen George0e22c362017-01-30 07:15:00 -05002108 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002109
2110 // read containing struct back
2111 assert_success!(i_prot.read_struct_begin());
2112
2113 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002114 assert_eq!(
2115 read_ident_1,
2116 TFieldIdentifier {
2117 name: None,
2118 ..field_ident_1
2119 }
2120 );
Allen George8b96bfb2016-11-02 08:01:08 -04002121 assert_success!(i_prot.read_field_end());
2122
2123 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002124 assert_eq!(
2125 read_ident_2,
2126 TFieldIdentifier {
2127 name: None,
2128 ..field_ident_2
2129 }
2130 );
Allen George8b96bfb2016-11-02 08:01:08 -04002131 assert_success!(i_prot.read_field_end());
2132
2133 // read contained struct back
2134 assert_success!(i_prot.read_struct_begin());
2135
2136 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002137 assert_eq!(
2138 read_ident_3,
2139 TFieldIdentifier {
2140 name: None,
2141 ..field_ident_3
2142 }
2143 );
Allen George8b96bfb2016-11-02 08:01:08 -04002144 assert_success!(i_prot.read_field_end());
2145
2146 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002147 assert_eq!(
2148 read_ident_4,
2149 TFieldIdentifier {
2150 name: None,
2151 ..field_ident_4
2152 }
2153 );
Allen George8b96bfb2016-11-02 08:01:08 -04002154 assert_success!(i_prot.read_field_end());
2155
2156 // end contained struct
2157 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002158 assert_eq!(
2159 read_ident_6,
2160 TFieldIdentifier {
2161 name: None,
2162 field_type: TType::Stop,
2163 id: None,
2164 }
2165 );
Allen George8b96bfb2016-11-02 08:01:08 -04002166 assert_success!(i_prot.read_struct_end());
2167
2168 // end containing struct
2169 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002170 assert_eq!(
2171 read_ident_7,
2172 TFieldIdentifier {
2173 name: None,
2174 field_type: TType::Stop,
2175 id: None,
2176 }
2177 );
Allen George8b96bfb2016-11-02 08:01:08 -04002178 assert_success!(i_prot.read_struct_end());
2179 }
2180
2181 #[test]
2182 fn must_write_nested_structs_3() {
2183 // last field of the containing struct is a full write
2184 // first field of the the contained struct is a full write
2185
Allen George0e22c362017-01-30 07:15:00 -05002186 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002187
2188 // start containing struct
2189 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2190
2191 // containing struct
2192 // since the delta is > 0 and < 15 it gets a delta write
2193 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2194 assert_success!(o_prot.write_field_end());
2195
2196 // containing struct
2197 // since this delta > 15 it gets a full write
2198 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2199 assert_success!(o_prot.write_field_end());
2200
2201 // start contained struct
2202 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2203
2204 // contained struct
2205 // since this delta > 15 it gets a full write
2206 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
2207 assert_success!(o_prot.write_field_end());
2208
2209 // contained struct
2210 // since the delta is > 0 and < 15 it gets a delta write
2211 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
2212 assert_success!(o_prot.write_field_end());
2213
2214 // end contained struct
2215 assert_success!(o_prot.write_field_stop());
2216 assert_success!(o_prot.write_struct_end());
2217
2218 // end containing struct
2219 assert_success!(o_prot.write_field_stop());
2220 assert_success!(o_prot.write_struct_end());
2221
Allen George7ddbcc02020-11-08 09:51:19 -05002222 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002223 let expected: [u8; 8] = [
2224 0x16, /* field delta (1) | field type */
2225 0x08, /* field type */
2226 0x2A, /* zig-zag varint field id */
2227 0x07, /* field type */
2228 0x2A, /* zig-zag varint field id */
2229 0x63, /* field delta (6) | field type */
2230 0x00, /* field stop - contained */
2231 0x00 /* field stop - containing */,
2232 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002233
Allen George0e22c362017-01-30 07:15:00 -05002234 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002235 }
2236
Allen George7ddbcc02020-11-08 09:51:19 -05002237 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002238 #[test]
2239 fn must_round_trip_nested_structs_3() {
2240 // last field of the containing struct is a full write
2241 // first field of the the contained struct is a full write
2242
Allen George0e22c362017-01-30 07:15:00 -05002243 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002244
2245 // start containing struct
2246 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2247
2248 // containing struct
2249 // since the delta is > 0 and < 15 it gets a delta write
2250 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2251 assert_success!(o_prot.write_field_begin(&field_ident_1));
2252 assert_success!(o_prot.write_field_end());
2253
2254 // containing struct
2255 // since this delta > 15 it gets a full write
2256 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2257 assert_success!(o_prot.write_field_begin(&field_ident_2));
2258 assert_success!(o_prot.write_field_end());
2259
2260 // start contained struct
2261 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2262
2263 // contained struct
2264 // since this delta > 15 it gets a full write
2265 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
2266 assert_success!(o_prot.write_field_begin(&field_ident_3));
2267 assert_success!(o_prot.write_field_end());
2268
2269 // contained struct
2270 // since the delta is > 0 and < 15 it gets a delta write
2271 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2272 assert_success!(o_prot.write_field_begin(&field_ident_4));
2273 assert_success!(o_prot.write_field_end());
2274
2275 // end contained struct
2276 assert_success!(o_prot.write_field_stop());
2277 assert_success!(o_prot.write_struct_end());
2278
2279 // end containing struct
2280 assert_success!(o_prot.write_field_stop());
2281 assert_success!(o_prot.write_struct_end());
2282
Allen George0e22c362017-01-30 07:15:00 -05002283 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002284
2285 // read containing struct back
2286 assert_success!(i_prot.read_struct_begin());
2287
2288 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002289 assert_eq!(
2290 read_ident_1,
2291 TFieldIdentifier {
2292 name: None,
2293 ..field_ident_1
2294 }
2295 );
Allen George8b96bfb2016-11-02 08:01:08 -04002296 assert_success!(i_prot.read_field_end());
2297
2298 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002299 assert_eq!(
2300 read_ident_2,
2301 TFieldIdentifier {
2302 name: None,
2303 ..field_ident_2
2304 }
2305 );
Allen George8b96bfb2016-11-02 08:01:08 -04002306 assert_success!(i_prot.read_field_end());
2307
2308 // read contained struct back
2309 assert_success!(i_prot.read_struct_begin());
2310
2311 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002312 assert_eq!(
2313 read_ident_3,
2314 TFieldIdentifier {
2315 name: None,
2316 ..field_ident_3
2317 }
2318 );
Allen George8b96bfb2016-11-02 08:01:08 -04002319 assert_success!(i_prot.read_field_end());
2320
2321 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002322 assert_eq!(
2323 read_ident_4,
2324 TFieldIdentifier {
2325 name: None,
2326 ..field_ident_4
2327 }
2328 );
Allen George8b96bfb2016-11-02 08:01:08 -04002329 assert_success!(i_prot.read_field_end());
2330
2331 // end contained struct
2332 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002333 assert_eq!(
2334 read_ident_6,
2335 TFieldIdentifier {
2336 name: None,
2337 field_type: TType::Stop,
2338 id: None,
2339 }
2340 );
Allen George8b96bfb2016-11-02 08:01:08 -04002341 assert_success!(i_prot.read_struct_end());
2342
2343 // end containing struct
2344 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002345 assert_eq!(
2346 read_ident_7,
2347 TFieldIdentifier {
2348 name: None,
2349 field_type: TType::Stop,
2350 id: None,
2351 }
2352 );
Allen George8b96bfb2016-11-02 08:01:08 -04002353 assert_success!(i_prot.read_struct_end());
2354 }
2355
2356 #[test]
2357 fn must_write_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002358 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002359
2360 // no bytes should be written however
2361 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2362
2363 // write three fields with field ids that cannot be encoded as deltas
2364
2365 // since the delta is > 0 and < 16 it gets a delta write
2366 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2367 assert_success!(o_prot.write_bool(true));
2368 assert_success!(o_prot.write_field_end());
2369
2370 // since this delta > 0 and < 15 it gets a delta write
2371 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
2372 assert_success!(o_prot.write_bool(false));
2373 assert_success!(o_prot.write_field_end());
2374
2375 // since this delta > 15 it gets a full write
2376 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
2377 assert_success!(o_prot.write_bool(true));
2378 assert_success!(o_prot.write_field_end());
2379
2380 // since this delta > 15 it gets a full write
2381 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
2382 assert_success!(o_prot.write_bool(false));
2383 assert_success!(o_prot.write_field_end());
2384
2385 // now, finish the struct off
2386 assert_success!(o_prot.write_field_stop());
2387 assert_success!(o_prot.write_struct_end());
2388
Allen George7ddbcc02020-11-08 09:51:19 -05002389 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002390 let expected: [u8; 7] = [
2391 0x11, /* field delta (1) | true */
2392 0x82, /* field delta (8) | false */
2393 0x01, /* true */
2394 0x34, /* field id */
2395 0x02, /* false */
2396 0x5A, /* field id */
2397 0x00 /* stop field */,
2398 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002399
Allen George0e22c362017-01-30 07:15:00 -05002400 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002401 }
2402
Allen George7ddbcc02020-11-08 09:51:19 -05002403 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002404 #[test]
2405 fn must_round_trip_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002406 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002407
2408 // no bytes should be written however
2409 let struct_ident = TStructIdentifier::new("foo");
2410 assert_success!(o_prot.write_struct_begin(&struct_ident));
2411
2412 // write two fields
2413
2414 // since the delta is > 0 and < 16 it gets a delta write
2415 let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
2416 assert_success!(o_prot.write_field_begin(&field_ident_1));
2417 assert_success!(o_prot.write_bool(true));
2418 assert_success!(o_prot.write_field_end());
2419
2420 // since this delta > 0 and < 15 it gets a delta write
2421 let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
2422 assert_success!(o_prot.write_field_begin(&field_ident_2));
2423 assert_success!(o_prot.write_bool(false));
2424 assert_success!(o_prot.write_field_end());
2425
2426 // since this delta > 15 it gets a full write
2427 let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
2428 assert_success!(o_prot.write_field_begin(&field_ident_3));
2429 assert_success!(o_prot.write_bool(true));
2430 assert_success!(o_prot.write_field_end());
2431
2432 // since this delta > 15 it gets a full write
2433 let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
2434 assert_success!(o_prot.write_field_begin(&field_ident_4));
2435 assert_success!(o_prot.write_bool(false));
2436 assert_success!(o_prot.write_field_end());
2437
2438 // now, finish the struct off
2439 assert_success!(o_prot.write_field_stop());
2440 assert_success!(o_prot.write_struct_end());
2441
Allen George0e22c362017-01-30 07:15:00 -05002442 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002443
2444 // read the struct back
2445 assert_success!(i_prot.read_struct_begin());
2446
2447 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002448 assert_eq!(
2449 read_ident_1,
2450 TFieldIdentifier {
2451 name: None,
2452 ..field_ident_1
2453 }
2454 );
Allen George8b96bfb2016-11-02 08:01:08 -04002455 let read_value_1 = assert_success!(i_prot.read_bool());
2456 assert_eq!(read_value_1, true);
2457 assert_success!(i_prot.read_field_end());
2458
2459 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002460 assert_eq!(
2461 read_ident_2,
2462 TFieldIdentifier {
2463 name: None,
2464 ..field_ident_2
2465 }
2466 );
Allen George8b96bfb2016-11-02 08:01:08 -04002467 let read_value_2 = assert_success!(i_prot.read_bool());
2468 assert_eq!(read_value_2, false);
2469 assert_success!(i_prot.read_field_end());
2470
2471 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002472 assert_eq!(
2473 read_ident_3,
2474 TFieldIdentifier {
2475 name: None,
2476 ..field_ident_3
2477 }
2478 );
Allen George8b96bfb2016-11-02 08:01:08 -04002479 let read_value_3 = assert_success!(i_prot.read_bool());
2480 assert_eq!(read_value_3, true);
2481 assert_success!(i_prot.read_field_end());
2482
2483 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002484 assert_eq!(
2485 read_ident_4,
2486 TFieldIdentifier {
2487 name: None,
2488 ..field_ident_4
2489 }
2490 );
Allen George8b96bfb2016-11-02 08:01:08 -04002491 let read_value_4 = assert_success!(i_prot.read_bool());
2492 assert_eq!(read_value_4, false);
2493 assert_success!(i_prot.read_field_end());
2494
2495 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002496 assert_eq!(
2497 read_ident_5,
2498 TFieldIdentifier {
2499 name: None,
2500 field_type: TType::Stop,
2501 id: None,
2502 }
2503 );
Allen George8b96bfb2016-11-02 08:01:08 -04002504
2505 assert_success!(i_prot.read_struct_end());
2506 }
2507
2508 #[test]
2509 #[should_panic]
2510 fn must_fail_if_write_field_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002511 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002512 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2513 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2514 o_prot.write_field_end().unwrap();
2515 }
2516
2517 #[test]
2518 #[should_panic]
2519 fn must_fail_if_write_stop_field_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002520 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002521 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2522 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2523 o_prot.write_field_stop().unwrap();
2524 }
2525
2526 #[test]
2527 #[should_panic]
2528 fn must_fail_if_write_struct_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002529 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002530 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2531 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2532 o_prot.write_struct_end().unwrap();
2533 }
2534
2535 #[test]
2536 #[should_panic]
2537 fn must_fail_if_write_struct_end_without_any_fields() {
Allen George0e22c362017-01-30 07:15:00 -05002538 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002539 o_prot.write_struct_end().unwrap();
2540 }
2541
2542 #[test]
2543 fn must_write_field_end() {
2544 assert_no_write(|o| o.write_field_end());
2545 }
2546
2547 #[test]
2548 fn must_write_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002549 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002550
2551 assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
2552
2553 let expected: [u8; 1] = [0x46 /* size | elem_type */];
2554
Allen George0e22c362017-01-30 07:15:00 -05002555 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002556 }
2557
2558 #[test]
2559 fn must_round_trip_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002560 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002561
2562 let ident = TListIdentifier::new(TType::I08, 10);
2563
2564 assert_success!(o_prot.write_list_begin(&ident));
2565
Allen George0e22c362017-01-30 07:15:00 -05002566 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002567
2568 let res = assert_success!(i_prot.read_list_begin());
2569 assert_eq!(&res, &ident);
2570 }
2571
2572 #[test]
2573 fn must_write_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002574 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002575
2576 let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
2577 assert!(res.is_ok());
2578
Allen George0e22c362017-01-30 07:15:00 -05002579 let expected: [u8; 3] = [
2580 0xF9, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002581 0x8F, 0x4E, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002582 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002583
Allen George0e22c362017-01-30 07:15:00 -05002584 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002585 }
2586
2587 #[test]
2588 fn must_round_trip_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002589 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002590
2591 let ident = TListIdentifier::new(TType::Set, 47381);
2592
2593 assert_success!(o_prot.write_list_begin(&ident));
2594
Allen George0e22c362017-01-30 07:15:00 -05002595 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002596
2597 let res = assert_success!(i_prot.read_list_begin());
2598 assert_eq!(&res, &ident);
2599 }
2600
2601 #[test]
2602 fn must_write_list_end() {
2603 assert_no_write(|o| o.write_list_end());
2604 }
2605
2606 #[test]
2607 fn must_write_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002608 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002609
2610 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
2611
2612 let expected: [u8; 1] = [0x2C /* size | elem_type */];
2613
Allen George0e22c362017-01-30 07:15:00 -05002614 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002615 }
2616
2617 #[test]
2618 fn must_round_trip_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002619 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002620
2621 let ident = TSetIdentifier::new(TType::I16, 7);
2622
2623 assert_success!(o_prot.write_set_begin(&ident));
2624
Allen George0e22c362017-01-30 07:15:00 -05002625 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002626
2627 let res = assert_success!(i_prot.read_set_begin());
2628 assert_eq!(&res, &ident);
2629 }
2630
2631 #[test]
2632 fn must_write_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002633 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002634
2635 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
2636
Allen George0e22c362017-01-30 07:15:00 -05002637 let expected: [u8; 4] = [
2638 0xF7, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002639 0xD3, 0xBA, 0x01, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002640 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002641
Allen George0e22c362017-01-30 07:15:00 -05002642 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002643 }
2644
2645 #[test]
2646 fn must_round_trip_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002647 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002648
Allen George7ddbcc02020-11-08 09:51:19 -05002649 let ident = TSetIdentifier::new(TType::Map, 3_928_429);
Allen George8b96bfb2016-11-02 08:01:08 -04002650
2651 assert_success!(o_prot.write_set_begin(&ident));
2652
Allen George0e22c362017-01-30 07:15:00 -05002653 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002654
2655 let res = assert_success!(i_prot.read_set_begin());
2656 assert_eq!(&res, &ident);
2657 }
2658
2659 #[test]
2660 fn must_write_set_end() {
2661 assert_no_write(|o| o.write_set_end());
2662 }
2663
2664 #[test]
2665 fn must_write_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002666 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002667
2668 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
2669
2670 let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything
2671
Allen George0e22c362017-01-30 07:15:00 -05002672 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002673 }
2674
2675 #[test]
2676 fn must_read_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002677 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002678
2679 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
2680
Allen George0e22c362017-01-30 07:15:00 -05002681 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002682
2683 let res = assert_success!(i_prot.read_map_begin());
Allen George0e22c362017-01-30 07:15:00 -05002684 assert_eq!(
2685 &res,
2686 &TMapIdentifier {
Allen Georgeef7a1892018-12-16 18:01:37 -05002687 key_type: None,
2688 value_type: None,
2689 size: 0,
2690 }
Allen George0e22c362017-01-30 07:15:00 -05002691 );
Allen George8b96bfb2016-11-02 08:01:08 -04002692 }
2693
2694 #[test]
2695 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002696 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002697
Allen Georgeef7a1892018-12-16 18:01:37 -05002698 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
2699 TType::Double,
2700 TType::String,
2701 238
2702 )));
Allen George8b96bfb2016-11-02 08:01:08 -04002703
Allen George0e22c362017-01-30 07:15:00 -05002704 let expected: [u8; 3] = [
Allen Georgeef7a1892018-12-16 18:01:37 -05002705 0xEE, 0x01, /* size as varint */
2706 0x78, /* key type | val type */
Allen George0e22c362017-01-30 07:15:00 -05002707 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002708
Allen George0e22c362017-01-30 07:15:00 -05002709 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002710 }
2711
2712 #[test]
2713 fn must_round_trip_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002714 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002715
Allen George7ddbcc02020-11-08 09:51:19 -05002716 let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349);
Allen George8b96bfb2016-11-02 08:01:08 -04002717
2718 assert_success!(o_prot.write_map_begin(&ident));
2719
Allen George0e22c362017-01-30 07:15:00 -05002720 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002721
2722 let res = assert_success!(i_prot.read_map_begin());
2723 assert_eq!(&res, &ident);
2724 }
2725
2726 #[test]
2727 fn must_write_map_end() {
2728 assert_no_write(|o| o.write_map_end());
2729 }
2730
2731 #[test]
2732 fn must_write_map_with_bool_key_and_value() {
Allen George0e22c362017-01-30 07:15:00 -05002733 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002734
2735 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
2736 assert_success!(o_prot.write_bool(true));
2737 assert_success!(o_prot.write_bool(false));
2738 assert_success!(o_prot.write_map_end());
2739
Allen George0e22c362017-01-30 07:15:00 -05002740 let expected: [u8; 4] = [
2741 0x01, /* size as varint */
2742 0x11, /* key type | val type */
2743 0x01, /* key: true */
Allen Georgeef7a1892018-12-16 18:01:37 -05002744 0x02, /* val: false */
Allen George0e22c362017-01-30 07:15:00 -05002745 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002746
Allen George0e22c362017-01-30 07:15:00 -05002747 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002748 }
2749
2750 #[test]
2751 fn must_round_trip_map_with_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002752 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002753
2754 let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
2755 assert_success!(o_prot.write_map_begin(&map_ident));
2756 assert_success!(o_prot.write_bool(true));
2757 assert_success!(o_prot.write_bool(false));
2758 assert_success!(o_prot.write_bool(false));
2759 assert_success!(o_prot.write_bool(true));
2760 assert_success!(o_prot.write_map_end());
2761
Allen George0e22c362017-01-30 07:15:00 -05002762 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002763
2764 // map header
2765 let rcvd_ident = assert_success!(i_prot.read_map_begin());
2766 assert_eq!(&rcvd_ident, &map_ident);
2767 // key 1
2768 let b = assert_success!(i_prot.read_bool());
2769 assert_eq!(b, true);
2770 // val 1
2771 let b = assert_success!(i_prot.read_bool());
2772 assert_eq!(b, false);
2773 // key 2
2774 let b = assert_success!(i_prot.read_bool());
2775 assert_eq!(b, false);
2776 // val 2
2777 let b = assert_success!(i_prot.read_bool());
2778 assert_eq!(b, true);
2779 // map end
2780 assert_success!(i_prot.read_map_end());
2781 }
2782
2783 #[test]
2784 fn must_read_map_end() {
Allen George0e22c362017-01-30 07:15:00 -05002785 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002786 assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
2787 }
2788
Allen Georgeef7a1892018-12-16 18:01:37 -05002789 fn test_objects() -> (
2790 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2791 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2792 ) {
Allen George0e22c362017-01-30 07:15:00 -05002793 let mem = TBufferChannel::with_capacity(80, 80);
Allen George8b96bfb2016-11-02 08:01:08 -04002794
Allen George0e22c362017-01-30 07:15:00 -05002795 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -04002796
Allen George0e22c362017-01-30 07:15:00 -05002797 let i_prot = TCompactInputProtocol::new(r_mem);
2798 let o_prot = TCompactOutputProtocol::new(w_mem);
Allen George8b96bfb2016-11-02 08:01:08 -04002799
Allen George0e22c362017-01-30 07:15:00 -05002800 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -04002801 }
2802
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002803 #[test]
2804 fn must_read_write_double() {
2805 let (mut i_prot, mut o_prot) = test_objects();
2806
Allen George7ddbcc02020-11-08 09:51:19 -05002807 #[allow(clippy::approx_constant)]
2808 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002809 o_prot.write_double(double).unwrap();
2810 copy_write_buffer_to_read_buffer!(o_prot);
2811
Allen George7ddbcc02020-11-08 09:51:19 -05002812 let read_double = i_prot.read_double().unwrap();
2813 assert!(read_double - double < std::f64::EPSILON);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002814 }
2815
2816 #[test]
2817 fn must_encode_double_as_other_langs() {
2818 let (_, mut o_prot) = test_objects();
2819 let expected = [24, 45, 68, 84, 251, 33, 9, 64];
2820
Allen George7ddbcc02020-11-08 09:51:19 -05002821 #[allow(clippy::approx_constant)]
2822 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002823 o_prot.write_double(double).unwrap();
2824
2825 assert_eq_written_bytes!(o_prot, expected);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002826 }
2827
Allen George0e22c362017-01-30 07:15:00 -05002828 fn assert_no_write<F>(mut write_fn: F)
2829 where
Allen Georgeb0d14132020-03-29 11:48:55 -04002830 F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> crate::Result<()>,
Allen George0e22c362017-01-30 07:15:00 -05002831 {
2832 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002833 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -05002834 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -04002835 }
2836}