blob: df5edaa82787c6751792684f4c43939dc403c04c [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
18use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
19use integer_encoding::{VarIntReader, VarIntWriter};
Allen George8b96bfb2016-11-02 08:01:08 -040020use std::convert::From;
Vadim Chekand3355af2018-01-05 23:12:47 -050021use std::io;
Allen Georgeef7a1892018-12-16 18:01:37 -050022use try_from::TryFrom;
Allen George8b96bfb2016-11-02 08:01:08 -040023
Allen Georgeef7a1892018-12-16 18:01:37 -050024use super::{
25 TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier, TMapIdentifier,
26 TMessageIdentifier, TMessageType,
27};
Allen George8b96bfb2016-11-02 08:01:08 -040028use super::{TOutputProtocol, TOutputProtocolFactory, TSetIdentifier, TStructIdentifier, TType};
Allen Georgeef7a1892018-12-16 18:01:37 -050029use transport::{TReadTransport, TWriteTransport};
Allen George8b96bfb2016-11-02 08:01:08 -040030
31const COMPACT_PROTOCOL_ID: u8 = 0x82;
32const COMPACT_VERSION: u8 = 0x01;
33const COMPACT_VERSION_MASK: u8 = 0x1F;
34
35/// Read messages encoded in the Thrift compact protocol.
36///
37/// # Examples
38///
39/// Create and use a `TCompactInputProtocol`.
40///
41/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -040042/// use thrift::protocol::{TCompactInputProtocol, TInputProtocol};
Allen George0e22c362017-01-30 07:15:00 -050043/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -040044///
Allen George0e22c362017-01-30 07:15:00 -050045/// let mut channel = TTcpChannel::new();
46/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040047///
Allen George0e22c362017-01-30 07:15:00 -050048/// let mut protocol = TCompactInputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -040049///
Allen George0e22c362017-01-30 07:15:00 -050050/// let recvd_bool = protocol.read_bool().unwrap();
51/// let recvd_string = protocol.read_string().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040052/// ```
Allen George0e22c362017-01-30 07:15:00 -050053#[derive(Debug)]
54pub struct TCompactInputProtocol<T>
55where
56 T: TReadTransport,
57{
Allen George8b96bfb2016-11-02 08:01:08 -040058 // Identifier of the last field deserialized for a struct.
59 last_read_field_id: i16,
60 // Stack of the last read field ids (a new entry is added each time a nested struct is read).
61 read_field_id_stack: Vec<i16>,
62 // Boolean value for a field.
63 // Saved because boolean fields and their value are encoded in a single byte,
64 // and reading the field only occurs after the field id is read.
65 pending_read_bool_value: Option<bool>,
66 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -050067 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -040068}
69
Allen George0e22c362017-01-30 07:15:00 -050070impl<T> TCompactInputProtocol<T>
71where
72 T: TReadTransport,
73{
Allen George8b96bfb2016-11-02 08:01:08 -040074 /// Create a `TCompactInputProtocol` that reads bytes from `transport`.
Allen George0e22c362017-01-30 07:15:00 -050075 pub fn new(transport: T) -> TCompactInputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -040076 TCompactInputProtocol {
77 last_read_field_id: 0,
78 read_field_id_stack: Vec::new(),
79 pending_read_bool_value: None,
80 transport: transport,
81 }
82 }
83
84 fn read_list_set_begin(&mut self) -> ::Result<(TType, i32)> {
85 let header = self.read_byte()?;
86 let element_type = collection_u8_to_type(header & 0x0F)?;
87
88 let element_count;
89 let possible_element_count = (header & 0xF0) >> 4;
90 if possible_element_count != 15 {
91 // high bits set high if count and type encoded separately
92 element_count = possible_element_count as i32;
93 } else {
Allen George0e22c362017-01-30 07:15:00 -050094 element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -040095 }
96
97 Ok((element_type, element_count))
98 }
99}
100
Allen George0e22c362017-01-30 07:15:00 -0500101impl<T> TInputProtocol for TCompactInputProtocol<T>
102where
103 T: TReadTransport,
104{
Allen George8b96bfb2016-11-02 08:01:08 -0400105 fn read_message_begin(&mut self) -> ::Result<TMessageIdentifier> {
106 let compact_id = self.read_byte()?;
107 if compact_id != COMPACT_PROTOCOL_ID {
Allen Georgeef7a1892018-12-16 18:01:37 -0500108 Err(::Error::Protocol(::ProtocolError {
109 kind: ::ProtocolErrorKind::BadVersion,
110 message: format!("invalid compact protocol header {:?}", compact_id),
111 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400112 } else {
113 Ok(())
114 }?;
115
116 let type_and_byte = self.read_byte()?;
117 let received_version = type_and_byte & COMPACT_VERSION_MASK;
118 if received_version != COMPACT_VERSION {
Allen Georgeef7a1892018-12-16 18:01:37 -0500119 Err(::Error::Protocol(::ProtocolError {
120 kind: ::ProtocolErrorKind::BadVersion,
121 message: format!(
122 "cannot process compact protocol version {:?}",
123 received_version
Allen George0e22c362017-01-30 07:15:00 -0500124 ),
Allen Georgeef7a1892018-12-16 18:01:37 -0500125 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400126 } else {
127 Ok(())
128 }?;
129
130 // NOTE: unsigned right shift will pad with 0s
131 let message_type: TMessageType = TMessageType::try_from(type_and_byte >> 5)?;
132 let sequence_number = self.read_i32()?;
133 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
144 fn read_message_end(&mut self) -> ::Result<()> {
145 Ok(())
146 }
147
148 fn read_struct_begin(&mut self) -> ::Result<Option<TStructIdentifier>> {
149 self.read_field_id_stack.push(self.last_read_field_id);
150 self.last_read_field_id = 0;
151 Ok(None)
152 }
153
154 fn read_struct_end(&mut self) -> ::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
162 fn read_field_begin(&mut self) -> ::Result<TFieldIdentifier> {
163 // 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,
197 field_type: field_type,
198 id: Some(self.last_read_field_id),
199 })
Allen George8b96bfb2016-11-02 08:01:08 -0400200 }
201 }
202 }
203
204 fn read_field_end(&mut self) -> ::Result<()> {
205 Ok(())
206 }
207
208 fn read_bool(&mut self) -> ::Result<bool> {
209 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 Georgeef7a1892018-12-16 18:01:37 -0500216 unkn => Err(::Error::Protocol(::ProtocolError {
217 kind: ::ProtocolErrorKind::InvalidData,
218 message: format!("cannot convert {} into bool", unkn),
219 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400220 }
221 }
222 }
223 }
224
225 fn read_bytes(&mut self) -> ::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
234 fn read_i8(&mut self) -> ::Result<i8> {
235 self.read_byte().map(|i| i as i8)
236 }
237
238 fn read_i16(&mut self) -> ::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
242 fn read_i32(&mut self) -> ::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
246 fn read_i64(&mut self) -> ::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
250 fn read_double(&mut self) -> ::Result<f64> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500251 self.transport.read_f64::<BigEndian>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400252 }
253
254 fn read_string(&mut self) -> ::Result<String> {
255 let bytes = self.read_bytes()?;
256 String::from_utf8(bytes).map_err(From::from)
257 }
258
259 fn read_list_begin(&mut self) -> ::Result<TListIdentifier> {
260 let (element_type, element_count) = self.read_list_set_begin()?;
261 Ok(TListIdentifier::new(element_type, element_count))
262 }
263
264 fn read_list_end(&mut self) -> ::Result<()> {
265 Ok(())
266 }
267
268 fn read_set_begin(&mut self) -> ::Result<TSetIdentifier> {
269 let (element_type, element_count) = self.read_list_set_begin()?;
270 Ok(TSetIdentifier::new(element_type, element_count))
271 }
272
273 fn read_set_end(&mut self) -> ::Result<()> {
274 Ok(())
275 }
276
277 fn read_map_begin(&mut self) -> ::Result<TMapIdentifier> {
Allen George0e22c362017-01-30 07:15:00 -0500278 let element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400279 if element_count == 0 {
280 Ok(TMapIdentifier::new(None, None, 0))
281 } else {
282 let type_header = self.read_byte()?;
283 let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
284 let val_type = collection_u8_to_type(type_header & 0x0F)?;
285 Ok(TMapIdentifier::new(key_type, val_type, element_count))
286 }
287 }
288
289 fn read_map_end(&mut self) -> ::Result<()> {
290 Ok(())
291 }
292
293 // utility
294 //
295
296 fn read_byte(&mut self) -> ::Result<u8> {
297 let mut buf = [0u8; 1];
Allen George0e22c362017-01-30 07:15:00 -0500298 self.transport
299 .read_exact(&mut buf)
300 .map_err(From::from)
301 .map(|_| buf[0])
Allen George8b96bfb2016-11-02 08:01:08 -0400302 }
303}
304
Vadim Chekand3355af2018-01-05 23:12:47 -0500305impl<T> io::Seek for TCompactInputProtocol<T>
306where
307 T: io::Seek + TReadTransport,
308{
309 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
310 self.transport.seek(pos)
311 }
312}
313
Allen George8b96bfb2016-11-02 08:01:08 -0400314/// Factory for creating instances of `TCompactInputProtocol`.
315#[derive(Default)]
316pub struct TCompactInputProtocolFactory;
317
318impl TCompactInputProtocolFactory {
319 /// Create a `TCompactInputProtocolFactory`.
320 pub fn new() -> TCompactInputProtocolFactory {
321 TCompactInputProtocolFactory {}
322 }
323}
324
325impl TInputProtocolFactory for TCompactInputProtocolFactory {
Allen George0e22c362017-01-30 07:15:00 -0500326 fn create(&self, transport: Box<TReadTransport + Send>) -> Box<TInputProtocol + Send> {
327 Box::new(TCompactInputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400328 }
329}
330
331/// Write messages using the Thrift compact protocol.
332///
333/// # Examples
334///
335/// Create and use a `TCompactOutputProtocol`.
336///
337/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -0400338/// use thrift::protocol::{TCompactOutputProtocol, TOutputProtocol};
Allen George0e22c362017-01-30 07:15:00 -0500339/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -0400340///
Allen George0e22c362017-01-30 07:15:00 -0500341/// let mut channel = TTcpChannel::new();
342/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400343///
Allen George0e22c362017-01-30 07:15:00 -0500344/// let mut protocol = TCompactOutputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -0400345///
Allen George0e22c362017-01-30 07:15:00 -0500346/// protocol.write_bool(true).unwrap();
347/// protocol.write_string("test_string").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400348/// ```
Allen George0e22c362017-01-30 07:15:00 -0500349#[derive(Debug)]
350pub struct TCompactOutputProtocol<T>
351where
352 T: TWriteTransport,
353{
Allen George8b96bfb2016-11-02 08:01:08 -0400354 // Identifier of the last field serialized for a struct.
355 last_write_field_id: i16,
Allen George0e22c362017-01-30 07:15:00 -0500356 // Stack of the last written field ids (new entry added each time a nested struct is written).
Allen George8b96bfb2016-11-02 08:01:08 -0400357 write_field_id_stack: Vec<i16>,
358 // Field identifier of the boolean field to be written.
359 // Saved because boolean fields and their value are encoded in a single byte
360 pending_write_bool_field_identifier: Option<TFieldIdentifier>,
361 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -0500362 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -0400363}
364
Allen George0e22c362017-01-30 07:15:00 -0500365impl<T> TCompactOutputProtocol<T>
366where
367 T: TWriteTransport,
368{
Allen George8b96bfb2016-11-02 08:01:08 -0400369 /// Create a `TCompactOutputProtocol` that writes bytes to `transport`.
Allen George0e22c362017-01-30 07:15:00 -0500370 pub fn new(transport: T) -> TCompactOutputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -0400371 TCompactOutputProtocol {
372 last_write_field_id: 0,
373 write_field_id_stack: Vec::new(),
374 pending_write_bool_field_identifier: None,
375 transport: transport,
376 }
377 }
378
379 // FIXME: field_type as unconstrained u8 is bad
380 fn write_field_header(&mut self, field_type: u8, field_id: i16) -> ::Result<()> {
381 let field_delta = field_id - self.last_write_field_id;
382 if field_delta > 0 && field_delta < 15 {
383 self.write_byte(((field_delta as u8) << 4) | field_type)?;
384 } else {
385 self.write_byte(field_type)?;
386 self.write_i16(field_id)?;
387 }
388 self.last_write_field_id = field_id;
389 Ok(())
390 }
391
392 fn write_list_set_begin(&mut self, element_type: TType, element_count: i32) -> ::Result<()> {
393 let elem_identifier = collection_type_to_u8(element_type);
394 if element_count <= 14 {
395 let header = (element_count as u8) << 4 | elem_identifier;
396 self.write_byte(header)
397 } else {
398 let header = 0xF0 | elem_identifier;
399 self.write_byte(header)?;
400 self.transport
Allen George8b96bfb2016-11-02 08:01:08 -0400401 .write_varint(element_count as u32)
402 .map_err(From::from)
403 .map(|_| ())
404 }
405 }
406
407 fn assert_no_pending_bool_write(&self) {
408 if let Some(ref f) = self.pending_write_bool_field_identifier {
409 panic!("pending bool field {:?} not written", f)
410 }
411 }
412}
413
Allen George0e22c362017-01-30 07:15:00 -0500414impl<T> TOutputProtocol for TCompactOutputProtocol<T>
415where
416 T: TWriteTransport,
417{
Allen George8b96bfb2016-11-02 08:01:08 -0400418 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> ::Result<()> {
419 self.write_byte(COMPACT_PROTOCOL_ID)?;
420 self.write_byte((u8::from(identifier.message_type) << 5) | COMPACT_VERSION)?;
421 self.write_i32(identifier.sequence_number)?;
422 self.write_string(&identifier.name)?;
423 Ok(())
424 }
425
426 fn write_message_end(&mut self) -> ::Result<()> {
427 self.assert_no_pending_bool_write();
428 Ok(())
429 }
430
431 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> ::Result<()> {
432 self.write_field_id_stack.push(self.last_write_field_id);
433 self.last_write_field_id = 0;
434 Ok(())
435 }
436
437 fn write_struct_end(&mut self) -> ::Result<()> {
438 self.assert_no_pending_bool_write();
Allen Georgeef7a1892018-12-16 18:01:37 -0500439 self.last_write_field_id = self
440 .write_field_id_stack
Allen George0e22c362017-01-30 07:15:00 -0500441 .pop()
442 .expect("should have previous field ids");
Allen George8b96bfb2016-11-02 08:01:08 -0400443 Ok(())
444 }
445
446 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> ::Result<()> {
447 match identifier.field_type {
448 TType::Bool => {
449 if self.pending_write_bool_field_identifier.is_some() {
Allen George0e22c362017-01-30 07:15:00 -0500450 panic!(
451 "should not have a pending bool while writing another bool with id: \
Allen Georgeef7a1892018-12-16 18:01:37 -0500452 {:?}",
Allen George0e22c362017-01-30 07:15:00 -0500453 identifier
454 )
Allen George8b96bfb2016-11-02 08:01:08 -0400455 }
456 self.pending_write_bool_field_identifier = Some(identifier.clone());
457 Ok(())
458 }
459 _ => {
460 let field_type = type_to_u8(identifier.field_type);
Allen Georgeef7a1892018-12-16 18:01:37 -0500461 let field_id = identifier.id.expect("non-stop field should have field id");
Allen George8b96bfb2016-11-02 08:01:08 -0400462 self.write_field_header(field_type, field_id)
463 }
464 }
465 }
466
467 fn write_field_end(&mut self) -> ::Result<()> {
468 self.assert_no_pending_bool_write();
469 Ok(())
470 }
471
472 fn write_field_stop(&mut self) -> ::Result<()> {
473 self.assert_no_pending_bool_write();
474 self.write_byte(type_to_u8(TType::Stop))
475 }
476
477 fn write_bool(&mut self, b: bool) -> ::Result<()> {
478 match self.pending_write_bool_field_identifier.take() {
479 Some(pending) => {
480 let field_id = pending.id.expect("bool field should have a field id");
481 let field_type_as_u8 = if b { 0x01 } else { 0x02 };
482 self.write_field_header(field_type_as_u8, field_id)
483 }
484 None => {
485 if b {
486 self.write_byte(0x01)
487 } else {
488 self.write_byte(0x02)
489 }
490 }
491 }
492 }
493
494 fn write_bytes(&mut self, b: &[u8]) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500495 self.transport.write_varint(b.len() as u32)?;
496 self.transport.write_all(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400497 }
498
499 fn write_i8(&mut self, i: i8) -> ::Result<()> {
500 self.write_byte(i as u8)
501 }
502
503 fn write_i16(&mut self, i: i16) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500504 self.transport
505 .write_varint(i)
506 .map_err(From::from)
507 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400508 }
509
510 fn write_i32(&mut self, i: i32) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500511 self.transport
512 .write_varint(i)
513 .map_err(From::from)
514 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400515 }
516
517 fn write_i64(&mut self, i: i64) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500518 self.transport
519 .write_varint(i)
520 .map_err(From::from)
521 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400522 }
523
524 fn write_double(&mut self, d: f64) -> ::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500525 self.transport.write_f64::<BigEndian>(d).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400526 }
527
528 fn write_string(&mut self, s: &str) -> ::Result<()> {
529 self.write_bytes(s.as_bytes())
530 }
531
532 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> ::Result<()> {
533 self.write_list_set_begin(identifier.element_type, identifier.size)
534 }
535
536 fn write_list_end(&mut self) -> ::Result<()> {
537 Ok(())
538 }
539
540 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> ::Result<()> {
541 self.write_list_set_begin(identifier.element_type, identifier.size)
542 }
543
544 fn write_set_end(&mut self) -> ::Result<()> {
545 Ok(())
546 }
547
548 fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> ::Result<()> {
549 if identifier.size == 0 {
550 self.write_byte(0)
551 } else {
Allen George0e22c362017-01-30 07:15:00 -0500552 self.transport.write_varint(identifier.size as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400553
Allen George0e22c362017-01-30 07:15:00 -0500554 let key_type = identifier
555 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400556 .expect("map identifier to write should contain key type");
557 let key_type_byte = collection_type_to_u8(key_type) << 4;
558
Allen George0e22c362017-01-30 07:15:00 -0500559 let val_type = identifier
560 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400561 .expect("map identifier to write should contain value type");
562 let val_type_byte = collection_type_to_u8(val_type);
563
564 let map_type_header = key_type_byte | val_type_byte;
565 self.write_byte(map_type_header)
566 }
567 }
568
569 fn write_map_end(&mut self) -> ::Result<()> {
570 Ok(())
571 }
572
573 fn flush(&mut self) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500574 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400575 }
576
577 // utility
578 //
579
580 fn write_byte(&mut self, b: u8) -> ::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500581 self.transport.write(&[b]).map_err(From::from).map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400582 }
583}
584
585/// Factory for creating instances of `TCompactOutputProtocol`.
586#[derive(Default)]
587pub struct TCompactOutputProtocolFactory;
588
589impl TCompactOutputProtocolFactory {
590 /// Create a `TCompactOutputProtocolFactory`.
591 pub fn new() -> TCompactOutputProtocolFactory {
592 TCompactOutputProtocolFactory {}
593 }
594}
595
596impl TOutputProtocolFactory for TCompactOutputProtocolFactory {
Allen George0e22c362017-01-30 07:15:00 -0500597 fn create(&self, transport: Box<TWriteTransport + Send>) -> Box<TOutputProtocol + Send> {
598 Box::new(TCompactOutputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400599 }
600}
601
602fn collection_type_to_u8(field_type: TType) -> u8 {
603 match field_type {
604 TType::Bool => 0x01,
605 f => type_to_u8(f),
606 }
607}
608
609fn type_to_u8(field_type: TType) -> u8 {
610 match field_type {
611 TType::Stop => 0x00,
612 TType::I08 => 0x03, // equivalent to TType::Byte
613 TType::I16 => 0x04,
614 TType::I32 => 0x05,
615 TType::I64 => 0x06,
616 TType::Double => 0x07,
617 TType::String => 0x08,
618 TType::List => 0x09,
619 TType::Set => 0x0A,
620 TType::Map => 0x0B,
621 TType::Struct => 0x0C,
Allen Georgeef7a1892018-12-16 18:01:37 -0500622 _ => panic!(format!(
623 "should not have attempted to convert {} to u8",
624 field_type
625 )),
Allen George8b96bfb2016-11-02 08:01:08 -0400626 }
627}
628
629fn collection_u8_to_type(b: u8) -> ::Result<TType> {
630 match b {
631 0x01 => Ok(TType::Bool),
632 o => u8_to_type(o),
633 }
634}
635
636fn u8_to_type(b: u8) -> ::Result<TType> {
637 match b {
638 0x00 => Ok(TType::Stop),
639 0x03 => Ok(TType::I08), // equivalent to TType::Byte
640 0x04 => Ok(TType::I16),
641 0x05 => Ok(TType::I32),
642 0x06 => Ok(TType::I64),
643 0x07 => Ok(TType::Double),
644 0x08 => Ok(TType::String),
645 0x09 => Ok(TType::List),
646 0x0A => Ok(TType::Set),
647 0x0B => Ok(TType::Map),
648 0x0C => Ok(TType::Struct),
Allen Georgeef7a1892018-12-16 18:01:37 -0500649 unkn => Err(::Error::Protocol(::ProtocolError {
650 kind: ::ProtocolErrorKind::InvalidData,
651 message: format!("cannot convert {} into TType", unkn),
652 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400653 }
654}
655
656#[cfg(test)]
657mod tests {
658
Allen Georgeef7a1892018-12-16 18:01:37 -0500659 use protocol::{
660 TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
661 TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
662 };
Allen George0e22c362017-01-30 07:15:00 -0500663 use transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400664
665 use super::*;
666
667 #[test]
668 fn must_write_message_begin_0() {
Allen George0e22c362017-01-30 07:15:00 -0500669 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400670
Allen Georgeef7a1892018-12-16 18:01:37 -0500671 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
672 "foo",
673 TMessageType::Call,
674 431
675 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400676
Allen Georgeef7a1892018-12-16 18:01:37 -0500677 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -0500678 let expected: [u8; 8] = [
679 0x82, /* protocol ID */
680 0x21, /* message type | protocol version */
681 0xDE,
682 0x06, /* zig-zag varint sequence number */
683 0x03, /* message-name length */
684 0x66,
685 0x6F,
686 0x6F /* "foo" */,
687 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400688
Allen George0e22c362017-01-30 07:15:00 -0500689 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400690 }
691
692 #[test]
693 fn must_write_message_begin_1() {
Allen George0e22c362017-01-30 07:15:00 -0500694 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400695
Allen Georgeef7a1892018-12-16 18:01:37 -0500696 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
697 "bar",
698 TMessageType::Reply,
699 991828
700 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400701
Allen Georgeef7a1892018-12-16 18:01:37 -0500702 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -0500703 let expected: [u8; 9] = [
704 0x82, /* protocol ID */
705 0x41, /* message type | protocol version */
706 0xA8,
707 0x89,
708 0x79, /* zig-zag varint sequence number */
709 0x03, /* message-name length */
710 0x62,
711 0x61,
712 0x72 /* "bar" */,
713 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400714
Allen George0e22c362017-01-30 07:15:00 -0500715 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400716 }
717
718 #[test]
719 fn must_round_trip_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500720 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400721
722 let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1283948);
723
724 assert_success!(o_prot.write_message_begin(&ident));
725
Allen George0e22c362017-01-30 07:15:00 -0500726 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400727
728 let res = assert_success!(i_prot.read_message_begin());
729 assert_eq!(&res, &ident);
730 }
731
732 #[test]
733 fn must_write_message_end() {
734 assert_no_write(|o| o.write_message_end());
735 }
736
737 // NOTE: structs and fields are tested together
738 //
739
740 #[test]
741 fn must_write_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500742 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400743
744 // no bytes should be written however
745 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
746
747 // write three fields with tiny field ids
748 // since they're small the field ids will be encoded as deltas
749
750 // since this is the first field (and it's zero) it gets the full varint write
751 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
752 assert_success!(o_prot.write_field_end());
753
754 // since this delta > 0 and < 15 it can be encoded as a delta
755 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
756 assert_success!(o_prot.write_field_end());
757
758 // since this delta > 0 and < 15 it can be encoded as a delta
759 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
760 assert_success!(o_prot.write_field_end());
761
762 // now, finish the struct off
763 assert_success!(o_prot.write_field_stop());
764 assert_success!(o_prot.write_struct_end());
765
Allen Georgeef7a1892018-12-16 18:01:37 -0500766 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -0500767 let expected: [u8; 5] = [
768 0x03, /* field type */
769 0x00, /* first field id */
770 0x44, /* field delta (4) | field type */
771 0x59, /* field delta (5) | field type */
772 0x00 /* field stop */,
773 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400774
Allen George0e22c362017-01-30 07:15:00 -0500775 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400776 }
777
778 #[test]
779 fn must_round_trip_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500780 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400781
782 // no bytes should be written however
783 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
784
785 // write three fields with tiny field ids
786 // since they're small the field ids will be encoded as deltas
787
788 // since this is the first field (and it's zero) it gets the full varint write
789 let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
790 assert_success!(o_prot.write_field_begin(&field_ident_1));
791 assert_success!(o_prot.write_field_end());
792
793 // since this delta > 0 and < 15 it can be encoded as a delta
794 let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
795 assert_success!(o_prot.write_field_begin(&field_ident_2));
796 assert_success!(o_prot.write_field_end());
797
798 // since this delta > 0 and < 15 it can be encoded as a delta
799 let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
800 assert_success!(o_prot.write_field_begin(&field_ident_3));
801 assert_success!(o_prot.write_field_end());
802
803 // now, finish the struct off
804 assert_success!(o_prot.write_field_stop());
805 assert_success!(o_prot.write_struct_end());
806
Allen George0e22c362017-01-30 07:15:00 -0500807 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400808
809 // read the struct back
810 assert_success!(i_prot.read_struct_begin());
811
812 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500813 assert_eq!(
814 read_ident_1,
815 TFieldIdentifier {
816 name: None,
817 ..field_ident_1
818 }
819 );
Allen George8b96bfb2016-11-02 08:01:08 -0400820 assert_success!(i_prot.read_field_end());
821
822 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500823 assert_eq!(
824 read_ident_2,
825 TFieldIdentifier {
826 name: None,
827 ..field_ident_2
828 }
829 );
Allen George8b96bfb2016-11-02 08:01:08 -0400830 assert_success!(i_prot.read_field_end());
831
832 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500833 assert_eq!(
834 read_ident_3,
835 TFieldIdentifier {
836 name: None,
837 ..field_ident_3
838 }
839 );
Allen George8b96bfb2016-11-02 08:01:08 -0400840 assert_success!(i_prot.read_field_end());
841
842 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500843 assert_eq!(
844 read_ident_4,
845 TFieldIdentifier {
846 name: None,
847 field_type: TType::Stop,
848 id: None,
849 }
850 );
Allen George8b96bfb2016-11-02 08:01:08 -0400851
852 assert_success!(i_prot.read_struct_end());
853 }
854
855 #[test]
856 fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500857 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400858
859 // no bytes should be written however
860 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
861
862 // write three fields with tiny field ids
863 // since they're small the field ids will be encoded as deltas
864
865 // gets a delta write
866 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
867 assert_success!(o_prot.write_field_end());
868
869 // since this delta > 0 and < 15 it can be encoded as a delta
870 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
871 assert_success!(o_prot.write_field_end());
872
873 // since this delta > 0 and < 15 it can be encoded as a delta
874 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
875 assert_success!(o_prot.write_field_end());
876
877 // now, finish the struct off
878 assert_success!(o_prot.write_field_stop());
879 assert_success!(o_prot.write_struct_end());
880
Allen Georgeef7a1892018-12-16 18:01:37 -0500881 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -0500882 let expected: [u8; 4] = [
883 0x15, /* field delta (1) | field type */
884 0x1A, /* field delta (1) | field type */
885 0x48, /* field delta (4) | field type */
886 0x00 /* field stop */,
887 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400888
Allen George0e22c362017-01-30 07:15:00 -0500889 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400890 }
891
892 #[test]
893 fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500894 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400895
896 // no bytes should be written however
897 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
898
899 // write three fields with tiny field ids
900 // since they're small the field ids will be encoded as deltas
901
902 // gets a delta write
903 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
904 assert_success!(o_prot.write_field_begin(&field_ident_1));
905 assert_success!(o_prot.write_field_end());
906
907 // since this delta > 0 and < 15 it can be encoded as a delta
908 let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
909 assert_success!(o_prot.write_field_begin(&field_ident_2));
910 assert_success!(o_prot.write_field_end());
911
912 // since this delta > 0 and < 15 it can be encoded as a delta
913 let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
914 assert_success!(o_prot.write_field_begin(&field_ident_3));
915 assert_success!(o_prot.write_field_end());
916
917 // now, finish the struct off
918 assert_success!(o_prot.write_field_stop());
919 assert_success!(o_prot.write_struct_end());
920
Allen George0e22c362017-01-30 07:15:00 -0500921 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400922
923 // read the struct back
924 assert_success!(i_prot.read_struct_begin());
925
926 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500927 assert_eq!(
928 read_ident_1,
929 TFieldIdentifier {
930 name: None,
931 ..field_ident_1
932 }
933 );
Allen George8b96bfb2016-11-02 08:01:08 -0400934 assert_success!(i_prot.read_field_end());
935
936 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500937 assert_eq!(
938 read_ident_2,
939 TFieldIdentifier {
940 name: None,
941 ..field_ident_2
942 }
943 );
Allen George8b96bfb2016-11-02 08:01:08 -0400944 assert_success!(i_prot.read_field_end());
945
946 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500947 assert_eq!(
948 read_ident_3,
949 TFieldIdentifier {
950 name: None,
951 ..field_ident_3
952 }
953 );
Allen George8b96bfb2016-11-02 08:01:08 -0400954 assert_success!(i_prot.read_field_end());
955
956 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500957 assert_eq!(
958 read_ident_4,
959 TFieldIdentifier {
960 name: None,
961 field_type: TType::Stop,
962 id: None,
963 }
964 );
Allen George8b96bfb2016-11-02 08:01:08 -0400965
966 assert_success!(i_prot.read_struct_end());
967 }
968
969 #[test]
970 fn must_write_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500971 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400972
973 // no bytes should be written however
974 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
975
976 // write three fields with field ids that cannot be encoded as deltas
977
978 // since this is the first field (and it's zero) it gets the full varint write
979 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
980 assert_success!(o_prot.write_field_end());
981
982 // since this delta is > 15 it is encoded as a zig-zag varint
983 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
984 assert_success!(o_prot.write_field_end());
985
986 // since this delta is > 15 it is encoded as a zig-zag varint
987 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
988 assert_success!(o_prot.write_field_end());
989
990 // now, finish the struct off
991 assert_success!(o_prot.write_field_stop());
992 assert_success!(o_prot.write_struct_end());
993
Allen Georgeef7a1892018-12-16 18:01:37 -0500994 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -0500995 let expected: [u8; 8] = [
996 0x05, /* field type */
997 0x00, /* first field id */
998 0x06, /* field type */
999 0x20, /* zig-zag varint field id */
1000 0x0A, /* field type */
1001 0xC6,
1002 0x01, /* zig-zag varint field id */
1003 0x00 /* field stop */,
1004 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001005
Allen George0e22c362017-01-30 07:15:00 -05001006 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001007 }
1008
1009 #[test]
1010 fn must_round_trip_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001011 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001012
1013 // no bytes should be written however
1014 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1015
1016 // write three fields with field ids that cannot be encoded as deltas
1017
1018 // since this is the first field (and it's zero) it gets the full varint write
1019 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
1020 assert_success!(o_prot.write_field_begin(&field_ident_1));
1021 assert_success!(o_prot.write_field_end());
1022
1023 // since this delta is > 15 it is encoded as a zig-zag varint
1024 let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
1025 assert_success!(o_prot.write_field_begin(&field_ident_2));
1026 assert_success!(o_prot.write_field_end());
1027
1028 // since this delta is > 15 it is encoded as a zig-zag varint
1029 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
1030 assert_success!(o_prot.write_field_begin(&field_ident_3));
1031 assert_success!(o_prot.write_field_end());
1032
1033 // now, finish the struct off
1034 assert_success!(o_prot.write_field_stop());
1035 assert_success!(o_prot.write_struct_end());
1036
Allen George0e22c362017-01-30 07:15:00 -05001037 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001038
1039 // read the struct back
1040 assert_success!(i_prot.read_struct_begin());
1041
1042 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001043 assert_eq!(
1044 read_ident_1,
1045 TFieldIdentifier {
1046 name: None,
1047 ..field_ident_1
1048 }
1049 );
Allen George8b96bfb2016-11-02 08:01:08 -04001050 assert_success!(i_prot.read_field_end());
1051
1052 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001053 assert_eq!(
1054 read_ident_2,
1055 TFieldIdentifier {
1056 name: None,
1057 ..field_ident_2
1058 }
1059 );
Allen George8b96bfb2016-11-02 08:01:08 -04001060 assert_success!(i_prot.read_field_end());
1061
1062 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001063 assert_eq!(
1064 read_ident_3,
1065 TFieldIdentifier {
1066 name: None,
1067 ..field_ident_3
1068 }
1069 );
Allen George8b96bfb2016-11-02 08:01:08 -04001070 assert_success!(i_prot.read_field_end());
1071
1072 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001073 assert_eq!(
1074 read_ident_4,
1075 TFieldIdentifier {
1076 name: None,
1077 field_type: TType::Stop,
1078 id: None,
1079 }
1080 );
Allen George8b96bfb2016-11-02 08:01:08 -04001081
1082 assert_success!(i_prot.read_struct_end());
1083 }
1084
1085 #[test]
1086 fn must_write_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001087 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001088
1089 // no bytes should be written however
1090 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1091
1092 // write three fields with field ids that cannot be encoded as deltas
1093
1094 // since the delta is > 0 and < 15 it gets a delta write
1095 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1096 assert_success!(o_prot.write_field_end());
1097
1098 // since this delta > 0 and < 15 it gets a delta write
1099 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1100 assert_success!(o_prot.write_field_end());
1101
1102 // since this delta is > 15 it is encoded as a zig-zag varint
1103 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
1104 assert_success!(o_prot.write_field_end());
1105
1106 // since this delta is > 15 it is encoded as a zig-zag varint
1107 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
1108 assert_success!(o_prot.write_field_end());
1109
1110 // since this is only 3 up from the previous it is recorded as a delta
1111 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
1112 assert_success!(o_prot.write_field_end());
1113
1114 // now, finish the struct off
1115 assert_success!(o_prot.write_field_stop());
1116 assert_success!(o_prot.write_struct_end());
1117
Allen Georgeef7a1892018-12-16 18:01:37 -05001118 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -05001119 let expected: [u8; 10] = [
1120 0x16, /* field delta (1) | field type */
1121 0x85, /* field delta (8) | field type */
1122 0x0A, /* field type */
1123 0xD0,
1124 0x0F, /* zig-zag varint field id */
1125 0x0A, /* field type */
1126 0xA2,
1127 0x1F, /* zig-zag varint field id */
1128 0x3A, /* field delta (3) | field type */
1129 0x00 /* field stop */,
1130 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001131
Allen George0e22c362017-01-30 07:15:00 -05001132 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001133 }
1134
1135 #[test]
1136 fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001137 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001138
1139 // no bytes should be written however
1140 let struct_ident = TStructIdentifier::new("foo");
1141 assert_success!(o_prot.write_struct_begin(&struct_ident));
1142
1143 // write three fields with field ids that cannot be encoded as deltas
1144
1145 // since the delta is > 0 and < 15 it gets a delta write
1146 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1147 assert_success!(o_prot.write_field_begin(&field_ident_1));
1148 assert_success!(o_prot.write_field_end());
1149
1150 // since this delta > 0 and < 15 it gets a delta write
1151 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1152 assert_success!(o_prot.write_field_begin(&field_ident_2));
1153 assert_success!(o_prot.write_field_end());
1154
1155 // since this delta is > 15 it is encoded as a zig-zag varint
1156 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
1157 assert_success!(o_prot.write_field_begin(&field_ident_3));
1158 assert_success!(o_prot.write_field_end());
1159
1160 // since this delta is > 15 it is encoded as a zig-zag varint
1161 let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
1162 assert_success!(o_prot.write_field_begin(&field_ident_4));
1163 assert_success!(o_prot.write_field_end());
1164
1165 // since this is only 3 up from the previous it is recorded as a delta
1166 let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
1167 assert_success!(o_prot.write_field_begin(&field_ident_5));
1168 assert_success!(o_prot.write_field_end());
1169
1170 // now, finish the struct off
1171 assert_success!(o_prot.write_field_stop());
1172 assert_success!(o_prot.write_struct_end());
1173
Allen George0e22c362017-01-30 07:15:00 -05001174 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001175
1176 // read the struct back
1177 assert_success!(i_prot.read_struct_begin());
1178
1179 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001180 assert_eq!(
1181 read_ident_1,
1182 TFieldIdentifier {
1183 name: None,
1184 ..field_ident_1
1185 }
1186 );
Allen George8b96bfb2016-11-02 08:01:08 -04001187 assert_success!(i_prot.read_field_end());
1188
1189 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001190 assert_eq!(
1191 read_ident_2,
1192 TFieldIdentifier {
1193 name: None,
1194 ..field_ident_2
1195 }
1196 );
Allen George8b96bfb2016-11-02 08:01:08 -04001197 assert_success!(i_prot.read_field_end());
1198
1199 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001200 assert_eq!(
1201 read_ident_3,
1202 TFieldIdentifier {
1203 name: None,
1204 ..field_ident_3
1205 }
1206 );
Allen George8b96bfb2016-11-02 08:01:08 -04001207 assert_success!(i_prot.read_field_end());
1208
1209 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001210 assert_eq!(
1211 read_ident_4,
1212 TFieldIdentifier {
1213 name: None,
1214 ..field_ident_4
1215 }
1216 );
Allen George8b96bfb2016-11-02 08:01:08 -04001217 assert_success!(i_prot.read_field_end());
1218
1219 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001220 assert_eq!(
1221 read_ident_5,
1222 TFieldIdentifier {
1223 name: None,
1224 ..field_ident_5
1225 }
1226 );
Allen George8b96bfb2016-11-02 08:01:08 -04001227 assert_success!(i_prot.read_field_end());
1228
1229 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001230 assert_eq!(
1231 read_ident_6,
1232 TFieldIdentifier {
1233 name: None,
1234 field_type: TType::Stop,
1235 id: None,
1236 }
1237 );
Allen George8b96bfb2016-11-02 08:01:08 -04001238
1239 assert_success!(i_prot.read_struct_end());
1240 }
1241
1242 #[test]
1243 fn must_write_nested_structs_0() {
1244 // last field of the containing struct is a delta
1245 // first field of the the contained struct is a delta
1246
Allen George0e22c362017-01-30 07:15:00 -05001247 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001248
1249 // start containing struct
1250 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1251
1252 // containing struct
1253 // since the delta is > 0 and < 15 it gets a delta write
1254 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1255 assert_success!(o_prot.write_field_end());
1256
1257 // containing struct
1258 // since this delta > 0 and < 15 it gets a delta write
1259 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1260 assert_success!(o_prot.write_field_end());
1261
1262 // start contained struct
1263 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1264
1265 // contained struct
1266 // since the delta is > 0 and < 15 it gets a delta write
1267 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
1268 assert_success!(o_prot.write_field_end());
1269
1270 // contained struct
1271 // since this delta > 15 it gets a full write
1272 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1273 assert_success!(o_prot.write_field_end());
1274
1275 // end contained struct
1276 assert_success!(o_prot.write_field_stop());
1277 assert_success!(o_prot.write_struct_end());
1278
1279 // end containing struct
1280 assert_success!(o_prot.write_field_stop());
1281 assert_success!(o_prot.write_struct_end());
1282
Allen Georgeef7a1892018-12-16 18:01:37 -05001283 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -05001284 let expected: [u8; 7] = [
1285 0x16, /* field delta (1) | field type */
1286 0x85, /* field delta (8) | field type */
1287 0x73, /* field delta (7) | field type */
1288 0x07, /* field type */
1289 0x30, /* zig-zag varint field id */
1290 0x00, /* field stop - contained */
1291 0x00 /* field stop - containing */,
1292 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001293
Allen George0e22c362017-01-30 07:15:00 -05001294 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001295 }
1296
1297 #[test]
1298 fn must_round_trip_nested_structs_0() {
1299 // last field of the containing struct is a delta
1300 // first field of the the contained struct is a delta
1301
Allen George0e22c362017-01-30 07:15:00 -05001302 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001303
1304 // start containing struct
1305 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1306
1307 // containing struct
1308 // since the delta is > 0 and < 15 it gets a delta write
1309 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1310 assert_success!(o_prot.write_field_begin(&field_ident_1));
1311 assert_success!(o_prot.write_field_end());
1312
1313 // containing struct
1314 // since this delta > 0 and < 15 it gets a delta write
1315 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1316 assert_success!(o_prot.write_field_begin(&field_ident_2));
1317 assert_success!(o_prot.write_field_end());
1318
1319 // start contained struct
1320 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1321
1322 // contained struct
1323 // since the delta is > 0 and < 15 it gets a delta write
1324 let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
1325 assert_success!(o_prot.write_field_begin(&field_ident_3));
1326 assert_success!(o_prot.write_field_end());
1327
1328 // contained struct
1329 // since this delta > 15 it gets a full write
1330 let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
1331 assert_success!(o_prot.write_field_begin(&field_ident_4));
1332 assert_success!(o_prot.write_field_end());
1333
1334 // end contained struct
1335 assert_success!(o_prot.write_field_stop());
1336 assert_success!(o_prot.write_struct_end());
1337
1338 // end containing struct
1339 assert_success!(o_prot.write_field_stop());
1340 assert_success!(o_prot.write_struct_end());
1341
Allen George0e22c362017-01-30 07:15:00 -05001342 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001343
1344 // read containing struct back
1345 assert_success!(i_prot.read_struct_begin());
1346
1347 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001348 assert_eq!(
1349 read_ident_1,
1350 TFieldIdentifier {
1351 name: None,
1352 ..field_ident_1
1353 }
1354 );
Allen George8b96bfb2016-11-02 08:01:08 -04001355 assert_success!(i_prot.read_field_end());
1356
1357 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001358 assert_eq!(
1359 read_ident_2,
1360 TFieldIdentifier {
1361 name: None,
1362 ..field_ident_2
1363 }
1364 );
Allen George8b96bfb2016-11-02 08:01:08 -04001365 assert_success!(i_prot.read_field_end());
1366
1367 // read contained struct back
1368 assert_success!(i_prot.read_struct_begin());
1369
1370 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001371 assert_eq!(
1372 read_ident_3,
1373 TFieldIdentifier {
1374 name: None,
1375 ..field_ident_3
1376 }
1377 );
Allen George8b96bfb2016-11-02 08:01:08 -04001378 assert_success!(i_prot.read_field_end());
1379
1380 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001381 assert_eq!(
1382 read_ident_4,
1383 TFieldIdentifier {
1384 name: None,
1385 ..field_ident_4
1386 }
1387 );
Allen George8b96bfb2016-11-02 08:01:08 -04001388 assert_success!(i_prot.read_field_end());
1389
1390 // end contained struct
1391 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001392 assert_eq!(
1393 read_ident_6,
1394 TFieldIdentifier {
1395 name: None,
1396 field_type: TType::Stop,
1397 id: None,
1398 }
1399 );
Allen George8b96bfb2016-11-02 08:01:08 -04001400 assert_success!(i_prot.read_struct_end());
1401
1402 // end containing struct
1403 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001404 assert_eq!(
1405 read_ident_7,
1406 TFieldIdentifier {
1407 name: None,
1408 field_type: TType::Stop,
1409 id: None,
1410 }
1411 );
Allen George8b96bfb2016-11-02 08:01:08 -04001412 assert_success!(i_prot.read_struct_end());
1413 }
1414
1415 #[test]
1416 fn must_write_nested_structs_1() {
1417 // last field of the containing struct is a delta
1418 // first field of the the contained struct is a full write
1419
Allen George0e22c362017-01-30 07:15:00 -05001420 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001421
1422 // start containing struct
1423 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1424
1425 // containing struct
1426 // since the delta is > 0 and < 15 it gets a delta write
1427 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1428 assert_success!(o_prot.write_field_end());
1429
1430 // containing struct
1431 // since this delta > 0 and < 15 it gets a delta write
1432 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1433 assert_success!(o_prot.write_field_end());
1434
1435 // start contained struct
1436 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1437
1438 // contained struct
1439 // since this delta > 15 it gets a full write
1440 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1441 assert_success!(o_prot.write_field_end());
1442
1443 // contained struct
1444 // since the delta is > 0 and < 15 it gets a delta write
1445 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1446 assert_success!(o_prot.write_field_end());
1447
1448 // end contained struct
1449 assert_success!(o_prot.write_field_stop());
1450 assert_success!(o_prot.write_struct_end());
1451
1452 // end containing struct
1453 assert_success!(o_prot.write_field_stop());
1454 assert_success!(o_prot.write_struct_end());
1455
Allen Georgeef7a1892018-12-16 18:01:37 -05001456 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -05001457 let expected: [u8; 7] = [
1458 0x16, /* field delta (1) | field type */
1459 0x85, /* field delta (8) | field type */
1460 0x07, /* field type */
1461 0x30, /* zig-zag varint field id */
1462 0x33, /* field delta (3) | field type */
1463 0x00, /* field stop - contained */
1464 0x00 /* field stop - containing */,
1465 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001466
Allen George0e22c362017-01-30 07:15:00 -05001467 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001468 }
1469
1470 #[test]
1471 fn must_round_trip_nested_structs_1() {
1472 // last field of the containing struct is a delta
1473 // first field of the the contained struct is a full write
1474
Allen George0e22c362017-01-30 07:15:00 -05001475 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001476
1477 // start containing struct
1478 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1479
1480 // containing struct
1481 // since the delta is > 0 and < 15 it gets a delta write
1482 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1483 assert_success!(o_prot.write_field_begin(&field_ident_1));
1484 assert_success!(o_prot.write_field_end());
1485
1486 // containing struct
1487 // since this delta > 0 and < 15 it gets a delta write
1488 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1489 assert_success!(o_prot.write_field_begin(&field_ident_2));
1490 assert_success!(o_prot.write_field_end());
1491
1492 // start contained struct
1493 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1494
1495 // contained struct
1496 // since this delta > 15 it gets a full write
1497 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
1498 assert_success!(o_prot.write_field_begin(&field_ident_3));
1499 assert_success!(o_prot.write_field_end());
1500
1501 // contained struct
1502 // since the delta is > 0 and < 15 it gets a delta write
1503 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
1504 assert_success!(o_prot.write_field_begin(&field_ident_4));
1505 assert_success!(o_prot.write_field_end());
1506
1507 // end contained struct
1508 assert_success!(o_prot.write_field_stop());
1509 assert_success!(o_prot.write_struct_end());
1510
1511 // end containing struct
1512 assert_success!(o_prot.write_field_stop());
1513 assert_success!(o_prot.write_struct_end());
1514
Allen George0e22c362017-01-30 07:15:00 -05001515 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001516
1517 // read containing struct back
1518 assert_success!(i_prot.read_struct_begin());
1519
1520 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001521 assert_eq!(
1522 read_ident_1,
1523 TFieldIdentifier {
1524 name: None,
1525 ..field_ident_1
1526 }
1527 );
Allen George8b96bfb2016-11-02 08:01:08 -04001528 assert_success!(i_prot.read_field_end());
1529
1530 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001531 assert_eq!(
1532 read_ident_2,
1533 TFieldIdentifier {
1534 name: None,
1535 ..field_ident_2
1536 }
1537 );
Allen George8b96bfb2016-11-02 08:01:08 -04001538 assert_success!(i_prot.read_field_end());
1539
1540 // read contained struct back
1541 assert_success!(i_prot.read_struct_begin());
1542
1543 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001544 assert_eq!(
1545 read_ident_3,
1546 TFieldIdentifier {
1547 name: None,
1548 ..field_ident_3
1549 }
1550 );
Allen George8b96bfb2016-11-02 08:01:08 -04001551 assert_success!(i_prot.read_field_end());
1552
1553 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001554 assert_eq!(
1555 read_ident_4,
1556 TFieldIdentifier {
1557 name: None,
1558 ..field_ident_4
1559 }
1560 );
Allen George8b96bfb2016-11-02 08:01:08 -04001561 assert_success!(i_prot.read_field_end());
1562
1563 // end contained struct
1564 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001565 assert_eq!(
1566 read_ident_6,
1567 TFieldIdentifier {
1568 name: None,
1569 field_type: TType::Stop,
1570 id: None,
1571 }
1572 );
Allen George8b96bfb2016-11-02 08:01:08 -04001573 assert_success!(i_prot.read_struct_end());
1574
1575 // end containing struct
1576 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001577 assert_eq!(
1578 read_ident_7,
1579 TFieldIdentifier {
1580 name: None,
1581 field_type: TType::Stop,
1582 id: None,
1583 }
1584 );
Allen George8b96bfb2016-11-02 08:01:08 -04001585 assert_success!(i_prot.read_struct_end());
1586 }
1587
1588 #[test]
1589 fn must_write_nested_structs_2() {
1590 // last field of the containing struct is a full write
1591 // first field of the the contained struct is a delta write
1592
Allen George0e22c362017-01-30 07:15:00 -05001593 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001594
1595 // start containing struct
1596 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1597
1598 // containing struct
1599 // since the delta is > 0 and < 15 it gets a delta write
1600 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1601 assert_success!(o_prot.write_field_end());
1602
1603 // containing struct
1604 // since this delta > 15 it gets a full write
1605 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
1606 assert_success!(o_prot.write_field_end());
1607
1608 // start contained struct
1609 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1610
1611 // contained struct
1612 // since this delta > 0 and < 15 it gets a delta write
1613 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
1614 assert_success!(o_prot.write_field_end());
1615
1616 // contained struct
1617 // since the delta is > 0 and < 15 it gets a delta write
1618 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
1619 assert_success!(o_prot.write_field_end());
1620
1621 // end contained struct
1622 assert_success!(o_prot.write_field_stop());
1623 assert_success!(o_prot.write_struct_end());
1624
1625 // end containing struct
1626 assert_success!(o_prot.write_field_stop());
1627 assert_success!(o_prot.write_struct_end());
1628
Allen Georgeef7a1892018-12-16 18:01:37 -05001629 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -05001630 let expected: [u8; 7] = [
1631 0x16, /* field delta (1) | field type */
1632 0x08, /* field type */
1633 0x2A, /* zig-zag varint field id */
1634 0x77, /* field delta(7) | field type */
1635 0x33, /* field delta (3) | field type */
1636 0x00, /* field stop - contained */
1637 0x00 /* field stop - containing */,
1638 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001639
Allen George0e22c362017-01-30 07:15:00 -05001640 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001641 }
1642
1643 #[test]
1644 fn must_round_trip_nested_structs_2() {
Allen George0e22c362017-01-30 07:15:00 -05001645 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001646
1647 // start containing struct
1648 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1649
1650 // containing struct
1651 // since the delta is > 0 and < 15 it gets a delta write
1652 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1653 assert_success!(o_prot.write_field_begin(&field_ident_1));
1654 assert_success!(o_prot.write_field_end());
1655
1656 // containing struct
1657 // since this delta > 15 it gets a full write
1658 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
1659 assert_success!(o_prot.write_field_begin(&field_ident_2));
1660 assert_success!(o_prot.write_field_end());
1661
1662 // start contained struct
1663 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1664
1665 // contained struct
1666 // since this delta > 0 and < 15 it gets a delta write
1667 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
1668 assert_success!(o_prot.write_field_begin(&field_ident_3));
1669 assert_success!(o_prot.write_field_end());
1670
1671 // contained struct
1672 // since the delta is > 0 and < 15 it gets a delta write
1673 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
1674 assert_success!(o_prot.write_field_begin(&field_ident_4));
1675 assert_success!(o_prot.write_field_end());
1676
1677 // end contained struct
1678 assert_success!(o_prot.write_field_stop());
1679 assert_success!(o_prot.write_struct_end());
1680
1681 // end containing struct
1682 assert_success!(o_prot.write_field_stop());
1683 assert_success!(o_prot.write_struct_end());
1684
Allen George0e22c362017-01-30 07:15:00 -05001685 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001686
1687 // read containing struct back
1688 assert_success!(i_prot.read_struct_begin());
1689
1690 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001691 assert_eq!(
1692 read_ident_1,
1693 TFieldIdentifier {
1694 name: None,
1695 ..field_ident_1
1696 }
1697 );
Allen George8b96bfb2016-11-02 08:01:08 -04001698 assert_success!(i_prot.read_field_end());
1699
1700 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001701 assert_eq!(
1702 read_ident_2,
1703 TFieldIdentifier {
1704 name: None,
1705 ..field_ident_2
1706 }
1707 );
Allen George8b96bfb2016-11-02 08:01:08 -04001708 assert_success!(i_prot.read_field_end());
1709
1710 // read contained struct back
1711 assert_success!(i_prot.read_struct_begin());
1712
1713 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001714 assert_eq!(
1715 read_ident_3,
1716 TFieldIdentifier {
1717 name: None,
1718 ..field_ident_3
1719 }
1720 );
Allen George8b96bfb2016-11-02 08:01:08 -04001721 assert_success!(i_prot.read_field_end());
1722
1723 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001724 assert_eq!(
1725 read_ident_4,
1726 TFieldIdentifier {
1727 name: None,
1728 ..field_ident_4
1729 }
1730 );
Allen George8b96bfb2016-11-02 08:01:08 -04001731 assert_success!(i_prot.read_field_end());
1732
1733 // end contained struct
1734 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001735 assert_eq!(
1736 read_ident_6,
1737 TFieldIdentifier {
1738 name: None,
1739 field_type: TType::Stop,
1740 id: None,
1741 }
1742 );
Allen George8b96bfb2016-11-02 08:01:08 -04001743 assert_success!(i_prot.read_struct_end());
1744
1745 // end containing struct
1746 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001747 assert_eq!(
1748 read_ident_7,
1749 TFieldIdentifier {
1750 name: None,
1751 field_type: TType::Stop,
1752 id: None,
1753 }
1754 );
Allen George8b96bfb2016-11-02 08:01:08 -04001755 assert_success!(i_prot.read_struct_end());
1756 }
1757
1758 #[test]
1759 fn must_write_nested_structs_3() {
1760 // last field of the containing struct is a full write
1761 // first field of the the contained struct is a full write
1762
Allen George0e22c362017-01-30 07:15:00 -05001763 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001764
1765 // start containing struct
1766 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1767
1768 // containing struct
1769 // since the delta is > 0 and < 15 it gets a delta write
1770 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1771 assert_success!(o_prot.write_field_end());
1772
1773 // containing struct
1774 // since this delta > 15 it gets a full write
1775 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
1776 assert_success!(o_prot.write_field_end());
1777
1778 // start contained struct
1779 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1780
1781 // contained struct
1782 // since this delta > 15 it gets a full write
1783 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
1784 assert_success!(o_prot.write_field_end());
1785
1786 // contained struct
1787 // since the delta is > 0 and < 15 it gets a delta write
1788 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1789 assert_success!(o_prot.write_field_end());
1790
1791 // end contained struct
1792 assert_success!(o_prot.write_field_stop());
1793 assert_success!(o_prot.write_struct_end());
1794
1795 // end containing struct
1796 assert_success!(o_prot.write_field_stop());
1797 assert_success!(o_prot.write_struct_end());
1798
Allen Georgeef7a1892018-12-16 18:01:37 -05001799 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -05001800 let expected: [u8; 8] = [
1801 0x16, /* field delta (1) | field type */
1802 0x08, /* field type */
1803 0x2A, /* zig-zag varint field id */
1804 0x07, /* field type */
1805 0x2A, /* zig-zag varint field id */
1806 0x63, /* field delta (6) | field type */
1807 0x00, /* field stop - contained */
1808 0x00 /* field stop - containing */,
1809 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001810
Allen George0e22c362017-01-30 07:15:00 -05001811 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001812 }
1813
1814 #[test]
1815 fn must_round_trip_nested_structs_3() {
1816 // last field of the containing struct is a full write
1817 // first field of the the contained struct is a full write
1818
Allen George0e22c362017-01-30 07:15:00 -05001819 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001820
1821 // start containing struct
1822 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1823
1824 // containing struct
1825 // since the delta is > 0 and < 15 it gets a delta write
1826 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1827 assert_success!(o_prot.write_field_begin(&field_ident_1));
1828 assert_success!(o_prot.write_field_end());
1829
1830 // containing struct
1831 // since this delta > 15 it gets a full write
1832 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
1833 assert_success!(o_prot.write_field_begin(&field_ident_2));
1834 assert_success!(o_prot.write_field_end());
1835
1836 // start contained struct
1837 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1838
1839 // contained struct
1840 // since this delta > 15 it gets a full write
1841 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
1842 assert_success!(o_prot.write_field_begin(&field_ident_3));
1843 assert_success!(o_prot.write_field_end());
1844
1845 // contained struct
1846 // since the delta is > 0 and < 15 it gets a delta write
1847 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
1848 assert_success!(o_prot.write_field_begin(&field_ident_4));
1849 assert_success!(o_prot.write_field_end());
1850
1851 // end contained struct
1852 assert_success!(o_prot.write_field_stop());
1853 assert_success!(o_prot.write_struct_end());
1854
1855 // end containing struct
1856 assert_success!(o_prot.write_field_stop());
1857 assert_success!(o_prot.write_struct_end());
1858
Allen George0e22c362017-01-30 07:15:00 -05001859 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001860
1861 // read containing struct back
1862 assert_success!(i_prot.read_struct_begin());
1863
1864 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001865 assert_eq!(
1866 read_ident_1,
1867 TFieldIdentifier {
1868 name: None,
1869 ..field_ident_1
1870 }
1871 );
Allen George8b96bfb2016-11-02 08:01:08 -04001872 assert_success!(i_prot.read_field_end());
1873
1874 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001875 assert_eq!(
1876 read_ident_2,
1877 TFieldIdentifier {
1878 name: None,
1879 ..field_ident_2
1880 }
1881 );
Allen George8b96bfb2016-11-02 08:01:08 -04001882 assert_success!(i_prot.read_field_end());
1883
1884 // read contained struct back
1885 assert_success!(i_prot.read_struct_begin());
1886
1887 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001888 assert_eq!(
1889 read_ident_3,
1890 TFieldIdentifier {
1891 name: None,
1892 ..field_ident_3
1893 }
1894 );
Allen George8b96bfb2016-11-02 08:01:08 -04001895 assert_success!(i_prot.read_field_end());
1896
1897 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001898 assert_eq!(
1899 read_ident_4,
1900 TFieldIdentifier {
1901 name: None,
1902 ..field_ident_4
1903 }
1904 );
Allen George8b96bfb2016-11-02 08:01:08 -04001905 assert_success!(i_prot.read_field_end());
1906
1907 // end contained struct
1908 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001909 assert_eq!(
1910 read_ident_6,
1911 TFieldIdentifier {
1912 name: None,
1913 field_type: TType::Stop,
1914 id: None,
1915 }
1916 );
Allen George8b96bfb2016-11-02 08:01:08 -04001917 assert_success!(i_prot.read_struct_end());
1918
1919 // end containing struct
1920 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001921 assert_eq!(
1922 read_ident_7,
1923 TFieldIdentifier {
1924 name: None,
1925 field_type: TType::Stop,
1926 id: None,
1927 }
1928 );
Allen George8b96bfb2016-11-02 08:01:08 -04001929 assert_success!(i_prot.read_struct_end());
1930 }
1931
1932 #[test]
1933 fn must_write_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05001934 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001935
1936 // no bytes should be written however
1937 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1938
1939 // write three fields with field ids that cannot be encoded as deltas
1940
1941 // since the delta is > 0 and < 16 it gets a delta write
1942 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
1943 assert_success!(o_prot.write_bool(true));
1944 assert_success!(o_prot.write_field_end());
1945
1946 // since this delta > 0 and < 15 it gets a delta write
1947 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
1948 assert_success!(o_prot.write_bool(false));
1949 assert_success!(o_prot.write_field_end());
1950
1951 // since this delta > 15 it gets a full write
1952 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
1953 assert_success!(o_prot.write_bool(true));
1954 assert_success!(o_prot.write_field_end());
1955
1956 // since this delta > 15 it gets a full write
1957 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
1958 assert_success!(o_prot.write_bool(false));
1959 assert_success!(o_prot.write_field_end());
1960
1961 // now, finish the struct off
1962 assert_success!(o_prot.write_field_stop());
1963 assert_success!(o_prot.write_struct_end());
1964
Allen Georgeef7a1892018-12-16 18:01:37 -05001965 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -05001966 let expected: [u8; 7] = [
1967 0x11, /* field delta (1) | true */
1968 0x82, /* field delta (8) | false */
1969 0x01, /* true */
1970 0x34, /* field id */
1971 0x02, /* false */
1972 0x5A, /* field id */
1973 0x00 /* stop field */,
1974 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001975
Allen George0e22c362017-01-30 07:15:00 -05001976 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001977 }
1978
1979 #[test]
1980 fn must_round_trip_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05001981 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001982
1983 // no bytes should be written however
1984 let struct_ident = TStructIdentifier::new("foo");
1985 assert_success!(o_prot.write_struct_begin(&struct_ident));
1986
1987 // write two fields
1988
1989 // since the delta is > 0 and < 16 it gets a delta write
1990 let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
1991 assert_success!(o_prot.write_field_begin(&field_ident_1));
1992 assert_success!(o_prot.write_bool(true));
1993 assert_success!(o_prot.write_field_end());
1994
1995 // since this delta > 0 and < 15 it gets a delta write
1996 let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
1997 assert_success!(o_prot.write_field_begin(&field_ident_2));
1998 assert_success!(o_prot.write_bool(false));
1999 assert_success!(o_prot.write_field_end());
2000
2001 // since this delta > 15 it gets a full write
2002 let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
2003 assert_success!(o_prot.write_field_begin(&field_ident_3));
2004 assert_success!(o_prot.write_bool(true));
2005 assert_success!(o_prot.write_field_end());
2006
2007 // since this delta > 15 it gets a full write
2008 let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
2009 assert_success!(o_prot.write_field_begin(&field_ident_4));
2010 assert_success!(o_prot.write_bool(false));
2011 assert_success!(o_prot.write_field_end());
2012
2013 // now, finish the struct off
2014 assert_success!(o_prot.write_field_stop());
2015 assert_success!(o_prot.write_struct_end());
2016
Allen George0e22c362017-01-30 07:15:00 -05002017 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002018
2019 // read the struct back
2020 assert_success!(i_prot.read_struct_begin());
2021
2022 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002023 assert_eq!(
2024 read_ident_1,
2025 TFieldIdentifier {
2026 name: None,
2027 ..field_ident_1
2028 }
2029 );
Allen George8b96bfb2016-11-02 08:01:08 -04002030 let read_value_1 = assert_success!(i_prot.read_bool());
2031 assert_eq!(read_value_1, true);
2032 assert_success!(i_prot.read_field_end());
2033
2034 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002035 assert_eq!(
2036 read_ident_2,
2037 TFieldIdentifier {
2038 name: None,
2039 ..field_ident_2
2040 }
2041 );
Allen George8b96bfb2016-11-02 08:01:08 -04002042 let read_value_2 = assert_success!(i_prot.read_bool());
2043 assert_eq!(read_value_2, false);
2044 assert_success!(i_prot.read_field_end());
2045
2046 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002047 assert_eq!(
2048 read_ident_3,
2049 TFieldIdentifier {
2050 name: None,
2051 ..field_ident_3
2052 }
2053 );
Allen George8b96bfb2016-11-02 08:01:08 -04002054 let read_value_3 = assert_success!(i_prot.read_bool());
2055 assert_eq!(read_value_3, true);
2056 assert_success!(i_prot.read_field_end());
2057
2058 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002059 assert_eq!(
2060 read_ident_4,
2061 TFieldIdentifier {
2062 name: None,
2063 ..field_ident_4
2064 }
2065 );
Allen George8b96bfb2016-11-02 08:01:08 -04002066 let read_value_4 = assert_success!(i_prot.read_bool());
2067 assert_eq!(read_value_4, false);
2068 assert_success!(i_prot.read_field_end());
2069
2070 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002071 assert_eq!(
2072 read_ident_5,
2073 TFieldIdentifier {
2074 name: None,
2075 field_type: TType::Stop,
2076 id: None,
2077 }
2078 );
Allen George8b96bfb2016-11-02 08:01:08 -04002079
2080 assert_success!(i_prot.read_struct_end());
2081 }
2082
2083 #[test]
2084 #[should_panic]
2085 fn must_fail_if_write_field_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002086 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002087 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2088 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2089 o_prot.write_field_end().unwrap();
2090 }
2091
2092 #[test]
2093 #[should_panic]
2094 fn must_fail_if_write_stop_field_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002095 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002096 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2097 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2098 o_prot.write_field_stop().unwrap();
2099 }
2100
2101 #[test]
2102 #[should_panic]
2103 fn must_fail_if_write_struct_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002104 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002105 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2106 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2107 o_prot.write_struct_end().unwrap();
2108 }
2109
2110 #[test]
2111 #[should_panic]
2112 fn must_fail_if_write_struct_end_without_any_fields() {
Allen George0e22c362017-01-30 07:15:00 -05002113 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002114 o_prot.write_struct_end().unwrap();
2115 }
2116
2117 #[test]
2118 fn must_write_field_end() {
2119 assert_no_write(|o| o.write_field_end());
2120 }
2121
2122 #[test]
2123 fn must_write_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002124 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002125
2126 assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
2127
2128 let expected: [u8; 1] = [0x46 /* size | elem_type */];
2129
Allen George0e22c362017-01-30 07:15:00 -05002130 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002131 }
2132
2133 #[test]
2134 fn must_round_trip_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002135 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002136
2137 let ident = TListIdentifier::new(TType::I08, 10);
2138
2139 assert_success!(o_prot.write_list_begin(&ident));
2140
Allen George0e22c362017-01-30 07:15:00 -05002141 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002142
2143 let res = assert_success!(i_prot.read_list_begin());
2144 assert_eq!(&res, &ident);
2145 }
2146
2147 #[test]
2148 fn must_write_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002149 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002150
2151 let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
2152 assert!(res.is_ok());
2153
Allen George0e22c362017-01-30 07:15:00 -05002154 let expected: [u8; 3] = [
2155 0xF9, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002156 0x8F, 0x4E, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002157 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002158
Allen George0e22c362017-01-30 07:15:00 -05002159 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002160 }
2161
2162 #[test]
2163 fn must_round_trip_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002164 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002165
2166 let ident = TListIdentifier::new(TType::Set, 47381);
2167
2168 assert_success!(o_prot.write_list_begin(&ident));
2169
Allen George0e22c362017-01-30 07:15:00 -05002170 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002171
2172 let res = assert_success!(i_prot.read_list_begin());
2173 assert_eq!(&res, &ident);
2174 }
2175
2176 #[test]
2177 fn must_write_list_end() {
2178 assert_no_write(|o| o.write_list_end());
2179 }
2180
2181 #[test]
2182 fn must_write_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002183 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002184
2185 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
2186
2187 let expected: [u8; 1] = [0x2C /* size | elem_type */];
2188
Allen George0e22c362017-01-30 07:15:00 -05002189 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002190 }
2191
2192 #[test]
2193 fn must_round_trip_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002194 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002195
2196 let ident = TSetIdentifier::new(TType::I16, 7);
2197
2198 assert_success!(o_prot.write_set_begin(&ident));
2199
Allen George0e22c362017-01-30 07:15:00 -05002200 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002201
2202 let res = assert_success!(i_prot.read_set_begin());
2203 assert_eq!(&res, &ident);
2204 }
2205
2206 #[test]
2207 fn must_write_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002208 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002209
2210 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
2211
Allen George0e22c362017-01-30 07:15:00 -05002212 let expected: [u8; 4] = [
2213 0xF7, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002214 0xD3, 0xBA, 0x01, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002215 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002216
Allen George0e22c362017-01-30 07:15:00 -05002217 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002218 }
2219
2220 #[test]
2221 fn must_round_trip_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002222 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002223
2224 let ident = TSetIdentifier::new(TType::Map, 3928429);
2225
2226 assert_success!(o_prot.write_set_begin(&ident));
2227
Allen George0e22c362017-01-30 07:15:00 -05002228 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002229
2230 let res = assert_success!(i_prot.read_set_begin());
2231 assert_eq!(&res, &ident);
2232 }
2233
2234 #[test]
2235 fn must_write_set_end() {
2236 assert_no_write(|o| o.write_set_end());
2237 }
2238
2239 #[test]
2240 fn must_write_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002241 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002242
2243 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
2244
2245 let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything
2246
Allen George0e22c362017-01-30 07:15:00 -05002247 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002248 }
2249
2250 #[test]
2251 fn must_read_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002252 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002253
2254 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
2255
Allen George0e22c362017-01-30 07:15:00 -05002256 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002257
2258 let res = assert_success!(i_prot.read_map_begin());
Allen George0e22c362017-01-30 07:15:00 -05002259 assert_eq!(
2260 &res,
2261 &TMapIdentifier {
Allen Georgeef7a1892018-12-16 18:01:37 -05002262 key_type: None,
2263 value_type: None,
2264 size: 0,
2265 }
Allen George0e22c362017-01-30 07:15:00 -05002266 );
Allen George8b96bfb2016-11-02 08:01:08 -04002267 }
2268
2269 #[test]
2270 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002271 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002272
Allen Georgeef7a1892018-12-16 18:01:37 -05002273 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
2274 TType::Double,
2275 TType::String,
2276 238
2277 )));
Allen George8b96bfb2016-11-02 08:01:08 -04002278
Allen George0e22c362017-01-30 07:15:00 -05002279 let expected: [u8; 3] = [
Allen Georgeef7a1892018-12-16 18:01:37 -05002280 0xEE, 0x01, /* size as varint */
2281 0x78, /* key type | val type */
Allen George0e22c362017-01-30 07:15:00 -05002282 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002283
Allen George0e22c362017-01-30 07:15:00 -05002284 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002285 }
2286
2287 #[test]
2288 fn must_round_trip_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002289 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002290
2291 let ident = TMapIdentifier::new(TType::Map, TType::List, 1928349);
2292
2293 assert_success!(o_prot.write_map_begin(&ident));
2294
Allen George0e22c362017-01-30 07:15:00 -05002295 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002296
2297 let res = assert_success!(i_prot.read_map_begin());
2298 assert_eq!(&res, &ident);
2299 }
2300
2301 #[test]
2302 fn must_write_map_end() {
2303 assert_no_write(|o| o.write_map_end());
2304 }
2305
2306 #[test]
2307 fn must_write_map_with_bool_key_and_value() {
Allen George0e22c362017-01-30 07:15:00 -05002308 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002309
2310 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
2311 assert_success!(o_prot.write_bool(true));
2312 assert_success!(o_prot.write_bool(false));
2313 assert_success!(o_prot.write_map_end());
2314
Allen George0e22c362017-01-30 07:15:00 -05002315 let expected: [u8; 4] = [
2316 0x01, /* size as varint */
2317 0x11, /* key type | val type */
2318 0x01, /* key: true */
Allen Georgeef7a1892018-12-16 18:01:37 -05002319 0x02, /* val: false */
Allen George0e22c362017-01-30 07:15:00 -05002320 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002321
Allen George0e22c362017-01-30 07:15:00 -05002322 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002323 }
2324
2325 #[test]
2326 fn must_round_trip_map_with_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002327 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002328
2329 let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
2330 assert_success!(o_prot.write_map_begin(&map_ident));
2331 assert_success!(o_prot.write_bool(true));
2332 assert_success!(o_prot.write_bool(false));
2333 assert_success!(o_prot.write_bool(false));
2334 assert_success!(o_prot.write_bool(true));
2335 assert_success!(o_prot.write_map_end());
2336
Allen George0e22c362017-01-30 07:15:00 -05002337 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002338
2339 // map header
2340 let rcvd_ident = assert_success!(i_prot.read_map_begin());
2341 assert_eq!(&rcvd_ident, &map_ident);
2342 // key 1
2343 let b = assert_success!(i_prot.read_bool());
2344 assert_eq!(b, true);
2345 // val 1
2346 let b = assert_success!(i_prot.read_bool());
2347 assert_eq!(b, false);
2348 // key 2
2349 let b = assert_success!(i_prot.read_bool());
2350 assert_eq!(b, false);
2351 // val 2
2352 let b = assert_success!(i_prot.read_bool());
2353 assert_eq!(b, true);
2354 // map end
2355 assert_success!(i_prot.read_map_end());
2356 }
2357
2358 #[test]
2359 fn must_read_map_end() {
Allen George0e22c362017-01-30 07:15:00 -05002360 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002361 assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
2362 }
2363
Allen Georgeef7a1892018-12-16 18:01:37 -05002364 fn test_objects() -> (
2365 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2366 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2367 ) {
Allen George0e22c362017-01-30 07:15:00 -05002368 let mem = TBufferChannel::with_capacity(80, 80);
Allen George8b96bfb2016-11-02 08:01:08 -04002369
Allen George0e22c362017-01-30 07:15:00 -05002370 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -04002371
Allen George0e22c362017-01-30 07:15:00 -05002372 let i_prot = TCompactInputProtocol::new(r_mem);
2373 let o_prot = TCompactOutputProtocol::new(w_mem);
Allen George8b96bfb2016-11-02 08:01:08 -04002374
Allen George0e22c362017-01-30 07:15:00 -05002375 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -04002376 }
2377
Allen George0e22c362017-01-30 07:15:00 -05002378 fn assert_no_write<F>(mut write_fn: F)
2379 where
2380 F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> ::Result<()>,
2381 {
2382 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002383 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -05002384 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -04002385 }
2386}