blob: 566f344cff1b4e84749af6d82d0b06a3c14280a1 [file] [log] [blame]
Allen George8b96bfb2016-11-02 08:01:08 -04001// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
Marcin Pajkowskib34680f2019-12-02 10:29:16 +010018use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
Allen George8b96bfb2016-11-02 08:01:08 -040019use integer_encoding::{VarIntReader, VarIntWriter};
Danny Browningddec4312019-03-08 14:20:41 -070020use std::convert::{From, TryFrom};
Vadim Chekand3355af2018-01-05 23:12:47 -050021use std::io;
Allen George8b96bfb2016-11-02 08:01:08 -040022
Allen Georgeef7a1892018-12-16 18:01:37 -050023use super::{
24 TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier, TMapIdentifier,
25 TMessageIdentifier, TMessageType,
26};
Allen George8b96bfb2016-11-02 08:01:08 -040027use super::{TOutputProtocol, TOutputProtocolFactory, TSetIdentifier, TStructIdentifier, TType};
Allen Georgeb0d14132020-03-29 11:48:55 -040028use crate::transport::{TReadTransport, TWriteTransport};
Allen George8b96bfb2016-11-02 08:01:08 -040029
30const COMPACT_PROTOCOL_ID: u8 = 0x82;
31const COMPACT_VERSION: u8 = 0x01;
32const COMPACT_VERSION_MASK: u8 = 0x1F;
33
34/// Read messages encoded in the Thrift compact protocol.
35///
36/// # Examples
37///
38/// Create and use a `TCompactInputProtocol`.
39///
40/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -040041/// use thrift::protocol::{TCompactInputProtocol, TInputProtocol};
Allen George0e22c362017-01-30 07:15:00 -050042/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -040043///
Allen George0e22c362017-01-30 07:15:00 -050044/// let mut channel = TTcpChannel::new();
45/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040046///
Allen George0e22c362017-01-30 07:15:00 -050047/// let mut protocol = TCompactInputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -040048///
Allen George0e22c362017-01-30 07:15:00 -050049/// let recvd_bool = protocol.read_bool().unwrap();
50/// let recvd_string = protocol.read_string().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040051/// ```
Allen George0e22c362017-01-30 07:15:00 -050052#[derive(Debug)]
53pub struct TCompactInputProtocol<T>
54where
55 T: TReadTransport,
56{
Allen George8b96bfb2016-11-02 08:01:08 -040057 // Identifier of the last field deserialized for a struct.
58 last_read_field_id: i16,
59 // Stack of the last read field ids (a new entry is added each time a nested struct is read).
60 read_field_id_stack: Vec<i16>,
61 // Boolean value for a field.
62 // Saved because boolean fields and their value are encoded in a single byte,
63 // and reading the field only occurs after the field id is read.
64 pending_read_bool_value: Option<bool>,
65 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -050066 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -040067}
68
Allen George0e22c362017-01-30 07:15:00 -050069impl<T> TCompactInputProtocol<T>
70where
71 T: TReadTransport,
72{
Allen George8b96bfb2016-11-02 08:01:08 -040073 /// Create a `TCompactInputProtocol` that reads bytes from `transport`.
Allen George0e22c362017-01-30 07:15:00 -050074 pub fn new(transport: T) -> TCompactInputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -040075 TCompactInputProtocol {
76 last_read_field_id: 0,
77 read_field_id_stack: Vec::new(),
78 pending_read_bool_value: None,
Allen George7ddbcc02020-11-08 09:51:19 -050079 transport,
Allen George8b96bfb2016-11-02 08:01:08 -040080 }
81 }
82
Allen Georgeb0d14132020-03-29 11:48:55 -040083 fn read_list_set_begin(&mut self) -> crate::Result<(TType, i32)> {
Allen George8b96bfb2016-11-02 08:01:08 -040084 let header = self.read_byte()?;
85 let element_type = collection_u8_to_type(header & 0x0F)?;
86
87 let element_count;
88 let possible_element_count = (header & 0xF0) >> 4;
89 if possible_element_count != 15 {
90 // high bits set high if count and type encoded separately
91 element_count = possible_element_count as i32;
92 } else {
Allen George0e22c362017-01-30 07:15:00 -050093 element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -040094 }
95
96 Ok((element_type, element_count))
97 }
98}
99
Allen George0e22c362017-01-30 07:15:00 -0500100impl<T> TInputProtocol for TCompactInputProtocol<T>
101where
102 T: TReadTransport,
103{
Allen Georgeb0d14132020-03-29 11:48:55 -0400104 fn read_message_begin(&mut self) -> crate::Result<TMessageIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400105 let compact_id = self.read_byte()?;
106 if compact_id != COMPACT_PROTOCOL_ID {
Allen Georgeb0d14132020-03-29 11:48:55 -0400107 Err(crate::Error::Protocol(crate::ProtocolError {
108 kind: crate::ProtocolErrorKind::BadVersion,
Allen Georgeef7a1892018-12-16 18:01:37 -0500109 message: format!("invalid compact protocol header {:?}", compact_id),
110 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400111 } else {
112 Ok(())
113 }?;
114
115 let type_and_byte = self.read_byte()?;
116 let received_version = type_and_byte & COMPACT_VERSION_MASK;
117 if received_version != COMPACT_VERSION {
Allen Georgeb0d14132020-03-29 11:48:55 -0400118 Err(crate::Error::Protocol(crate::ProtocolError {
119 kind: crate::ProtocolErrorKind::BadVersion,
Allen Georgeef7a1892018-12-16 18:01:37 -0500120 message: format!(
121 "cannot process compact protocol version {:?}",
122 received_version
Allen George0e22c362017-01-30 07:15:00 -0500123 ),
Allen Georgeef7a1892018-12-16 18:01:37 -0500124 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400125 } else {
126 Ok(())
127 }?;
128
129 // NOTE: unsigned right shift will pad with 0s
130 let message_type: TMessageType = TMessageType::try_from(type_and_byte >> 5)?;
Allen George48905102021-02-20 08:47:01 -0500131 // writing side wrote signed sequence number as u32 to avoid zigzag encoding
132 let sequence_number = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400133 let service_call_name = self.read_string()?;
134
135 self.last_read_field_id = 0;
136
Allen Georgeef7a1892018-12-16 18:01:37 -0500137 Ok(TMessageIdentifier::new(
138 service_call_name,
139 message_type,
140 sequence_number,
141 ))
Allen George8b96bfb2016-11-02 08:01:08 -0400142 }
143
Allen Georgeb0d14132020-03-29 11:48:55 -0400144 fn read_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400145 Ok(())
146 }
147
Allen Georgeb0d14132020-03-29 11:48:55 -0400148 fn read_struct_begin(&mut self) -> crate::Result<Option<TStructIdentifier>> {
Allen George8b96bfb2016-11-02 08:01:08 -0400149 self.read_field_id_stack.push(self.last_read_field_id);
150 self.last_read_field_id = 0;
151 Ok(None)
152 }
153
Allen Georgeb0d14132020-03-29 11:48:55 -0400154 fn read_struct_end(&mut self) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500155 self.last_read_field_id = self
156 .read_field_id_stack
Allen George8b96bfb2016-11-02 08:01:08 -0400157 .pop()
158 .expect("should have previous field ids");
159 Ok(())
160 }
161
Allen Georgeb0d14132020-03-29 11:48:55 -0400162 fn read_field_begin(&mut self) -> crate::Result<TFieldIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400163 // we can read at least one byte, which is:
164 // - the type
165 // - the field delta and the type
166 let field_type = self.read_byte()?;
167 let field_delta = (field_type & 0xF0) >> 4;
168 let field_type = match field_type & 0x0F {
169 0x01 => {
170 self.pending_read_bool_value = Some(true);
171 Ok(TType::Bool)
172 }
173 0x02 => {
174 self.pending_read_bool_value = Some(false);
175 Ok(TType::Bool)
176 }
177 ttu8 => u8_to_type(ttu8),
178 }?;
179
180 match field_type {
Allen Georgeef7a1892018-12-16 18:01:37 -0500181 TType::Stop => Ok(
182 TFieldIdentifier::new::<Option<String>, String, Option<i16>>(
183 None,
184 TType::Stop,
185 None,
186 ),
187 ),
Allen George8b96bfb2016-11-02 08:01:08 -0400188 _ => {
189 if field_delta != 0 {
190 self.last_read_field_id += field_delta as i16;
191 } else {
192 self.last_read_field_id = self.read_i16()?;
193 };
194
Allen Georgeef7a1892018-12-16 18:01:37 -0500195 Ok(TFieldIdentifier {
196 name: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500197 field_type,
Allen Georgeef7a1892018-12-16 18:01:37 -0500198 id: Some(self.last_read_field_id),
199 })
Allen George8b96bfb2016-11-02 08:01:08 -0400200 }
201 }
202 }
203
Allen Georgeb0d14132020-03-29 11:48:55 -0400204 fn read_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400205 Ok(())
206 }
207
Allen Georgeb0d14132020-03-29 11:48:55 -0400208 fn read_bool(&mut self) -> crate::Result<bool> {
Allen George8b96bfb2016-11-02 08:01:08 -0400209 match self.pending_read_bool_value.take() {
210 Some(b) => Ok(b),
211 None => {
212 let b = self.read_byte()?;
213 match b {
214 0x01 => Ok(true),
215 0x02 => Ok(false),
Allen Georgeb0d14132020-03-29 11:48:55 -0400216 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
217 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500218 message: format!("cannot convert {} into bool", unkn),
219 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400220 }
221 }
222 }
223 }
224
Allen Georgeb0d14132020-03-29 11:48:55 -0400225 fn read_bytes(&mut self) -> crate::Result<Vec<u8>> {
Allen George0e22c362017-01-30 07:15:00 -0500226 let len = self.transport.read_varint::<u32>()?;
Allen George8b96bfb2016-11-02 08:01:08 -0400227 let mut buf = vec![0u8; len as usize];
Allen George0e22c362017-01-30 07:15:00 -0500228 self.transport
229 .read_exact(&mut buf)
230 .map_err(From::from)
231 .map(|_| buf)
Allen George8b96bfb2016-11-02 08:01:08 -0400232 }
233
Allen Georgeb0d14132020-03-29 11:48:55 -0400234 fn read_i8(&mut self) -> crate::Result<i8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400235 self.read_byte().map(|i| i as i8)
236 }
237
Allen Georgeb0d14132020-03-29 11:48:55 -0400238 fn read_i16(&mut self) -> crate::Result<i16> {
Allen George0e22c362017-01-30 07:15:00 -0500239 self.transport.read_varint::<i16>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400240 }
241
Allen Georgeb0d14132020-03-29 11:48:55 -0400242 fn read_i32(&mut self) -> crate::Result<i32> {
Allen George0e22c362017-01-30 07:15:00 -0500243 self.transport.read_varint::<i32>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400244 }
245
Allen Georgeb0d14132020-03-29 11:48:55 -0400246 fn read_i64(&mut self) -> crate::Result<i64> {
Allen George0e22c362017-01-30 07:15:00 -0500247 self.transport.read_varint::<i64>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400248 }
249
Allen Georgeb0d14132020-03-29 11:48:55 -0400250 fn read_double(&mut self) -> crate::Result<f64> {
Allen George8a1743d2020-12-05 01:19:27 -0500251 self.transport
252 .read_f64::<LittleEndian>()
253 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400254 }
255
Allen Georgeb0d14132020-03-29 11:48:55 -0400256 fn read_string(&mut self) -> crate::Result<String> {
Allen George8b96bfb2016-11-02 08:01:08 -0400257 let bytes = self.read_bytes()?;
258 String::from_utf8(bytes).map_err(From::from)
259 }
260
Allen Georgeb0d14132020-03-29 11:48:55 -0400261 fn read_list_begin(&mut self) -> crate::Result<TListIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400262 let (element_type, element_count) = self.read_list_set_begin()?;
263 Ok(TListIdentifier::new(element_type, element_count))
264 }
265
Allen Georgeb0d14132020-03-29 11:48:55 -0400266 fn read_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400267 Ok(())
268 }
269
Allen Georgeb0d14132020-03-29 11:48:55 -0400270 fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400271 let (element_type, element_count) = self.read_list_set_begin()?;
272 Ok(TSetIdentifier::new(element_type, element_count))
273 }
274
Allen Georgeb0d14132020-03-29 11:48:55 -0400275 fn read_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400276 Ok(())
277 }
278
Allen Georgeb0d14132020-03-29 11:48:55 -0400279 fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier> {
Allen George0e22c362017-01-30 07:15:00 -0500280 let element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400281 if element_count == 0 {
282 Ok(TMapIdentifier::new(None, None, 0))
283 } else {
284 let type_header = self.read_byte()?;
285 let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
286 let val_type = collection_u8_to_type(type_header & 0x0F)?;
287 Ok(TMapIdentifier::new(key_type, val_type, element_count))
288 }
289 }
290
Allen Georgeb0d14132020-03-29 11:48:55 -0400291 fn read_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400292 Ok(())
293 }
294
295 // utility
296 //
297
Allen Georgeb0d14132020-03-29 11:48:55 -0400298 fn read_byte(&mut self) -> crate::Result<u8> {
Allen George8b96bfb2016-11-02 08:01:08 -0400299 let mut buf = [0u8; 1];
Allen George0e22c362017-01-30 07:15:00 -0500300 self.transport
301 .read_exact(&mut buf)
302 .map_err(From::from)
303 .map(|_| buf[0])
Allen George8b96bfb2016-11-02 08:01:08 -0400304 }
305}
306
Vadim Chekand3355af2018-01-05 23:12:47 -0500307impl<T> io::Seek for TCompactInputProtocol<T>
308where
309 T: io::Seek + TReadTransport,
310{
311 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
312 self.transport.seek(pos)
313 }
314}
315
Allen George8b96bfb2016-11-02 08:01:08 -0400316/// Factory for creating instances of `TCompactInputProtocol`.
317#[derive(Default)]
318pub struct TCompactInputProtocolFactory;
319
320impl TCompactInputProtocolFactory {
321 /// Create a `TCompactInputProtocolFactory`.
322 pub fn new() -> TCompactInputProtocolFactory {
323 TCompactInputProtocolFactory {}
324 }
325}
326
327impl TInputProtocolFactory for TCompactInputProtocolFactory {
Danny Browning77d96c12019-08-21 13:41:07 -0600328 fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500329 Box::new(TCompactInputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400330 }
331}
332
333/// Write messages using the Thrift compact protocol.
334///
335/// # Examples
336///
337/// Create and use a `TCompactOutputProtocol`.
338///
339/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -0400340/// use thrift::protocol::{TCompactOutputProtocol, TOutputProtocol};
Allen George0e22c362017-01-30 07:15:00 -0500341/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -0400342///
Allen George0e22c362017-01-30 07:15:00 -0500343/// let mut channel = TTcpChannel::new();
344/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400345///
Allen George0e22c362017-01-30 07:15:00 -0500346/// let mut protocol = TCompactOutputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -0400347///
Allen George0e22c362017-01-30 07:15:00 -0500348/// protocol.write_bool(true).unwrap();
349/// protocol.write_string("test_string").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400350/// ```
Allen George0e22c362017-01-30 07:15:00 -0500351#[derive(Debug)]
352pub struct TCompactOutputProtocol<T>
353where
354 T: TWriteTransport,
355{
Allen George8b96bfb2016-11-02 08:01:08 -0400356 // Identifier of the last field serialized for a struct.
357 last_write_field_id: i16,
Allen George0e22c362017-01-30 07:15:00 -0500358 // Stack of the last written field ids (new entry added each time a nested struct is written).
Allen George8b96bfb2016-11-02 08:01:08 -0400359 write_field_id_stack: Vec<i16>,
360 // Field identifier of the boolean field to be written.
361 // Saved because boolean fields and their value are encoded in a single byte
362 pending_write_bool_field_identifier: Option<TFieldIdentifier>,
363 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -0500364 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -0400365}
366
Allen George0e22c362017-01-30 07:15:00 -0500367impl<T> TCompactOutputProtocol<T>
368where
369 T: TWriteTransport,
370{
Allen George8b96bfb2016-11-02 08:01:08 -0400371 /// Create a `TCompactOutputProtocol` that writes bytes to `transport`.
Allen George0e22c362017-01-30 07:15:00 -0500372 pub fn new(transport: T) -> TCompactOutputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -0400373 TCompactOutputProtocol {
374 last_write_field_id: 0,
375 write_field_id_stack: Vec::new(),
376 pending_write_bool_field_identifier: None,
Allen George7ddbcc02020-11-08 09:51:19 -0500377 transport,
Allen George8b96bfb2016-11-02 08:01:08 -0400378 }
379 }
380
381 // FIXME: field_type as unconstrained u8 is bad
Allen Georgeb0d14132020-03-29 11:48:55 -0400382 fn write_field_header(&mut self, field_type: u8, field_id: i16) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400383 let field_delta = field_id - self.last_write_field_id;
384 if field_delta > 0 && field_delta < 15 {
385 self.write_byte(((field_delta as u8) << 4) | field_type)?;
386 } else {
387 self.write_byte(field_type)?;
388 self.write_i16(field_id)?;
389 }
390 self.last_write_field_id = field_id;
391 Ok(())
392 }
393
Allen George8a1743d2020-12-05 01:19:27 -0500394 fn write_list_set_begin(
395 &mut self,
396 element_type: TType,
397 element_count: i32,
398 ) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400399 let elem_identifier = collection_type_to_u8(element_type);
400 if element_count <= 14 {
401 let header = (element_count as u8) << 4 | elem_identifier;
402 self.write_byte(header)
403 } else {
404 let header = 0xF0 | elem_identifier;
405 self.write_byte(header)?;
Allen George48905102021-02-20 08:47:01 -0500406 // element count is strictly positive as per the spec, so
407 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George8b96bfb2016-11-02 08:01:08 -0400408 self.transport
Allen George8b96bfb2016-11-02 08:01:08 -0400409 .write_varint(element_count as u32)
410 .map_err(From::from)
411 .map(|_| ())
412 }
413 }
414
415 fn assert_no_pending_bool_write(&self) {
416 if let Some(ref f) = self.pending_write_bool_field_identifier {
417 panic!("pending bool field {:?} not written", f)
418 }
419 }
420}
421
Allen George0e22c362017-01-30 07:15:00 -0500422impl<T> TOutputProtocol for TCompactOutputProtocol<T>
423where
424 T: TWriteTransport,
425{
Allen Georgeb0d14132020-03-29 11:48:55 -0400426 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400427 self.write_byte(COMPACT_PROTOCOL_ID)?;
428 self.write_byte((u8::from(identifier.message_type) << 5) | COMPACT_VERSION)?;
Allen George48905102021-02-20 08:47:01 -0500429 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George55c3e4c2021-03-01 23:19:52 -0500430 self.transport
431 .write_varint(identifier.sequence_number as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400432 self.write_string(&identifier.name)?;
433 Ok(())
434 }
435
Allen Georgeb0d14132020-03-29 11:48:55 -0400436 fn write_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400437 self.assert_no_pending_bool_write();
438 Ok(())
439 }
440
Allen Georgeb0d14132020-03-29 11:48:55 -0400441 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400442 self.write_field_id_stack.push(self.last_write_field_id);
443 self.last_write_field_id = 0;
444 Ok(())
445 }
446
Allen Georgeb0d14132020-03-29 11:48:55 -0400447 fn write_struct_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400448 self.assert_no_pending_bool_write();
Allen Georgeef7a1892018-12-16 18:01:37 -0500449 self.last_write_field_id = self
450 .write_field_id_stack
Allen George0e22c362017-01-30 07:15:00 -0500451 .pop()
452 .expect("should have previous field ids");
Allen George8b96bfb2016-11-02 08:01:08 -0400453 Ok(())
454 }
455
Allen Georgeb0d14132020-03-29 11:48:55 -0400456 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400457 match identifier.field_type {
458 TType::Bool => {
459 if self.pending_write_bool_field_identifier.is_some() {
Allen George0e22c362017-01-30 07:15:00 -0500460 panic!(
461 "should not have a pending bool while writing another bool with id: \
Allen Georgeef7a1892018-12-16 18:01:37 -0500462 {:?}",
Allen George0e22c362017-01-30 07:15:00 -0500463 identifier
464 )
Allen George8b96bfb2016-11-02 08:01:08 -0400465 }
466 self.pending_write_bool_field_identifier = Some(identifier.clone());
467 Ok(())
468 }
469 _ => {
470 let field_type = type_to_u8(identifier.field_type);
Allen Georgeef7a1892018-12-16 18:01:37 -0500471 let field_id = identifier.id.expect("non-stop field should have field id");
Allen George8b96bfb2016-11-02 08:01:08 -0400472 self.write_field_header(field_type, field_id)
473 }
474 }
475 }
476
Allen Georgeb0d14132020-03-29 11:48:55 -0400477 fn write_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400478 self.assert_no_pending_bool_write();
479 Ok(())
480 }
481
Allen Georgeb0d14132020-03-29 11:48:55 -0400482 fn write_field_stop(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400483 self.assert_no_pending_bool_write();
484 self.write_byte(type_to_u8(TType::Stop))
485 }
486
Allen Georgeb0d14132020-03-29 11:48:55 -0400487 fn write_bool(&mut self, b: bool) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400488 match self.pending_write_bool_field_identifier.take() {
489 Some(pending) => {
490 let field_id = pending.id.expect("bool field should have a field id");
491 let field_type_as_u8 = if b { 0x01 } else { 0x02 };
492 self.write_field_header(field_type_as_u8, field_id)
493 }
494 None => {
495 if b {
496 self.write_byte(0x01)
497 } else {
498 self.write_byte(0x02)
499 }
500 }
501 }
502 }
503
Allen Georgeb0d14132020-03-29 11:48:55 -0400504 fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> {
Allen George48905102021-02-20 08:47:01 -0500505 // length is strictly positive as per the spec, so
506 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500507 self.transport.write_varint(b.len() as u32)?;
508 self.transport.write_all(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400509 }
510
Allen Georgeb0d14132020-03-29 11:48:55 -0400511 fn write_i8(&mut self, i: i8) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400512 self.write_byte(i as u8)
513 }
514
Allen Georgeb0d14132020-03-29 11:48:55 -0400515 fn write_i16(&mut self, i: i16) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500516 self.transport
Allen George48905102021-02-20 08:47:01 -0500517 .write_varint(i)
Allen George0e22c362017-01-30 07:15:00 -0500518 .map_err(From::from)
519 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400520 }
521
Allen Georgeb0d14132020-03-29 11:48:55 -0400522 fn write_i32(&mut self, i: i32) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500523 self.transport
524 .write_varint(i)
525 .map_err(From::from)
526 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400527 }
528
Allen Georgeb0d14132020-03-29 11:48:55 -0400529 fn write_i64(&mut self, i: i64) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500530 self.transport
531 .write_varint(i)
532 .map_err(From::from)
533 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400534 }
535
Allen Georgeb0d14132020-03-29 11:48:55 -0400536 fn write_double(&mut self, d: f64) -> crate::Result<()> {
Allen George8a1743d2020-12-05 01:19:27 -0500537 self.transport
538 .write_f64::<LittleEndian>(d)
539 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400540 }
541
Allen Georgeb0d14132020-03-29 11:48:55 -0400542 fn write_string(&mut self, s: &str) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400543 self.write_bytes(s.as_bytes())
544 }
545
Allen Georgeb0d14132020-03-29 11:48:55 -0400546 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400547 self.write_list_set_begin(identifier.element_type, identifier.size)
548 }
549
Allen Georgeb0d14132020-03-29 11:48:55 -0400550 fn write_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400551 Ok(())
552 }
553
Allen Georgeb0d14132020-03-29 11:48:55 -0400554 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400555 self.write_list_set_begin(identifier.element_type, identifier.size)
556 }
557
Allen Georgeb0d14132020-03-29 11:48:55 -0400558 fn write_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400559 Ok(())
560 }
561
Allen Georgeb0d14132020-03-29 11:48:55 -0400562 fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400563 if identifier.size == 0 {
564 self.write_byte(0)
565 } else {
Allen George48905102021-02-20 08:47:01 -0500566 // element count is strictly positive as per the spec, so
567 // cast i32 as u32 so that varint writing won't use zigzag encoding
Allen George0e22c362017-01-30 07:15:00 -0500568 self.transport.write_varint(identifier.size as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400569
Allen George0e22c362017-01-30 07:15:00 -0500570 let key_type = identifier
571 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400572 .expect("map identifier to write should contain key type");
573 let key_type_byte = collection_type_to_u8(key_type) << 4;
574
Allen George0e22c362017-01-30 07:15:00 -0500575 let val_type = identifier
576 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400577 .expect("map identifier to write should contain value type");
578 let val_type_byte = collection_type_to_u8(val_type);
579
580 let map_type_header = key_type_byte | val_type_byte;
581 self.write_byte(map_type_header)
582 }
583 }
584
Allen Georgeb0d14132020-03-29 11:48:55 -0400585 fn write_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400586 Ok(())
587 }
588
Allen Georgeb0d14132020-03-29 11:48:55 -0400589 fn flush(&mut self) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500590 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400591 }
592
593 // utility
594 //
595
Allen Georgeb0d14132020-03-29 11:48:55 -0400596 fn write_byte(&mut self, b: u8) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500597 self.transport.write(&[b]).map_err(From::from).map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400598 }
599}
600
601/// Factory for creating instances of `TCompactOutputProtocol`.
602#[derive(Default)]
603pub struct TCompactOutputProtocolFactory;
604
605impl TCompactOutputProtocolFactory {
606 /// Create a `TCompactOutputProtocolFactory`.
607 pub fn new() -> TCompactOutputProtocolFactory {
608 TCompactOutputProtocolFactory {}
609 }
610}
611
612impl TOutputProtocolFactory for TCompactOutputProtocolFactory {
Allen George8a1743d2020-12-05 01:19:27 -0500613 fn create(
614 &self,
615 transport: Box<dyn TWriteTransport + Send>,
616 ) -> Box<dyn TOutputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500617 Box::new(TCompactOutputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400618 }
619}
620
621fn collection_type_to_u8(field_type: TType) -> u8 {
622 match field_type {
623 TType::Bool => 0x01,
624 f => type_to_u8(f),
625 }
626}
627
628fn type_to_u8(field_type: TType) -> u8 {
629 match field_type {
630 TType::Stop => 0x00,
631 TType::I08 => 0x03, // equivalent to TType::Byte
632 TType::I16 => 0x04,
633 TType::I32 => 0x05,
634 TType::I64 => 0x06,
635 TType::Double => 0x07,
636 TType::String => 0x08,
637 TType::List => 0x09,
638 TType::Set => 0x0A,
639 TType::Map => 0x0B,
640 TType::Struct => 0x0C,
Allen George2b691ee2021-10-14 22:25:07 -0400641 _ => panic!("should not have attempted to convert {} to u8", field_type),
Allen George8b96bfb2016-11-02 08:01:08 -0400642 }
643}
644
Allen Georgeb0d14132020-03-29 11:48:55 -0400645fn collection_u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400646 match b {
647 0x01 => Ok(TType::Bool),
648 o => u8_to_type(o),
649 }
650}
651
Allen Georgeb0d14132020-03-29 11:48:55 -0400652fn u8_to_type(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400653 match b {
654 0x00 => Ok(TType::Stop),
655 0x03 => Ok(TType::I08), // equivalent to TType::Byte
656 0x04 => Ok(TType::I16),
657 0x05 => Ok(TType::I32),
658 0x06 => Ok(TType::I64),
659 0x07 => Ok(TType::Double),
660 0x08 => Ok(TType::String),
661 0x09 => Ok(TType::List),
662 0x0A => Ok(TType::Set),
663 0x0B => Ok(TType::Map),
664 0x0C => Ok(TType::Struct),
Allen Georgeb0d14132020-03-29 11:48:55 -0400665 unkn => Err(crate::Error::Protocol(crate::ProtocolError {
666 kind: crate::ProtocolErrorKind::InvalidData,
Allen Georgeef7a1892018-12-16 18:01:37 -0500667 message: format!("cannot convert {} into TType", unkn),
668 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400669 }
670}
671
672#[cfg(test)]
673mod tests {
674
Allen George8a1743d2020-12-05 01:19:27 -0500675 use std::i32;
676
Allen Georgeb0d14132020-03-29 11:48:55 -0400677 use crate::protocol::{
Allen Georgeef7a1892018-12-16 18:01:37 -0500678 TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
679 TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
680 };
Allen Georgeb0d14132020-03-29 11:48:55 -0400681 use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400682
683 use super::*;
684
685 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500686 fn must_write_message_begin_largest_maximum_positive_sequence_number() {
687 let (_, mut o_prot) = test_objects();
688
689 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
690 "bar",
691 TMessageType::Reply,
692 i32::MAX
693 )));
694
695 #[rustfmt::skip]
696 let expected: [u8; 11] = [
697 0x82, /* protocol ID */
698 0x41, /* message type | protocol version */
699 0xFF,
700 0xFF,
701 0xFF,
702 0xFF,
703 0x07, /* non-zig-zag varint sequence number */
704 0x03, /* message-name length */
705 0x62,
706 0x61,
707 0x72 /* "bar" */,
708 ];
709
710 assert_eq_written_bytes!(o_prot, expected);
711 }
712
713 #[test]
714 fn must_read_message_begin_largest_maximum_positive_sequence_number() {
715 let (mut i_prot, _) = test_objects();
716
717 #[rustfmt::skip]
718 let source_bytes: [u8; 11] = [
719 0x82, /* protocol ID */
720 0x41, /* message type | protocol version */
721 0xFF,
722 0xFF,
723 0xFF,
724 0xFF,
725 0x07, /* non-zig-zag varint sequence number */
726 0x03, /* message-name length */
727 0x62,
728 0x61,
729 0x72 /* "bar" */,
730 ];
731
732 i_prot.transport.set_readable_bytes(&source_bytes);
733
734 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MAX);
735 let res = assert_success!(i_prot.read_message_begin());
736
737 assert_eq!(&expected, &res);
738 }
739
740 #[test]
741 fn must_write_message_begin_positive_sequence_number_0() {
Allen George0e22c362017-01-30 07:15:00 -0500742 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400743
Allen Georgeef7a1892018-12-16 18:01:37 -0500744 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
745 "foo",
746 TMessageType::Call,
747 431
748 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400749
Allen George7ddbcc02020-11-08 09:51:19 -0500750 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500751 let expected: [u8; 8] = [
752 0x82, /* protocol ID */
753 0x21, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500754 0xAF,
755 0x03, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500756 0x03, /* message-name length */
757 0x66,
758 0x6F,
759 0x6F /* "foo" */,
760 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400761
Allen George0e22c362017-01-30 07:15:00 -0500762 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400763 }
764
765 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500766 fn must_read_message_begin_positive_sequence_number_0() {
767 let (mut i_prot, _) = test_objects();
768
769 #[rustfmt::skip]
770 let source_bytes: [u8; 8] = [
771 0x82, /* protocol ID */
772 0x21, /* message type | protocol version */
773 0xAF,
774 0x03, /* non-zig-zag varint sequence number */
775 0x03, /* message-name length */
776 0x66,
777 0x6F,
778 0x6F /* "foo" */,
779 ];
780
781 i_prot.transport.set_readable_bytes(&source_bytes);
782
783 let expected = TMessageIdentifier::new("foo", TMessageType::Call, 431);
784 let res = assert_success!(i_prot.read_message_begin());
785
786 assert_eq!(&expected, &res);
787 }
788
789 #[test]
790 fn must_write_message_begin_positive_sequence_number_1() {
Allen George0e22c362017-01-30 07:15:00 -0500791 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400792
Allen Georgeef7a1892018-12-16 18:01:37 -0500793 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
794 "bar",
795 TMessageType::Reply,
Allen George7ddbcc02020-11-08 09:51:19 -0500796 991_828
Allen Georgeef7a1892018-12-16 18:01:37 -0500797 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400798
Allen George7ddbcc02020-11-08 09:51:19 -0500799 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500800 let expected: [u8; 9] = [
801 0x82, /* protocol ID */
802 0x41, /* message type | protocol version */
Allen George8a1743d2020-12-05 01:19:27 -0500803 0xD4,
804 0xC4,
805 0x3C, /* non-zig-zag varint sequence number */
Allen George0e22c362017-01-30 07:15:00 -0500806 0x03, /* message-name length */
807 0x62,
808 0x61,
809 0x72 /* "bar" */,
810 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400811
Allen George0e22c362017-01-30 07:15:00 -0500812 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400813 }
814
815 #[test]
Allen George8a1743d2020-12-05 01:19:27 -0500816 fn must_read_message_begin_positive_sequence_number_1() {
817 let (mut i_prot, _) = test_objects();
818
819 #[rustfmt::skip]
820 let source_bytes: [u8; 9] = [
821 0x82, /* protocol ID */
822 0x41, /* message type | protocol version */
823 0xD4,
824 0xC4,
825 0x3C, /* non-zig-zag varint sequence number */
826 0x03, /* message-name length */
827 0x62,
828 0x61,
829 0x72 /* "bar" */,
830 ];
831
832 i_prot.transport.set_readable_bytes(&source_bytes);
833
834 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 991_828);
835 let res = assert_success!(i_prot.read_message_begin());
836
837 assert_eq!(&expected, &res);
838 }
839
840 #[test]
841 fn must_write_message_begin_zero_sequence_number() {
842 let (_, mut o_prot) = test_objects();
843
844 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
845 "bar",
846 TMessageType::Reply,
847 0
848 )));
849
850 #[rustfmt::skip]
851 let expected: [u8; 7] = [
852 0x82, /* protocol ID */
853 0x41, /* message type | protocol version */
854 0x00, /* non-zig-zag varint sequence number */
855 0x03, /* message-name length */
856 0x62,
857 0x61,
858 0x72 /* "bar" */,
859 ];
860
861 assert_eq_written_bytes!(o_prot, expected);
862 }
863
864 #[test]
865 fn must_read_message_begin_zero_sequence_number() {
866 let (mut i_prot, _) = test_objects();
867
868 #[rustfmt::skip]
869 let source_bytes: [u8; 7] = [
870 0x82, /* protocol ID */
871 0x41, /* message type | protocol version */
872 0x00, /* non-zig-zag varint sequence number */
873 0x03, /* message-name length */
874 0x62,
875 0x61,
876 0x72 /* "bar" */,
877 ];
878
879 i_prot.transport.set_readable_bytes(&source_bytes);
880
881 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 0);
882 let res = assert_success!(i_prot.read_message_begin());
883
884 assert_eq!(&expected, &res);
885 }
886
887 #[test]
888 fn must_write_message_begin_largest_minimum_negative_sequence_number() {
889 let (_, mut o_prot) = test_objects();
890
891 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
892 "bar",
893 TMessageType::Reply,
894 i32::MIN
895 )));
896
897 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
898 #[rustfmt::skip]
899 let expected: [u8; 11] = [
900 0x82, /* protocol ID */
901 0x41, /* message type | protocol version */
902 0x80,
903 0x80,
904 0x80,
905 0x80,
906 0x08, /* non-zig-zag varint sequence number */
907 0x03, /* message-name length */
908 0x62,
909 0x61,
910 0x72 /* "bar" */,
911 ];
912
913 assert_eq_written_bytes!(o_prot, expected);
914 }
915
916 #[test]
917 fn must_read_message_begin_largest_minimum_negative_sequence_number() {
918 let (mut i_prot, _) = test_objects();
919
920 // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
921 #[rustfmt::skip]
922 let source_bytes: [u8; 11] = [
923 0x82, /* protocol ID */
924 0x41, /* message type | protocol version */
925 0x80,
926 0x80,
927 0x80,
928 0x80,
929 0x08, /* non-zig-zag varint sequence number */
930 0x03, /* message-name length */
931 0x62,
932 0x61,
933 0x72 /* "bar" */,
934 ];
935
936 i_prot.transport.set_readable_bytes(&source_bytes);
937
938 let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MIN);
939 let res = assert_success!(i_prot.read_message_begin());
940
941 assert_eq!(&expected, &res);
942 }
943
944 #[test]
945 fn must_write_message_begin_negative_sequence_number_0() {
946 let (_, mut o_prot) = test_objects();
947
948 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
949 "foo",
950 TMessageType::Call,
951 -431
952 )));
953
954 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
955 #[rustfmt::skip]
956 let expected: [u8; 11] = [
957 0x82, /* protocol ID */
958 0x21, /* message type | protocol version */
959 0xD1,
960 0xFC,
961 0xFF,
962 0xFF,
963 0x0F, /* non-zig-zag varint sequence number */
964 0x03, /* message-name length */
965 0x66,
966 0x6F,
967 0x6F /* "foo" */,
968 ];
969
970 assert_eq_written_bytes!(o_prot, expected);
971 }
972
973 #[test]
974 fn must_read_message_begin_negative_sequence_number_0() {
975 let (mut i_prot, _) = test_objects();
976
977 // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
978 #[rustfmt::skip]
979 let source_bytes: [u8; 11] = [
980 0x82, /* protocol ID */
981 0x21, /* message type | protocol version */
982 0xD1,
983 0xFC,
984 0xFF,
985 0xFF,
986 0x0F, /* non-zig-zag varint sequence number */
987 0x03, /* message-name length */
988 0x66,
989 0x6F,
990 0x6F /* "foo" */,
991 ];
992
993 i_prot.transport.set_readable_bytes(&source_bytes);
994
995 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -431);
996 let res = assert_success!(i_prot.read_message_begin());
997
998 assert_eq!(&expected, &res);
999 }
1000
1001 #[test]
1002 fn must_write_message_begin_negative_sequence_number_1() {
1003 let (_, mut o_prot) = test_objects();
1004
1005 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1006 "foo",
1007 TMessageType::Call,
1008 -73_184_125
1009 )));
1010
1011 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1012 #[rustfmt::skip]
1013 let expected: [u8; 11] = [
1014 0x82, /* protocol ID */
1015 0x21, /* message type | protocol version */
1016 0x83,
1017 0x99,
1018 0x8D,
1019 0xDD,
1020 0x0F, /* non-zig-zag varint sequence number */
1021 0x03, /* message-name length */
1022 0x66,
1023 0x6F,
1024 0x6F /* "foo" */,
1025 ];
1026
1027 assert_eq_written_bytes!(o_prot, expected);
1028 }
1029
1030 #[test]
1031 fn must_read_message_begin_negative_sequence_number_1() {
1032 let (mut i_prot, _) = test_objects();
1033
1034 // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1035 #[rustfmt::skip]
1036 let source_bytes: [u8; 11] = [
1037 0x82, /* protocol ID */
1038 0x21, /* message type | protocol version */
1039 0x83,
1040 0x99,
1041 0x8D,
1042 0xDD,
1043 0x0F, /* non-zig-zag varint sequence number */
1044 0x03, /* message-name length */
1045 0x66,
1046 0x6F,
1047 0x6F /* "foo" */,
1048 ];
1049
1050 i_prot.transport.set_readable_bytes(&source_bytes);
1051
1052 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -73_184_125);
1053 let res = assert_success!(i_prot.read_message_begin());
1054
1055 assert_eq!(&expected, &res);
1056 }
1057
1058 #[test]
1059 fn must_write_message_begin_negative_sequence_number_2() {
1060 let (_, mut o_prot) = test_objects();
1061
1062 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1063 "foo",
1064 TMessageType::Call,
1065 -1_073_741_823
1066 )));
1067
1068 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
1069 #[rustfmt::skip]
1070 let expected: [u8; 11] = [
1071 0x82, /* protocol ID */
1072 0x21, /* message type | protocol version */
1073 0x81,
1074 0x80,
1075 0x80,
1076 0x80,
1077 0x0C, /* non-zig-zag varint sequence number */
1078 0x03, /* message-name length */
1079 0x66,
1080 0x6F,
1081 0x6F /* "foo" */,
1082 ];
1083
1084 assert_eq_written_bytes!(o_prot, expected);
1085 }
1086
1087 #[test]
1088 fn must_read_message_begin_negative_sequence_number_2() {
1089 let (mut i_prot, _) = test_objects();
1090
1091 // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
Allen George55c3e4c2021-03-01 23:19:52 -05001092 #[rustfmt::skip]
Allen George8a1743d2020-12-05 01:19:27 -05001093 let source_bytes: [u8; 11] = [
1094 0x82, /* protocol ID */
1095 0x21, /* message type | protocol version */
1096 0x81,
1097 0x80,
1098 0x80,
1099 0x80,
1100 0x0C, /* non-zig-zag varint sequence number */
1101 0x03, /* message-name length */
1102 0x66,
1103 0x6F,
Allen George55c3e4c2021-03-01 23:19:52 -05001104 0x6F, /* "foo" */
Allen George8a1743d2020-12-05 01:19:27 -05001105 ];
1106
1107 i_prot.transport.set_readable_bytes(&source_bytes);
1108
1109 let expected = TMessageIdentifier::new("foo", TMessageType::Call, -1_073_741_823);
1110 let res = assert_success!(i_prot.read_message_begin());
1111
1112 assert_eq!(&expected, &res);
1113 }
1114
1115 #[test]
Nik Claytone7917602020-03-05 11:51:15 +01001116 fn must_round_trip_upto_i64_maxvalue() {
1117 // See https://issues.apache.org/jira/browse/THRIFT-5131
1118 for i in 0..64 {
1119 let (mut i_prot, mut o_prot) = test_objects();
1120 let val: i64 = ((1u64 << i) - 1) as i64;
1121
1122 o_prot
Allen George8a1743d2020-12-05 01:19:27 -05001123 .write_field_begin(&TFieldIdentifier::new("val", TType::I64, 1))
Nik Claytone7917602020-03-05 11:51:15 +01001124 .unwrap();
1125 o_prot.write_i64(val).unwrap();
1126 o_prot.write_field_end().unwrap();
1127 o_prot.flush().unwrap();
1128
1129 copy_write_buffer_to_read_buffer!(o_prot);
1130
1131 i_prot.read_field_begin().unwrap();
1132 assert_eq!(val, i_prot.read_i64().unwrap());
1133 }
1134 }
1135
1136 #[test]
Allen George8b96bfb2016-11-02 08:01:08 -04001137 fn must_round_trip_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -05001138 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001139
Allen George7ddbcc02020-11-08 09:51:19 -05001140 let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948);
Allen George8b96bfb2016-11-02 08:01:08 -04001141
1142 assert_success!(o_prot.write_message_begin(&ident));
1143
Allen George0e22c362017-01-30 07:15:00 -05001144 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001145
1146 let res = assert_success!(i_prot.read_message_begin());
1147 assert_eq!(&res, &ident);
1148 }
1149
1150 #[test]
1151 fn must_write_message_end() {
1152 assert_no_write(|o| o.write_message_end());
1153 }
1154
1155 // NOTE: structs and fields are tested together
1156 //
1157
1158 #[test]
1159 fn must_write_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001160 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001161
1162 // no bytes should be written however
1163 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1164
1165 // write three fields with tiny field ids
1166 // since they're small the field ids will be encoded as deltas
1167
1168 // since this is the first field (and it's zero) it gets the full varint write
1169 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
1170 assert_success!(o_prot.write_field_end());
1171
1172 // since this delta > 0 and < 15 it can be encoded as a delta
1173 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
1174 assert_success!(o_prot.write_field_end());
1175
1176 // since this delta > 0 and < 15 it can be encoded as a delta
1177 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
1178 assert_success!(o_prot.write_field_end());
1179
1180 // now, finish the struct off
1181 assert_success!(o_prot.write_field_stop());
1182 assert_success!(o_prot.write_struct_end());
1183
Allen George7ddbcc02020-11-08 09:51:19 -05001184 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001185 let expected: [u8; 5] = [
1186 0x03, /* field type */
1187 0x00, /* first field id */
1188 0x44, /* field delta (4) | field type */
1189 0x59, /* field delta (5) | field type */
1190 0x00 /* field stop */,
1191 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001192
Allen George0e22c362017-01-30 07:15:00 -05001193 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001194 }
1195
1196 #[test]
1197 fn must_round_trip_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001198 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001199
1200 // no bytes should be written however
1201 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1202
1203 // write three fields with tiny field ids
1204 // since they're small the field ids will be encoded as deltas
1205
1206 // since this is the first field (and it's zero) it gets the full varint write
1207 let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
1208 assert_success!(o_prot.write_field_begin(&field_ident_1));
1209 assert_success!(o_prot.write_field_end());
1210
1211 // since this delta > 0 and < 15 it can be encoded as a delta
1212 let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
1213 assert_success!(o_prot.write_field_begin(&field_ident_2));
1214 assert_success!(o_prot.write_field_end());
1215
1216 // since this delta > 0 and < 15 it can be encoded as a delta
1217 let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
1218 assert_success!(o_prot.write_field_begin(&field_ident_3));
1219 assert_success!(o_prot.write_field_end());
1220
1221 // now, finish the struct off
1222 assert_success!(o_prot.write_field_stop());
1223 assert_success!(o_prot.write_struct_end());
1224
Allen George0e22c362017-01-30 07:15:00 -05001225 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001226
1227 // read the struct back
1228 assert_success!(i_prot.read_struct_begin());
1229
1230 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001231 assert_eq!(
1232 read_ident_1,
1233 TFieldIdentifier {
1234 name: None,
1235 ..field_ident_1
1236 }
1237 );
Allen George8b96bfb2016-11-02 08:01:08 -04001238 assert_success!(i_prot.read_field_end());
1239
1240 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001241 assert_eq!(
1242 read_ident_2,
1243 TFieldIdentifier {
1244 name: None,
1245 ..field_ident_2
1246 }
1247 );
Allen George8b96bfb2016-11-02 08:01:08 -04001248 assert_success!(i_prot.read_field_end());
1249
1250 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001251 assert_eq!(
1252 read_ident_3,
1253 TFieldIdentifier {
1254 name: None,
1255 ..field_ident_3
1256 }
1257 );
Allen George8b96bfb2016-11-02 08:01:08 -04001258 assert_success!(i_prot.read_field_end());
1259
1260 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001261 assert_eq!(
1262 read_ident_4,
1263 TFieldIdentifier {
1264 name: None,
1265 field_type: TType::Stop,
1266 id: None,
1267 }
1268 );
Allen George8b96bfb2016-11-02 08:01:08 -04001269
1270 assert_success!(i_prot.read_struct_end());
1271 }
1272
1273 #[test]
1274 fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001275 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001276
1277 // no bytes should be written however
1278 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1279
1280 // write three fields with tiny field ids
1281 // since they're small the field ids will be encoded as deltas
1282
1283 // gets a delta write
1284 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
1285 assert_success!(o_prot.write_field_end());
1286
1287 // since this delta > 0 and < 15 it can be encoded as a delta
1288 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
1289 assert_success!(o_prot.write_field_end());
1290
1291 // since this delta > 0 and < 15 it can be encoded as a delta
1292 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
1293 assert_success!(o_prot.write_field_end());
1294
1295 // now, finish the struct off
1296 assert_success!(o_prot.write_field_stop());
1297 assert_success!(o_prot.write_struct_end());
1298
Allen George7ddbcc02020-11-08 09:51:19 -05001299 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001300 let expected: [u8; 4] = [
1301 0x15, /* field delta (1) | field type */
1302 0x1A, /* field delta (1) | field type */
1303 0x48, /* field delta (4) | field type */
1304 0x00 /* field stop */,
1305 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001306
Allen George0e22c362017-01-30 07:15:00 -05001307 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001308 }
1309
1310 #[test]
1311 fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001312 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001313
1314 // no bytes should be written however
1315 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1316
1317 // write three fields with tiny field ids
1318 // since they're small the field ids will be encoded as deltas
1319
1320 // gets a delta write
1321 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
1322 assert_success!(o_prot.write_field_begin(&field_ident_1));
1323 assert_success!(o_prot.write_field_end());
1324
1325 // since this delta > 0 and < 15 it can be encoded as a delta
1326 let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
1327 assert_success!(o_prot.write_field_begin(&field_ident_2));
1328 assert_success!(o_prot.write_field_end());
1329
1330 // since this delta > 0 and < 15 it can be encoded as a delta
1331 let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
1332 assert_success!(o_prot.write_field_begin(&field_ident_3));
1333 assert_success!(o_prot.write_field_end());
1334
1335 // now, finish the struct off
1336 assert_success!(o_prot.write_field_stop());
1337 assert_success!(o_prot.write_struct_end());
1338
Allen George0e22c362017-01-30 07:15:00 -05001339 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001340
1341 // read the struct back
1342 assert_success!(i_prot.read_struct_begin());
1343
1344 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001345 assert_eq!(
1346 read_ident_1,
1347 TFieldIdentifier {
1348 name: None,
1349 ..field_ident_1
1350 }
1351 );
Allen George8b96bfb2016-11-02 08:01:08 -04001352 assert_success!(i_prot.read_field_end());
1353
1354 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001355 assert_eq!(
1356 read_ident_2,
1357 TFieldIdentifier {
1358 name: None,
1359 ..field_ident_2
1360 }
1361 );
Allen George8b96bfb2016-11-02 08:01:08 -04001362 assert_success!(i_prot.read_field_end());
1363
1364 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001365 assert_eq!(
1366 read_ident_3,
1367 TFieldIdentifier {
1368 name: None,
1369 ..field_ident_3
1370 }
1371 );
Allen George8b96bfb2016-11-02 08:01:08 -04001372 assert_success!(i_prot.read_field_end());
1373
1374 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001375 assert_eq!(
1376 read_ident_4,
1377 TFieldIdentifier {
1378 name: None,
1379 field_type: TType::Stop,
1380 id: None,
1381 }
1382 );
Allen George8b96bfb2016-11-02 08:01:08 -04001383
1384 assert_success!(i_prot.read_struct_end());
1385 }
1386
1387 #[test]
1388 fn must_write_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001389 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001390
1391 // no bytes should be written however
1392 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1393
1394 // write three fields with field ids that cannot be encoded as deltas
1395
1396 // since this is the first field (and it's zero) it gets the full varint write
1397 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
1398 assert_success!(o_prot.write_field_end());
1399
1400 // since this delta is > 15 it is encoded as a zig-zag varint
1401 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
1402 assert_success!(o_prot.write_field_end());
1403
1404 // since this delta is > 15 it is encoded as a zig-zag varint
1405 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
1406 assert_success!(o_prot.write_field_end());
1407
1408 // now, finish the struct off
1409 assert_success!(o_prot.write_field_stop());
1410 assert_success!(o_prot.write_struct_end());
1411
Allen George7ddbcc02020-11-08 09:51:19 -05001412 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001413 let expected: [u8; 8] = [
1414 0x05, /* field type */
1415 0x00, /* first field id */
1416 0x06, /* field type */
1417 0x20, /* zig-zag varint field id */
1418 0x0A, /* field type */
1419 0xC6,
1420 0x01, /* zig-zag varint field id */
1421 0x00 /* field stop */,
1422 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001423
Allen George0e22c362017-01-30 07:15:00 -05001424 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001425 }
1426
1427 #[test]
1428 fn must_round_trip_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001429 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001430
1431 // no bytes should be written however
1432 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1433
1434 // write three fields with field ids that cannot be encoded as deltas
1435
1436 // since this is the first field (and it's zero) it gets the full varint write
1437 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
1438 assert_success!(o_prot.write_field_begin(&field_ident_1));
1439 assert_success!(o_prot.write_field_end());
1440
1441 // since this delta is > 15 it is encoded as a zig-zag varint
1442 let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
1443 assert_success!(o_prot.write_field_begin(&field_ident_2));
1444 assert_success!(o_prot.write_field_end());
1445
1446 // since this delta is > 15 it is encoded as a zig-zag varint
1447 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
1448 assert_success!(o_prot.write_field_begin(&field_ident_3));
1449 assert_success!(o_prot.write_field_end());
1450
1451 // now, finish the struct off
1452 assert_success!(o_prot.write_field_stop());
1453 assert_success!(o_prot.write_struct_end());
1454
Allen George0e22c362017-01-30 07:15:00 -05001455 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001456
1457 // read the struct back
1458 assert_success!(i_prot.read_struct_begin());
1459
1460 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001461 assert_eq!(
1462 read_ident_1,
1463 TFieldIdentifier {
1464 name: None,
1465 ..field_ident_1
1466 }
1467 );
Allen George8b96bfb2016-11-02 08:01:08 -04001468 assert_success!(i_prot.read_field_end());
1469
1470 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001471 assert_eq!(
1472 read_ident_2,
1473 TFieldIdentifier {
1474 name: None,
1475 ..field_ident_2
1476 }
1477 );
Allen George8b96bfb2016-11-02 08:01:08 -04001478 assert_success!(i_prot.read_field_end());
1479
1480 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001481 assert_eq!(
1482 read_ident_3,
1483 TFieldIdentifier {
1484 name: None,
1485 ..field_ident_3
1486 }
1487 );
Allen George8b96bfb2016-11-02 08:01:08 -04001488 assert_success!(i_prot.read_field_end());
1489
1490 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001491 assert_eq!(
1492 read_ident_4,
1493 TFieldIdentifier {
1494 name: None,
1495 field_type: TType::Stop,
1496 id: None,
1497 }
1498 );
Allen George8b96bfb2016-11-02 08:01:08 -04001499
1500 assert_success!(i_prot.read_struct_end());
1501 }
1502
1503 #[test]
1504 fn must_write_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001505 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001506
1507 // no bytes should be written however
1508 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1509
1510 // write three fields with field ids that cannot be encoded as deltas
1511
1512 // since the delta is > 0 and < 15 it gets a delta write
1513 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1514 assert_success!(o_prot.write_field_end());
1515
1516 // since this delta > 0 and < 15 it gets a delta write
1517 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1518 assert_success!(o_prot.write_field_end());
1519
1520 // since this delta is > 15 it is encoded as a zig-zag varint
1521 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
1522 assert_success!(o_prot.write_field_end());
1523
1524 // since this delta is > 15 it is encoded as a zig-zag varint
1525 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
1526 assert_success!(o_prot.write_field_end());
1527
1528 // since this is only 3 up from the previous it is recorded as a delta
1529 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
1530 assert_success!(o_prot.write_field_end());
1531
1532 // now, finish the struct off
1533 assert_success!(o_prot.write_field_stop());
1534 assert_success!(o_prot.write_struct_end());
1535
Allen George7ddbcc02020-11-08 09:51:19 -05001536 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001537 let expected: [u8; 10] = [
1538 0x16, /* field delta (1) | field type */
1539 0x85, /* field delta (8) | field type */
1540 0x0A, /* field type */
1541 0xD0,
1542 0x0F, /* zig-zag varint field id */
1543 0x0A, /* field type */
1544 0xA2,
1545 0x1F, /* zig-zag varint field id */
1546 0x3A, /* field delta (3) | field type */
1547 0x00 /* field stop */,
1548 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001549
Allen George0e22c362017-01-30 07:15:00 -05001550 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001551 }
1552
Allen George7ddbcc02020-11-08 09:51:19 -05001553 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001554 #[test]
1555 fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001556 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001557
1558 // no bytes should be written however
1559 let struct_ident = TStructIdentifier::new("foo");
1560 assert_success!(o_prot.write_struct_begin(&struct_ident));
1561
1562 // write three fields with field ids that cannot be encoded as deltas
1563
1564 // since the delta is > 0 and < 15 it gets a delta write
1565 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1566 assert_success!(o_prot.write_field_begin(&field_ident_1));
1567 assert_success!(o_prot.write_field_end());
1568
1569 // since this delta > 0 and < 15 it gets a delta write
1570 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1571 assert_success!(o_prot.write_field_begin(&field_ident_2));
1572 assert_success!(o_prot.write_field_end());
1573
1574 // since this delta is > 15 it is encoded as a zig-zag varint
1575 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
1576 assert_success!(o_prot.write_field_begin(&field_ident_3));
1577 assert_success!(o_prot.write_field_end());
1578
1579 // since this delta is > 15 it is encoded as a zig-zag varint
1580 let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
1581 assert_success!(o_prot.write_field_begin(&field_ident_4));
1582 assert_success!(o_prot.write_field_end());
1583
1584 // since this is only 3 up from the previous it is recorded as a delta
1585 let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
1586 assert_success!(o_prot.write_field_begin(&field_ident_5));
1587 assert_success!(o_prot.write_field_end());
1588
1589 // now, finish the struct off
1590 assert_success!(o_prot.write_field_stop());
1591 assert_success!(o_prot.write_struct_end());
1592
Allen George0e22c362017-01-30 07:15:00 -05001593 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001594
1595 // read the struct back
1596 assert_success!(i_prot.read_struct_begin());
1597
1598 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001599 assert_eq!(
1600 read_ident_1,
1601 TFieldIdentifier {
1602 name: None,
1603 ..field_ident_1
1604 }
1605 );
Allen George8b96bfb2016-11-02 08:01:08 -04001606 assert_success!(i_prot.read_field_end());
1607
1608 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001609 assert_eq!(
1610 read_ident_2,
1611 TFieldIdentifier {
1612 name: None,
1613 ..field_ident_2
1614 }
1615 );
Allen George8b96bfb2016-11-02 08:01:08 -04001616 assert_success!(i_prot.read_field_end());
1617
1618 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001619 assert_eq!(
1620 read_ident_3,
1621 TFieldIdentifier {
1622 name: None,
1623 ..field_ident_3
1624 }
1625 );
Allen George8b96bfb2016-11-02 08:01:08 -04001626 assert_success!(i_prot.read_field_end());
1627
1628 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001629 assert_eq!(
1630 read_ident_4,
1631 TFieldIdentifier {
1632 name: None,
1633 ..field_ident_4
1634 }
1635 );
Allen George8b96bfb2016-11-02 08:01:08 -04001636 assert_success!(i_prot.read_field_end());
1637
1638 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001639 assert_eq!(
1640 read_ident_5,
1641 TFieldIdentifier {
1642 name: None,
1643 ..field_ident_5
1644 }
1645 );
Allen George8b96bfb2016-11-02 08:01:08 -04001646 assert_success!(i_prot.read_field_end());
1647
1648 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001649 assert_eq!(
1650 read_ident_6,
1651 TFieldIdentifier {
1652 name: None,
1653 field_type: TType::Stop,
1654 id: None,
1655 }
1656 );
Allen George8b96bfb2016-11-02 08:01:08 -04001657
1658 assert_success!(i_prot.read_struct_end());
1659 }
1660
1661 #[test]
1662 fn must_write_nested_structs_0() {
1663 // last field of the containing struct is a delta
1664 // first field of the the contained struct is a delta
1665
Allen George0e22c362017-01-30 07:15:00 -05001666 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001667
1668 // start containing struct
1669 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1670
1671 // containing struct
1672 // since the delta is > 0 and < 15 it gets a delta write
1673 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1674 assert_success!(o_prot.write_field_end());
1675
1676 // containing struct
1677 // since this delta > 0 and < 15 it gets a delta write
1678 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1679 assert_success!(o_prot.write_field_end());
1680
1681 // start contained struct
1682 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1683
1684 // contained struct
1685 // since the delta is > 0 and < 15 it gets a delta write
1686 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
1687 assert_success!(o_prot.write_field_end());
1688
1689 // contained struct
1690 // since this delta > 15 it gets a full write
1691 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1692 assert_success!(o_prot.write_field_end());
1693
1694 // end contained struct
1695 assert_success!(o_prot.write_field_stop());
1696 assert_success!(o_prot.write_struct_end());
1697
1698 // end containing struct
1699 assert_success!(o_prot.write_field_stop());
1700 assert_success!(o_prot.write_struct_end());
1701
Allen George7ddbcc02020-11-08 09:51:19 -05001702 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001703 let expected: [u8; 7] = [
1704 0x16, /* field delta (1) | field type */
1705 0x85, /* field delta (8) | field type */
1706 0x73, /* field delta (7) | field type */
1707 0x07, /* field type */
1708 0x30, /* zig-zag varint field id */
1709 0x00, /* field stop - contained */
1710 0x00 /* field stop - containing */,
1711 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001712
Allen George0e22c362017-01-30 07:15:00 -05001713 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001714 }
1715
Allen George7ddbcc02020-11-08 09:51:19 -05001716 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001717 #[test]
1718 fn must_round_trip_nested_structs_0() {
1719 // last field of the containing struct is a delta
1720 // first field of the the contained struct is a delta
1721
Allen George0e22c362017-01-30 07:15:00 -05001722 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001723
1724 // start containing struct
1725 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1726
1727 // containing struct
1728 // since the delta is > 0 and < 15 it gets a delta write
1729 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1730 assert_success!(o_prot.write_field_begin(&field_ident_1));
1731 assert_success!(o_prot.write_field_end());
1732
1733 // containing struct
1734 // since this delta > 0 and < 15 it gets a delta write
1735 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1736 assert_success!(o_prot.write_field_begin(&field_ident_2));
1737 assert_success!(o_prot.write_field_end());
1738
1739 // start contained struct
1740 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1741
1742 // contained struct
1743 // since the delta is > 0 and < 15 it gets a delta write
1744 let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
1745 assert_success!(o_prot.write_field_begin(&field_ident_3));
1746 assert_success!(o_prot.write_field_end());
1747
1748 // contained struct
1749 // since this delta > 15 it gets a full write
1750 let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
1751 assert_success!(o_prot.write_field_begin(&field_ident_4));
1752 assert_success!(o_prot.write_field_end());
1753
1754 // end contained struct
1755 assert_success!(o_prot.write_field_stop());
1756 assert_success!(o_prot.write_struct_end());
1757
1758 // end containing struct
1759 assert_success!(o_prot.write_field_stop());
1760 assert_success!(o_prot.write_struct_end());
1761
Allen George0e22c362017-01-30 07:15:00 -05001762 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001763
1764 // read containing struct back
1765 assert_success!(i_prot.read_struct_begin());
1766
1767 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001768 assert_eq!(
1769 read_ident_1,
1770 TFieldIdentifier {
1771 name: None,
1772 ..field_ident_1
1773 }
1774 );
Allen George8b96bfb2016-11-02 08:01:08 -04001775 assert_success!(i_prot.read_field_end());
1776
1777 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001778 assert_eq!(
1779 read_ident_2,
1780 TFieldIdentifier {
1781 name: None,
1782 ..field_ident_2
1783 }
1784 );
Allen George8b96bfb2016-11-02 08:01:08 -04001785 assert_success!(i_prot.read_field_end());
1786
1787 // read contained struct back
1788 assert_success!(i_prot.read_struct_begin());
1789
1790 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001791 assert_eq!(
1792 read_ident_3,
1793 TFieldIdentifier {
1794 name: None,
1795 ..field_ident_3
1796 }
1797 );
Allen George8b96bfb2016-11-02 08:01:08 -04001798 assert_success!(i_prot.read_field_end());
1799
1800 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001801 assert_eq!(
1802 read_ident_4,
1803 TFieldIdentifier {
1804 name: None,
1805 ..field_ident_4
1806 }
1807 );
Allen George8b96bfb2016-11-02 08:01:08 -04001808 assert_success!(i_prot.read_field_end());
1809
1810 // end contained struct
1811 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001812 assert_eq!(
1813 read_ident_6,
1814 TFieldIdentifier {
1815 name: None,
1816 field_type: TType::Stop,
1817 id: None,
1818 }
1819 );
Allen George8b96bfb2016-11-02 08:01:08 -04001820 assert_success!(i_prot.read_struct_end());
1821
1822 // end containing struct
1823 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001824 assert_eq!(
1825 read_ident_7,
1826 TFieldIdentifier {
1827 name: None,
1828 field_type: TType::Stop,
1829 id: None,
1830 }
1831 );
Allen George8b96bfb2016-11-02 08:01:08 -04001832 assert_success!(i_prot.read_struct_end());
1833 }
1834
1835 #[test]
1836 fn must_write_nested_structs_1() {
1837 // last field of the containing struct is a delta
1838 // first field of the the contained struct is a full write
1839
Allen George0e22c362017-01-30 07:15:00 -05001840 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001841
1842 // start containing struct
1843 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1844
1845 // containing struct
1846 // since the delta is > 0 and < 15 it gets a delta write
1847 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1848 assert_success!(o_prot.write_field_end());
1849
1850 // containing struct
1851 // since this delta > 0 and < 15 it gets a delta write
1852 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1853 assert_success!(o_prot.write_field_end());
1854
1855 // start contained struct
1856 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1857
1858 // contained struct
1859 // since this delta > 15 it gets a full write
1860 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1861 assert_success!(o_prot.write_field_end());
1862
1863 // contained struct
1864 // since the delta is > 0 and < 15 it gets a delta write
1865 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1866 assert_success!(o_prot.write_field_end());
1867
1868 // end contained struct
1869 assert_success!(o_prot.write_field_stop());
1870 assert_success!(o_prot.write_struct_end());
1871
1872 // end containing struct
1873 assert_success!(o_prot.write_field_stop());
1874 assert_success!(o_prot.write_struct_end());
1875
Allen George7ddbcc02020-11-08 09:51:19 -05001876 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001877 let expected: [u8; 7] = [
1878 0x16, /* field delta (1) | field type */
1879 0x85, /* field delta (8) | field type */
1880 0x07, /* field type */
1881 0x30, /* zig-zag varint field id */
1882 0x33, /* field delta (3) | field type */
1883 0x00, /* field stop - contained */
1884 0x00 /* field stop - containing */,
1885 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001886
Allen George0e22c362017-01-30 07:15:00 -05001887 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001888 }
1889
Allen George7ddbcc02020-11-08 09:51:19 -05001890 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04001891 #[test]
1892 fn must_round_trip_nested_structs_1() {
1893 // last field of the containing struct is a delta
1894 // first field of the the contained struct is a full write
1895
Allen George0e22c362017-01-30 07:15:00 -05001896 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001897
1898 // start containing struct
1899 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1900
1901 // containing struct
1902 // since the delta is > 0 and < 15 it gets a delta write
1903 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1904 assert_success!(o_prot.write_field_begin(&field_ident_1));
1905 assert_success!(o_prot.write_field_end());
1906
1907 // containing struct
1908 // since this delta > 0 and < 15 it gets a delta write
1909 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1910 assert_success!(o_prot.write_field_begin(&field_ident_2));
1911 assert_success!(o_prot.write_field_end());
1912
1913 // start contained struct
1914 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1915
1916 // contained struct
1917 // since this delta > 15 it gets a full write
1918 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
1919 assert_success!(o_prot.write_field_begin(&field_ident_3));
1920 assert_success!(o_prot.write_field_end());
1921
1922 // contained struct
1923 // since the delta is > 0 and < 15 it gets a delta write
1924 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
1925 assert_success!(o_prot.write_field_begin(&field_ident_4));
1926 assert_success!(o_prot.write_field_end());
1927
1928 // end contained struct
1929 assert_success!(o_prot.write_field_stop());
1930 assert_success!(o_prot.write_struct_end());
1931
1932 // end containing struct
1933 assert_success!(o_prot.write_field_stop());
1934 assert_success!(o_prot.write_struct_end());
1935
Allen George0e22c362017-01-30 07:15:00 -05001936 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001937
1938 // read containing struct back
1939 assert_success!(i_prot.read_struct_begin());
1940
1941 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001942 assert_eq!(
1943 read_ident_1,
1944 TFieldIdentifier {
1945 name: None,
1946 ..field_ident_1
1947 }
1948 );
Allen George8b96bfb2016-11-02 08:01:08 -04001949 assert_success!(i_prot.read_field_end());
1950
1951 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001952 assert_eq!(
1953 read_ident_2,
1954 TFieldIdentifier {
1955 name: None,
1956 ..field_ident_2
1957 }
1958 );
Allen George8b96bfb2016-11-02 08:01:08 -04001959 assert_success!(i_prot.read_field_end());
1960
1961 // read contained struct back
1962 assert_success!(i_prot.read_struct_begin());
1963
1964 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001965 assert_eq!(
1966 read_ident_3,
1967 TFieldIdentifier {
1968 name: None,
1969 ..field_ident_3
1970 }
1971 );
Allen George8b96bfb2016-11-02 08:01:08 -04001972 assert_success!(i_prot.read_field_end());
1973
1974 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001975 assert_eq!(
1976 read_ident_4,
1977 TFieldIdentifier {
1978 name: None,
1979 ..field_ident_4
1980 }
1981 );
Allen George8b96bfb2016-11-02 08:01:08 -04001982 assert_success!(i_prot.read_field_end());
1983
1984 // end contained struct
1985 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001986 assert_eq!(
1987 read_ident_6,
1988 TFieldIdentifier {
1989 name: None,
1990 field_type: TType::Stop,
1991 id: None,
1992 }
1993 );
Allen George8b96bfb2016-11-02 08:01:08 -04001994 assert_success!(i_prot.read_struct_end());
1995
1996 // end containing struct
1997 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001998 assert_eq!(
1999 read_ident_7,
2000 TFieldIdentifier {
2001 name: None,
2002 field_type: TType::Stop,
2003 id: None,
2004 }
2005 );
Allen George8b96bfb2016-11-02 08:01:08 -04002006 assert_success!(i_prot.read_struct_end());
2007 }
2008
2009 #[test]
2010 fn must_write_nested_structs_2() {
2011 // last field of the containing struct is a full write
2012 // first field of the the contained struct is a delta write
2013
Allen George0e22c362017-01-30 07:15:00 -05002014 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002015
2016 // start containing struct
2017 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2018
2019 // containing struct
2020 // since the delta is > 0 and < 15 it gets a delta write
2021 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2022 assert_success!(o_prot.write_field_end());
2023
2024 // containing struct
2025 // since this delta > 15 it gets a full write
2026 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2027 assert_success!(o_prot.write_field_end());
2028
2029 // start contained struct
2030 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2031
2032 // contained struct
2033 // since this delta > 0 and < 15 it gets a delta write
2034 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
2035 assert_success!(o_prot.write_field_end());
2036
2037 // contained struct
2038 // since the delta is > 0 and < 15 it gets a delta write
2039 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
2040 assert_success!(o_prot.write_field_end());
2041
2042 // end contained struct
2043 assert_success!(o_prot.write_field_stop());
2044 assert_success!(o_prot.write_struct_end());
2045
2046 // end containing struct
2047 assert_success!(o_prot.write_field_stop());
2048 assert_success!(o_prot.write_struct_end());
2049
Allen George7ddbcc02020-11-08 09:51:19 -05002050 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002051 let expected: [u8; 7] = [
2052 0x16, /* field delta (1) | field type */
2053 0x08, /* field type */
2054 0x2A, /* zig-zag varint field id */
2055 0x77, /* field delta(7) | field type */
2056 0x33, /* field delta (3) | field type */
2057 0x00, /* field stop - contained */
2058 0x00 /* field stop - containing */,
2059 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002060
Allen George0e22c362017-01-30 07:15:00 -05002061 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002062 }
2063
Allen George7ddbcc02020-11-08 09:51:19 -05002064 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002065 #[test]
2066 fn must_round_trip_nested_structs_2() {
Allen George0e22c362017-01-30 07:15:00 -05002067 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002068
2069 // start containing struct
2070 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2071
2072 // containing struct
2073 // since the delta is > 0 and < 15 it gets a delta write
2074 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2075 assert_success!(o_prot.write_field_begin(&field_ident_1));
2076 assert_success!(o_prot.write_field_end());
2077
2078 // containing struct
2079 // since this delta > 15 it gets a full write
2080 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2081 assert_success!(o_prot.write_field_begin(&field_ident_2));
2082 assert_success!(o_prot.write_field_end());
2083
2084 // start contained struct
2085 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2086
2087 // contained struct
2088 // since this delta > 0 and < 15 it gets a delta write
2089 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
2090 assert_success!(o_prot.write_field_begin(&field_ident_3));
2091 assert_success!(o_prot.write_field_end());
2092
2093 // contained struct
2094 // since the delta is > 0 and < 15 it gets a delta write
2095 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
2096 assert_success!(o_prot.write_field_begin(&field_ident_4));
2097 assert_success!(o_prot.write_field_end());
2098
2099 // end contained struct
2100 assert_success!(o_prot.write_field_stop());
2101 assert_success!(o_prot.write_struct_end());
2102
2103 // end containing struct
2104 assert_success!(o_prot.write_field_stop());
2105 assert_success!(o_prot.write_struct_end());
2106
Allen George0e22c362017-01-30 07:15:00 -05002107 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002108
2109 // read containing struct back
2110 assert_success!(i_prot.read_struct_begin());
2111
2112 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002113 assert_eq!(
2114 read_ident_1,
2115 TFieldIdentifier {
2116 name: None,
2117 ..field_ident_1
2118 }
2119 );
Allen George8b96bfb2016-11-02 08:01:08 -04002120 assert_success!(i_prot.read_field_end());
2121
2122 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002123 assert_eq!(
2124 read_ident_2,
2125 TFieldIdentifier {
2126 name: None,
2127 ..field_ident_2
2128 }
2129 );
Allen George8b96bfb2016-11-02 08:01:08 -04002130 assert_success!(i_prot.read_field_end());
2131
2132 // read contained struct back
2133 assert_success!(i_prot.read_struct_begin());
2134
2135 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002136 assert_eq!(
2137 read_ident_3,
2138 TFieldIdentifier {
2139 name: None,
2140 ..field_ident_3
2141 }
2142 );
Allen George8b96bfb2016-11-02 08:01:08 -04002143 assert_success!(i_prot.read_field_end());
2144
2145 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002146 assert_eq!(
2147 read_ident_4,
2148 TFieldIdentifier {
2149 name: None,
2150 ..field_ident_4
2151 }
2152 );
Allen George8b96bfb2016-11-02 08:01:08 -04002153 assert_success!(i_prot.read_field_end());
2154
2155 // end contained struct
2156 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002157 assert_eq!(
2158 read_ident_6,
2159 TFieldIdentifier {
2160 name: None,
2161 field_type: TType::Stop,
2162 id: None,
2163 }
2164 );
Allen George8b96bfb2016-11-02 08:01:08 -04002165 assert_success!(i_prot.read_struct_end());
2166
2167 // end containing struct
2168 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002169 assert_eq!(
2170 read_ident_7,
2171 TFieldIdentifier {
2172 name: None,
2173 field_type: TType::Stop,
2174 id: None,
2175 }
2176 );
Allen George8b96bfb2016-11-02 08:01:08 -04002177 assert_success!(i_prot.read_struct_end());
2178 }
2179
2180 #[test]
2181 fn must_write_nested_structs_3() {
2182 // last field of the containing struct is a full write
2183 // first field of the the contained struct is a full write
2184
Allen George0e22c362017-01-30 07:15:00 -05002185 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002186
2187 // start containing struct
2188 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2189
2190 // containing struct
2191 // since the delta is > 0 and < 15 it gets a delta write
2192 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2193 assert_success!(o_prot.write_field_end());
2194
2195 // containing struct
2196 // since this delta > 15 it gets a full write
2197 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2198 assert_success!(o_prot.write_field_end());
2199
2200 // start contained struct
2201 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2202
2203 // contained struct
2204 // since this delta > 15 it gets a full write
2205 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
2206 assert_success!(o_prot.write_field_end());
2207
2208 // contained struct
2209 // since the delta is > 0 and < 15 it gets a delta write
2210 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
2211 assert_success!(o_prot.write_field_end());
2212
2213 // end contained struct
2214 assert_success!(o_prot.write_field_stop());
2215 assert_success!(o_prot.write_struct_end());
2216
2217 // end containing struct
2218 assert_success!(o_prot.write_field_stop());
2219 assert_success!(o_prot.write_struct_end());
2220
Allen George7ddbcc02020-11-08 09:51:19 -05002221 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002222 let expected: [u8; 8] = [
2223 0x16, /* field delta (1) | field type */
2224 0x08, /* field type */
2225 0x2A, /* zig-zag varint field id */
2226 0x07, /* field type */
2227 0x2A, /* zig-zag varint field id */
2228 0x63, /* field delta (6) | field type */
2229 0x00, /* field stop - contained */
2230 0x00 /* field stop - containing */,
2231 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002232
Allen George0e22c362017-01-30 07:15:00 -05002233 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002234 }
2235
Allen George7ddbcc02020-11-08 09:51:19 -05002236 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002237 #[test]
2238 fn must_round_trip_nested_structs_3() {
2239 // last field of the containing struct is a full write
2240 // first field of the the contained struct is a full write
2241
Allen George0e22c362017-01-30 07:15:00 -05002242 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002243
2244 // start containing struct
2245 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2246
2247 // containing struct
2248 // since the delta is > 0 and < 15 it gets a delta write
2249 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2250 assert_success!(o_prot.write_field_begin(&field_ident_1));
2251 assert_success!(o_prot.write_field_end());
2252
2253 // containing struct
2254 // since this delta > 15 it gets a full write
2255 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2256 assert_success!(o_prot.write_field_begin(&field_ident_2));
2257 assert_success!(o_prot.write_field_end());
2258
2259 // start contained struct
2260 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2261
2262 // contained struct
2263 // since this delta > 15 it gets a full write
2264 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
2265 assert_success!(o_prot.write_field_begin(&field_ident_3));
2266 assert_success!(o_prot.write_field_end());
2267
2268 // contained struct
2269 // since the delta is > 0 and < 15 it gets a delta write
2270 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2271 assert_success!(o_prot.write_field_begin(&field_ident_4));
2272 assert_success!(o_prot.write_field_end());
2273
2274 // end contained struct
2275 assert_success!(o_prot.write_field_stop());
2276 assert_success!(o_prot.write_struct_end());
2277
2278 // end containing struct
2279 assert_success!(o_prot.write_field_stop());
2280 assert_success!(o_prot.write_struct_end());
2281
Allen George0e22c362017-01-30 07:15:00 -05002282 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002283
2284 // read containing struct back
2285 assert_success!(i_prot.read_struct_begin());
2286
2287 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002288 assert_eq!(
2289 read_ident_1,
2290 TFieldIdentifier {
2291 name: None,
2292 ..field_ident_1
2293 }
2294 );
Allen George8b96bfb2016-11-02 08:01:08 -04002295 assert_success!(i_prot.read_field_end());
2296
2297 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002298 assert_eq!(
2299 read_ident_2,
2300 TFieldIdentifier {
2301 name: None,
2302 ..field_ident_2
2303 }
2304 );
Allen George8b96bfb2016-11-02 08:01:08 -04002305 assert_success!(i_prot.read_field_end());
2306
2307 // read contained struct back
2308 assert_success!(i_prot.read_struct_begin());
2309
2310 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002311 assert_eq!(
2312 read_ident_3,
2313 TFieldIdentifier {
2314 name: None,
2315 ..field_ident_3
2316 }
2317 );
Allen George8b96bfb2016-11-02 08:01:08 -04002318 assert_success!(i_prot.read_field_end());
2319
2320 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002321 assert_eq!(
2322 read_ident_4,
2323 TFieldIdentifier {
2324 name: None,
2325 ..field_ident_4
2326 }
2327 );
Allen George8b96bfb2016-11-02 08:01:08 -04002328 assert_success!(i_prot.read_field_end());
2329
2330 // end contained struct
2331 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002332 assert_eq!(
2333 read_ident_6,
2334 TFieldIdentifier {
2335 name: None,
2336 field_type: TType::Stop,
2337 id: None,
2338 }
2339 );
Allen George8b96bfb2016-11-02 08:01:08 -04002340 assert_success!(i_prot.read_struct_end());
2341
2342 // end containing struct
2343 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002344 assert_eq!(
2345 read_ident_7,
2346 TFieldIdentifier {
2347 name: None,
2348 field_type: TType::Stop,
2349 id: None,
2350 }
2351 );
Allen George8b96bfb2016-11-02 08:01:08 -04002352 assert_success!(i_prot.read_struct_end());
2353 }
2354
2355 #[test]
2356 fn must_write_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002357 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002358
2359 // no bytes should be written however
2360 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2361
2362 // write three fields with field ids that cannot be encoded as deltas
2363
2364 // since the delta is > 0 and < 16 it gets a delta write
2365 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2366 assert_success!(o_prot.write_bool(true));
2367 assert_success!(o_prot.write_field_end());
2368
2369 // since this delta > 0 and < 15 it gets a delta write
2370 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
2371 assert_success!(o_prot.write_bool(false));
2372 assert_success!(o_prot.write_field_end());
2373
2374 // since this delta > 15 it gets a full write
2375 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
2376 assert_success!(o_prot.write_bool(true));
2377 assert_success!(o_prot.write_field_end());
2378
2379 // since this delta > 15 it gets a full write
2380 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
2381 assert_success!(o_prot.write_bool(false));
2382 assert_success!(o_prot.write_field_end());
2383
2384 // now, finish the struct off
2385 assert_success!(o_prot.write_field_stop());
2386 assert_success!(o_prot.write_struct_end());
2387
Allen George7ddbcc02020-11-08 09:51:19 -05002388 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05002389 let expected: [u8; 7] = [
2390 0x11, /* field delta (1) | true */
2391 0x82, /* field delta (8) | false */
2392 0x01, /* true */
2393 0x34, /* field id */
2394 0x02, /* false */
2395 0x5A, /* field id */
2396 0x00 /* stop field */,
2397 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002398
Allen George0e22c362017-01-30 07:15:00 -05002399 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002400 }
2401
Allen George7ddbcc02020-11-08 09:51:19 -05002402 #[allow(clippy::cognitive_complexity)]
Allen George8b96bfb2016-11-02 08:01:08 -04002403 #[test]
2404 fn must_round_trip_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05002405 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002406
2407 // no bytes should be written however
2408 let struct_ident = TStructIdentifier::new("foo");
2409 assert_success!(o_prot.write_struct_begin(&struct_ident));
2410
2411 // write two fields
2412
2413 // since the delta is > 0 and < 16 it gets a delta write
2414 let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
2415 assert_success!(o_prot.write_field_begin(&field_ident_1));
2416 assert_success!(o_prot.write_bool(true));
2417 assert_success!(o_prot.write_field_end());
2418
2419 // since this delta > 0 and < 15 it gets a delta write
2420 let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
2421 assert_success!(o_prot.write_field_begin(&field_ident_2));
2422 assert_success!(o_prot.write_bool(false));
2423 assert_success!(o_prot.write_field_end());
2424
2425 // since this delta > 15 it gets a full write
2426 let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
2427 assert_success!(o_prot.write_field_begin(&field_ident_3));
2428 assert_success!(o_prot.write_bool(true));
2429 assert_success!(o_prot.write_field_end());
2430
2431 // since this delta > 15 it gets a full write
2432 let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
2433 assert_success!(o_prot.write_field_begin(&field_ident_4));
2434 assert_success!(o_prot.write_bool(false));
2435 assert_success!(o_prot.write_field_end());
2436
2437 // now, finish the struct off
2438 assert_success!(o_prot.write_field_stop());
2439 assert_success!(o_prot.write_struct_end());
2440
Allen George0e22c362017-01-30 07:15:00 -05002441 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002442
2443 // read the struct back
2444 assert_success!(i_prot.read_struct_begin());
2445
2446 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002447 assert_eq!(
2448 read_ident_1,
2449 TFieldIdentifier {
2450 name: None,
2451 ..field_ident_1
2452 }
2453 );
Allen George8b96bfb2016-11-02 08:01:08 -04002454 let read_value_1 = assert_success!(i_prot.read_bool());
2455 assert_eq!(read_value_1, true);
2456 assert_success!(i_prot.read_field_end());
2457
2458 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002459 assert_eq!(
2460 read_ident_2,
2461 TFieldIdentifier {
2462 name: None,
2463 ..field_ident_2
2464 }
2465 );
Allen George8b96bfb2016-11-02 08:01:08 -04002466 let read_value_2 = assert_success!(i_prot.read_bool());
2467 assert_eq!(read_value_2, false);
2468 assert_success!(i_prot.read_field_end());
2469
2470 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002471 assert_eq!(
2472 read_ident_3,
2473 TFieldIdentifier {
2474 name: None,
2475 ..field_ident_3
2476 }
2477 );
Allen George8b96bfb2016-11-02 08:01:08 -04002478 let read_value_3 = assert_success!(i_prot.read_bool());
2479 assert_eq!(read_value_3, true);
2480 assert_success!(i_prot.read_field_end());
2481
2482 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002483 assert_eq!(
2484 read_ident_4,
2485 TFieldIdentifier {
2486 name: None,
2487 ..field_ident_4
2488 }
2489 );
Allen George8b96bfb2016-11-02 08:01:08 -04002490 let read_value_4 = assert_success!(i_prot.read_bool());
2491 assert_eq!(read_value_4, false);
2492 assert_success!(i_prot.read_field_end());
2493
2494 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002495 assert_eq!(
2496 read_ident_5,
2497 TFieldIdentifier {
2498 name: None,
2499 field_type: TType::Stop,
2500 id: None,
2501 }
2502 );
Allen George8b96bfb2016-11-02 08:01:08 -04002503
2504 assert_success!(i_prot.read_struct_end());
2505 }
2506
2507 #[test]
2508 #[should_panic]
2509 fn must_fail_if_write_field_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002510 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002511 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2512 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2513 o_prot.write_field_end().unwrap();
2514 }
2515
2516 #[test]
2517 #[should_panic]
2518 fn must_fail_if_write_stop_field_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002519 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002520 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2521 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2522 o_prot.write_field_stop().unwrap();
2523 }
2524
2525 #[test]
2526 #[should_panic]
2527 fn must_fail_if_write_struct_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002528 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002529 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2530 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2531 o_prot.write_struct_end().unwrap();
2532 }
2533
2534 #[test]
2535 #[should_panic]
2536 fn must_fail_if_write_struct_end_without_any_fields() {
Allen George0e22c362017-01-30 07:15:00 -05002537 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002538 o_prot.write_struct_end().unwrap();
2539 }
2540
2541 #[test]
2542 fn must_write_field_end() {
2543 assert_no_write(|o| o.write_field_end());
2544 }
2545
2546 #[test]
2547 fn must_write_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002548 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002549
2550 assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
2551
2552 let expected: [u8; 1] = [0x46 /* size | elem_type */];
2553
Allen George0e22c362017-01-30 07:15:00 -05002554 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002555 }
2556
2557 #[test]
2558 fn must_round_trip_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002559 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002560
2561 let ident = TListIdentifier::new(TType::I08, 10);
2562
2563 assert_success!(o_prot.write_list_begin(&ident));
2564
Allen George0e22c362017-01-30 07:15:00 -05002565 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002566
2567 let res = assert_success!(i_prot.read_list_begin());
2568 assert_eq!(&res, &ident);
2569 }
2570
2571 #[test]
2572 fn must_write_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002573 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002574
2575 let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
2576 assert!(res.is_ok());
2577
Allen George0e22c362017-01-30 07:15:00 -05002578 let expected: [u8; 3] = [
2579 0xF9, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002580 0x8F, 0x4E, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002581 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002582
Allen George0e22c362017-01-30 07:15:00 -05002583 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002584 }
2585
2586 #[test]
2587 fn must_round_trip_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002588 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002589
2590 let ident = TListIdentifier::new(TType::Set, 47381);
2591
2592 assert_success!(o_prot.write_list_begin(&ident));
2593
Allen George0e22c362017-01-30 07:15:00 -05002594 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002595
2596 let res = assert_success!(i_prot.read_list_begin());
2597 assert_eq!(&res, &ident);
2598 }
2599
2600 #[test]
2601 fn must_write_list_end() {
2602 assert_no_write(|o| o.write_list_end());
2603 }
2604
2605 #[test]
2606 fn must_write_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002607 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002608
2609 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
2610
2611 let expected: [u8; 1] = [0x2C /* size | elem_type */];
2612
Allen George0e22c362017-01-30 07:15:00 -05002613 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002614 }
2615
2616 #[test]
2617 fn must_round_trip_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002618 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002619
2620 let ident = TSetIdentifier::new(TType::I16, 7);
2621
2622 assert_success!(o_prot.write_set_begin(&ident));
2623
Allen George0e22c362017-01-30 07:15:00 -05002624 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002625
2626 let res = assert_success!(i_prot.read_set_begin());
2627 assert_eq!(&res, &ident);
2628 }
2629
2630 #[test]
2631 fn must_write_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002632 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002633
2634 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
2635
Allen George0e22c362017-01-30 07:15:00 -05002636 let expected: [u8; 4] = [
2637 0xF7, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002638 0xD3, 0xBA, 0x01, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002639 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002640
Allen George0e22c362017-01-30 07:15:00 -05002641 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002642 }
2643
2644 #[test]
2645 fn must_round_trip_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002646 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002647
Allen George7ddbcc02020-11-08 09:51:19 -05002648 let ident = TSetIdentifier::new(TType::Map, 3_928_429);
Allen George8b96bfb2016-11-02 08:01:08 -04002649
2650 assert_success!(o_prot.write_set_begin(&ident));
2651
Allen George0e22c362017-01-30 07:15:00 -05002652 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002653
2654 let res = assert_success!(i_prot.read_set_begin());
2655 assert_eq!(&res, &ident);
2656 }
2657
2658 #[test]
2659 fn must_write_set_end() {
2660 assert_no_write(|o| o.write_set_end());
2661 }
2662
2663 #[test]
2664 fn must_write_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002665 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002666
2667 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
2668
2669 let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything
2670
Allen George0e22c362017-01-30 07:15:00 -05002671 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002672 }
2673
2674 #[test]
2675 fn must_read_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002676 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002677
2678 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
2679
Allen George0e22c362017-01-30 07:15:00 -05002680 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002681
2682 let res = assert_success!(i_prot.read_map_begin());
Allen George0e22c362017-01-30 07:15:00 -05002683 assert_eq!(
2684 &res,
2685 &TMapIdentifier {
Allen Georgeef7a1892018-12-16 18:01:37 -05002686 key_type: None,
2687 value_type: None,
2688 size: 0,
2689 }
Allen George0e22c362017-01-30 07:15:00 -05002690 );
Allen George8b96bfb2016-11-02 08:01:08 -04002691 }
2692
2693 #[test]
2694 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002695 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002696
Allen Georgeef7a1892018-12-16 18:01:37 -05002697 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
2698 TType::Double,
2699 TType::String,
2700 238
2701 )));
Allen George8b96bfb2016-11-02 08:01:08 -04002702
Allen George0e22c362017-01-30 07:15:00 -05002703 let expected: [u8; 3] = [
Allen Georgeef7a1892018-12-16 18:01:37 -05002704 0xEE, 0x01, /* size as varint */
2705 0x78, /* key type | val type */
Allen George0e22c362017-01-30 07:15:00 -05002706 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002707
Allen George0e22c362017-01-30 07:15:00 -05002708 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002709 }
2710
2711 #[test]
2712 fn must_round_trip_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002713 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002714
Allen George7ddbcc02020-11-08 09:51:19 -05002715 let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349);
Allen George8b96bfb2016-11-02 08:01:08 -04002716
2717 assert_success!(o_prot.write_map_begin(&ident));
2718
Allen George0e22c362017-01-30 07:15:00 -05002719 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002720
2721 let res = assert_success!(i_prot.read_map_begin());
2722 assert_eq!(&res, &ident);
2723 }
2724
2725 #[test]
2726 fn must_write_map_end() {
2727 assert_no_write(|o| o.write_map_end());
2728 }
2729
2730 #[test]
2731 fn must_write_map_with_bool_key_and_value() {
Allen George0e22c362017-01-30 07:15:00 -05002732 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002733
2734 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
2735 assert_success!(o_prot.write_bool(true));
2736 assert_success!(o_prot.write_bool(false));
2737 assert_success!(o_prot.write_map_end());
2738
Allen George0e22c362017-01-30 07:15:00 -05002739 let expected: [u8; 4] = [
2740 0x01, /* size as varint */
2741 0x11, /* key type | val type */
2742 0x01, /* key: true */
Allen Georgeef7a1892018-12-16 18:01:37 -05002743 0x02, /* val: false */
Allen George0e22c362017-01-30 07:15:00 -05002744 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002745
Allen George0e22c362017-01-30 07:15:00 -05002746 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002747 }
2748
2749 #[test]
2750 fn must_round_trip_map_with_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002751 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002752
2753 let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
2754 assert_success!(o_prot.write_map_begin(&map_ident));
2755 assert_success!(o_prot.write_bool(true));
2756 assert_success!(o_prot.write_bool(false));
2757 assert_success!(o_prot.write_bool(false));
2758 assert_success!(o_prot.write_bool(true));
2759 assert_success!(o_prot.write_map_end());
2760
Allen George0e22c362017-01-30 07:15:00 -05002761 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002762
2763 // map header
2764 let rcvd_ident = assert_success!(i_prot.read_map_begin());
2765 assert_eq!(&rcvd_ident, &map_ident);
2766 // key 1
2767 let b = assert_success!(i_prot.read_bool());
2768 assert_eq!(b, true);
2769 // val 1
2770 let b = assert_success!(i_prot.read_bool());
2771 assert_eq!(b, false);
2772 // key 2
2773 let b = assert_success!(i_prot.read_bool());
2774 assert_eq!(b, false);
2775 // val 2
2776 let b = assert_success!(i_prot.read_bool());
2777 assert_eq!(b, true);
2778 // map end
2779 assert_success!(i_prot.read_map_end());
2780 }
2781
2782 #[test]
2783 fn must_read_map_end() {
Allen George0e22c362017-01-30 07:15:00 -05002784 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002785 assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
2786 }
2787
Allen Georgeef7a1892018-12-16 18:01:37 -05002788 fn test_objects() -> (
2789 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2790 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2791 ) {
Allen George0e22c362017-01-30 07:15:00 -05002792 let mem = TBufferChannel::with_capacity(80, 80);
Allen George8b96bfb2016-11-02 08:01:08 -04002793
Allen George0e22c362017-01-30 07:15:00 -05002794 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -04002795
Allen George0e22c362017-01-30 07:15:00 -05002796 let i_prot = TCompactInputProtocol::new(r_mem);
2797 let o_prot = TCompactOutputProtocol::new(w_mem);
Allen George8b96bfb2016-11-02 08:01:08 -04002798
Allen George0e22c362017-01-30 07:15:00 -05002799 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -04002800 }
2801
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002802 #[test]
2803 fn must_read_write_double() {
2804 let (mut i_prot, mut o_prot) = test_objects();
2805
Allen George7ddbcc02020-11-08 09:51:19 -05002806 #[allow(clippy::approx_constant)]
2807 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002808 o_prot.write_double(double).unwrap();
2809 copy_write_buffer_to_read_buffer!(o_prot);
2810
Allen George7ddbcc02020-11-08 09:51:19 -05002811 let read_double = i_prot.read_double().unwrap();
2812 assert!(read_double - double < std::f64::EPSILON);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002813 }
2814
2815 #[test]
2816 fn must_encode_double_as_other_langs() {
2817 let (_, mut o_prot) = test_objects();
2818 let expected = [24, 45, 68, 84, 251, 33, 9, 64];
2819
Allen George7ddbcc02020-11-08 09:51:19 -05002820 #[allow(clippy::approx_constant)]
2821 let double = 3.141_592_653_589_793;
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002822 o_prot.write_double(double).unwrap();
2823
2824 assert_eq_written_bytes!(o_prot, expected);
Marcin Pajkowskib34680f2019-12-02 10:29:16 +01002825 }
2826
Allen George0e22c362017-01-30 07:15:00 -05002827 fn assert_no_write<F>(mut write_fn: F)
2828 where
Allen Georgeb0d14132020-03-29 11:48:55 -04002829 F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> crate::Result<()>,
Allen George0e22c362017-01-30 07:15:00 -05002830 {
2831 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002832 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -05002833 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -04002834 }
2835}