blob: 1e67f4931ebf27dde1cb49aeb90510441696d702 [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;
Allen George8b96bfb2016-11-02 08:01:08 -040021use try_from::TryFrom;
Vadim Chekand3355af2018-01-05 23:12:47 -050022use std::io;
Allen George8b96bfb2016-11-02 08:01:08 -040023
Allen George0e22c362017-01-30 07:15:00 -050024use transport::{TReadTransport, TWriteTransport};
25use super::{TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier,
26 TMapIdentifier, TMessageIdentifier, TMessageType};
Allen George8b96bfb2016-11-02 08:01:08 -040027use super::{TOutputProtocol, TOutputProtocolFactory, TSetIdentifier, TStructIdentifier, TType};
28
29const COMPACT_PROTOCOL_ID: u8 = 0x82;
30const COMPACT_VERSION: u8 = 0x01;
31const COMPACT_VERSION_MASK: u8 = 0x1F;
32
33/// Read messages encoded in the Thrift compact protocol.
34///
35/// # Examples
36///
37/// Create and use a `TCompactInputProtocol`.
38///
39/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -040040/// use thrift::protocol::{TCompactInputProtocol, TInputProtocol};
Allen George0e22c362017-01-30 07:15:00 -050041/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -040042///
Allen George0e22c362017-01-30 07:15:00 -050043/// let mut channel = TTcpChannel::new();
44/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040045///
Allen George0e22c362017-01-30 07:15:00 -050046/// let mut protocol = TCompactInputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -040047///
Allen George0e22c362017-01-30 07:15:00 -050048/// let recvd_bool = protocol.read_bool().unwrap();
49/// let recvd_string = protocol.read_string().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040050/// ```
Allen George0e22c362017-01-30 07:15:00 -050051#[derive(Debug)]
52pub struct TCompactInputProtocol<T>
53where
54 T: TReadTransport,
55{
Allen George8b96bfb2016-11-02 08:01:08 -040056 // Identifier of the last field deserialized for a struct.
57 last_read_field_id: i16,
58 // Stack of the last read field ids (a new entry is added each time a nested struct is read).
59 read_field_id_stack: Vec<i16>,
60 // Boolean value for a field.
61 // Saved because boolean fields and their value are encoded in a single byte,
62 // and reading the field only occurs after the field id is read.
63 pending_read_bool_value: Option<bool>,
64 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -050065 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -040066}
67
Allen George0e22c362017-01-30 07:15:00 -050068impl<T> TCompactInputProtocol<T>
69where
70 T: TReadTransport,
71{
Allen George8b96bfb2016-11-02 08:01:08 -040072 /// Create a `TCompactInputProtocol` that reads bytes from `transport`.
Allen George0e22c362017-01-30 07:15:00 -050073 pub fn new(transport: T) -> TCompactInputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -040074 TCompactInputProtocol {
75 last_read_field_id: 0,
76 read_field_id_stack: Vec::new(),
77 pending_read_bool_value: None,
78 transport: transport,
79 }
80 }
81
82 fn read_list_set_begin(&mut self) -> ::Result<(TType, i32)> {
83 let header = self.read_byte()?;
84 let element_type = collection_u8_to_type(header & 0x0F)?;
85
86 let element_count;
87 let possible_element_count = (header & 0xF0) >> 4;
88 if possible_element_count != 15 {
89 // high bits set high if count and type encoded separately
90 element_count = possible_element_count as i32;
91 } else {
Allen George0e22c362017-01-30 07:15:00 -050092 element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -040093 }
94
95 Ok((element_type, element_count))
96 }
97}
98
Allen George0e22c362017-01-30 07:15:00 -050099impl<T> TInputProtocol for TCompactInputProtocol<T>
100where
101 T: TReadTransport,
102{
Allen George8b96bfb2016-11-02 08:01:08 -0400103 fn read_message_begin(&mut self) -> ::Result<TMessageIdentifier> {
104 let compact_id = self.read_byte()?;
105 if compact_id != COMPACT_PROTOCOL_ID {
Allen George0e22c362017-01-30 07:15:00 -0500106 Err(
107 ::Error::Protocol(
108 ::ProtocolError {
109 kind: ::ProtocolErrorKind::BadVersion,
110 message: format!("invalid compact protocol header {:?}", compact_id),
111 },
112 ),
113 )
Allen George8b96bfb2016-11-02 08:01:08 -0400114 } else {
115 Ok(())
116 }?;
117
118 let type_and_byte = self.read_byte()?;
119 let received_version = type_and_byte & COMPACT_VERSION_MASK;
120 if received_version != COMPACT_VERSION {
Allen George0e22c362017-01-30 07:15:00 -0500121 Err(
122 ::Error::Protocol(
123 ::ProtocolError {
124 kind: ::ProtocolErrorKind::BadVersion,
125 message: format!(
126 "cannot process compact protocol version {:?}",
127 received_version
128 ),
129 },
130 ),
131 )
Allen George8b96bfb2016-11-02 08:01:08 -0400132 } else {
133 Ok(())
134 }?;
135
136 // NOTE: unsigned right shift will pad with 0s
137 let message_type: TMessageType = TMessageType::try_from(type_and_byte >> 5)?;
138 let sequence_number = self.read_i32()?;
139 let service_call_name = self.read_string()?;
140
141 self.last_read_field_id = 0;
142
Allen George0e22c362017-01-30 07:15:00 -0500143 Ok(TMessageIdentifier::new(service_call_name, message_type, sequence_number),)
Allen George8b96bfb2016-11-02 08:01:08 -0400144 }
145
146 fn read_message_end(&mut self) -> ::Result<()> {
147 Ok(())
148 }
149
150 fn read_struct_begin(&mut self) -> ::Result<Option<TStructIdentifier>> {
151 self.read_field_id_stack.push(self.last_read_field_id);
152 self.last_read_field_id = 0;
153 Ok(None)
154 }
155
156 fn read_struct_end(&mut self) -> ::Result<()> {
157 self.last_read_field_id = self.read_field_id_stack
158 .pop()
159 .expect("should have previous field ids");
160 Ok(())
161 }
162
163 fn read_field_begin(&mut self) -> ::Result<TFieldIdentifier> {
164 // we can read at least one byte, which is:
165 // - the type
166 // - the field delta and the type
167 let field_type = self.read_byte()?;
168 let field_delta = (field_type & 0xF0) >> 4;
169 let field_type = match field_type & 0x0F {
170 0x01 => {
171 self.pending_read_bool_value = Some(true);
172 Ok(TType::Bool)
173 }
174 0x02 => {
175 self.pending_read_bool_value = Some(false);
176 Ok(TType::Bool)
177 }
178 ttu8 => u8_to_type(ttu8),
179 }?;
180
181 match field_type {
182 TType::Stop => {
Allen George0e22c362017-01-30 07:15:00 -0500183 Ok(
184 TFieldIdentifier::new::<Option<String>, String, Option<i16>>(
185 None,
186 TType::Stop,
187 None,
188 ),
189 )
Allen George8b96bfb2016-11-02 08:01:08 -0400190 }
191 _ => {
192 if field_delta != 0 {
193 self.last_read_field_id += field_delta as i16;
194 } else {
195 self.last_read_field_id = self.read_i16()?;
196 };
197
Allen George0e22c362017-01-30 07:15:00 -0500198 Ok(
199 TFieldIdentifier {
200 name: None,
201 field_type: field_type,
202 id: Some(self.last_read_field_id),
203 },
204 )
Allen George8b96bfb2016-11-02 08:01:08 -0400205 }
206 }
207 }
208
209 fn read_field_end(&mut self) -> ::Result<()> {
210 Ok(())
211 }
212
213 fn read_bool(&mut self) -> ::Result<bool> {
214 match self.pending_read_bool_value.take() {
215 Some(b) => Ok(b),
216 None => {
217 let b = self.read_byte()?;
218 match b {
219 0x01 => Ok(true),
220 0x02 => Ok(false),
221 unkn => {
Allen George0e22c362017-01-30 07:15:00 -0500222 Err(
223 ::Error::Protocol(
224 ::ProtocolError {
225 kind: ::ProtocolErrorKind::InvalidData,
226 message: format!("cannot convert {} into bool", unkn),
227 },
228 ),
229 )
Allen George8b96bfb2016-11-02 08:01:08 -0400230 }
231 }
232 }
233 }
234 }
235
236 fn read_bytes(&mut self) -> ::Result<Vec<u8>> {
Allen George0e22c362017-01-30 07:15:00 -0500237 let len = self.transport.read_varint::<u32>()?;
Allen George8b96bfb2016-11-02 08:01:08 -0400238 let mut buf = vec![0u8; len as usize];
Allen George0e22c362017-01-30 07:15:00 -0500239 self.transport
240 .read_exact(&mut buf)
241 .map_err(From::from)
242 .map(|_| buf)
Allen George8b96bfb2016-11-02 08:01:08 -0400243 }
244
245 fn read_i8(&mut self) -> ::Result<i8> {
246 self.read_byte().map(|i| i as i8)
247 }
248
249 fn read_i16(&mut self) -> ::Result<i16> {
Allen George0e22c362017-01-30 07:15:00 -0500250 self.transport.read_varint::<i16>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400251 }
252
253 fn read_i32(&mut self) -> ::Result<i32> {
Allen George0e22c362017-01-30 07:15:00 -0500254 self.transport.read_varint::<i32>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400255 }
256
257 fn read_i64(&mut self) -> ::Result<i64> {
Allen George0e22c362017-01-30 07:15:00 -0500258 self.transport.read_varint::<i64>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400259 }
260
261 fn read_double(&mut self) -> ::Result<f64> {
Allen George0e22c362017-01-30 07:15:00 -0500262 self.transport
263 .read_f64::<BigEndian>()
264 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400265 }
266
267 fn read_string(&mut self) -> ::Result<String> {
268 let bytes = self.read_bytes()?;
269 String::from_utf8(bytes).map_err(From::from)
270 }
271
272 fn read_list_begin(&mut self) -> ::Result<TListIdentifier> {
273 let (element_type, element_count) = self.read_list_set_begin()?;
274 Ok(TListIdentifier::new(element_type, element_count))
275 }
276
277 fn read_list_end(&mut self) -> ::Result<()> {
278 Ok(())
279 }
280
281 fn read_set_begin(&mut self) -> ::Result<TSetIdentifier> {
282 let (element_type, element_count) = self.read_list_set_begin()?;
283 Ok(TSetIdentifier::new(element_type, element_count))
284 }
285
286 fn read_set_end(&mut self) -> ::Result<()> {
287 Ok(())
288 }
289
290 fn read_map_begin(&mut self) -> ::Result<TMapIdentifier> {
Allen George0e22c362017-01-30 07:15:00 -0500291 let element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400292 if element_count == 0 {
293 Ok(TMapIdentifier::new(None, None, 0))
294 } else {
295 let type_header = self.read_byte()?;
296 let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
297 let val_type = collection_u8_to_type(type_header & 0x0F)?;
298 Ok(TMapIdentifier::new(key_type, val_type, element_count))
299 }
300 }
301
302 fn read_map_end(&mut self) -> ::Result<()> {
303 Ok(())
304 }
305
306 // utility
307 //
308
309 fn read_byte(&mut self) -> ::Result<u8> {
310 let mut buf = [0u8; 1];
Allen George0e22c362017-01-30 07:15:00 -0500311 self.transport
312 .read_exact(&mut buf)
313 .map_err(From::from)
314 .map(|_| buf[0])
Allen George8b96bfb2016-11-02 08:01:08 -0400315 }
316}
317
Vadim Chekand3355af2018-01-05 23:12:47 -0500318
319impl<T> io::Seek for TCompactInputProtocol<T>
320where
321 T: io::Seek + TReadTransport,
322{
323 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
324 self.transport.seek(pos)
325 }
326}
327
Allen George8b96bfb2016-11-02 08:01:08 -0400328/// Factory for creating instances of `TCompactInputProtocol`.
329#[derive(Default)]
330pub struct TCompactInputProtocolFactory;
331
332impl TCompactInputProtocolFactory {
333 /// Create a `TCompactInputProtocolFactory`.
334 pub fn new() -> TCompactInputProtocolFactory {
335 TCompactInputProtocolFactory {}
336 }
337}
338
339impl TInputProtocolFactory for TCompactInputProtocolFactory {
Allen George0e22c362017-01-30 07:15:00 -0500340 fn create(&self, transport: Box<TReadTransport + Send>) -> Box<TInputProtocol + Send> {
341 Box::new(TCompactInputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400342 }
343}
344
345/// Write messages using the Thrift compact protocol.
346///
347/// # Examples
348///
349/// Create and use a `TCompactOutputProtocol`.
350///
351/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -0400352/// use thrift::protocol::{TCompactOutputProtocol, TOutputProtocol};
Allen George0e22c362017-01-30 07:15:00 -0500353/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -0400354///
Allen George0e22c362017-01-30 07:15:00 -0500355/// let mut channel = TTcpChannel::new();
356/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400357///
Allen George0e22c362017-01-30 07:15:00 -0500358/// let mut protocol = TCompactOutputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -0400359///
Allen George0e22c362017-01-30 07:15:00 -0500360/// protocol.write_bool(true).unwrap();
361/// protocol.write_string("test_string").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400362/// ```
Allen George0e22c362017-01-30 07:15:00 -0500363#[derive(Debug)]
364pub struct TCompactOutputProtocol<T>
365where
366 T: TWriteTransport,
367{
Allen George8b96bfb2016-11-02 08:01:08 -0400368 // Identifier of the last field serialized for a struct.
369 last_write_field_id: i16,
Allen George0e22c362017-01-30 07:15:00 -0500370 // Stack of the last written field ids (new entry added each time a nested struct is written).
Allen George8b96bfb2016-11-02 08:01:08 -0400371 write_field_id_stack: Vec<i16>,
372 // Field identifier of the boolean field to be written.
373 // Saved because boolean fields and their value are encoded in a single byte
374 pending_write_bool_field_identifier: Option<TFieldIdentifier>,
375 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -0500376 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -0400377}
378
Allen George0e22c362017-01-30 07:15:00 -0500379impl<T> TCompactOutputProtocol<T>
380where
381 T: TWriteTransport,
382{
Allen George8b96bfb2016-11-02 08:01:08 -0400383 /// Create a `TCompactOutputProtocol` that writes bytes to `transport`.
Allen George0e22c362017-01-30 07:15:00 -0500384 pub fn new(transport: T) -> TCompactOutputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -0400385 TCompactOutputProtocol {
386 last_write_field_id: 0,
387 write_field_id_stack: Vec::new(),
388 pending_write_bool_field_identifier: None,
389 transport: transport,
390 }
391 }
392
393 // FIXME: field_type as unconstrained u8 is bad
394 fn write_field_header(&mut self, field_type: u8, field_id: i16) -> ::Result<()> {
395 let field_delta = field_id - self.last_write_field_id;
396 if field_delta > 0 && field_delta < 15 {
397 self.write_byte(((field_delta as u8) << 4) | field_type)?;
398 } else {
399 self.write_byte(field_type)?;
400 self.write_i16(field_id)?;
401 }
402 self.last_write_field_id = field_id;
403 Ok(())
404 }
405
406 fn write_list_set_begin(&mut self, element_type: TType, element_count: i32) -> ::Result<()> {
407 let elem_identifier = collection_type_to_u8(element_type);
408 if element_count <= 14 {
409 let header = (element_count as u8) << 4 | elem_identifier;
410 self.write_byte(header)
411 } else {
412 let header = 0xF0 | elem_identifier;
413 self.write_byte(header)?;
414 self.transport
Allen George8b96bfb2016-11-02 08:01:08 -0400415 .write_varint(element_count as u32)
416 .map_err(From::from)
417 .map(|_| ())
418 }
419 }
420
421 fn assert_no_pending_bool_write(&self) {
422 if let Some(ref f) = self.pending_write_bool_field_identifier {
423 panic!("pending bool field {:?} not written", f)
424 }
425 }
426}
427
Allen George0e22c362017-01-30 07:15:00 -0500428impl<T> TOutputProtocol for TCompactOutputProtocol<T>
429where
430 T: TWriteTransport,
431{
Allen George8b96bfb2016-11-02 08:01:08 -0400432 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> ::Result<()> {
433 self.write_byte(COMPACT_PROTOCOL_ID)?;
434 self.write_byte((u8::from(identifier.message_type) << 5) | COMPACT_VERSION)?;
435 self.write_i32(identifier.sequence_number)?;
436 self.write_string(&identifier.name)?;
437 Ok(())
438 }
439
440 fn write_message_end(&mut self) -> ::Result<()> {
441 self.assert_no_pending_bool_write();
442 Ok(())
443 }
444
445 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> ::Result<()> {
446 self.write_field_id_stack.push(self.last_write_field_id);
447 self.last_write_field_id = 0;
448 Ok(())
449 }
450
451 fn write_struct_end(&mut self) -> ::Result<()> {
452 self.assert_no_pending_bool_write();
Allen George0e22c362017-01-30 07:15:00 -0500453 self.last_write_field_id = self.write_field_id_stack
454 .pop()
455 .expect("should have previous field ids");
Allen George8b96bfb2016-11-02 08:01:08 -0400456 Ok(())
457 }
458
459 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> ::Result<()> {
460 match identifier.field_type {
461 TType::Bool => {
462 if self.pending_write_bool_field_identifier.is_some() {
Allen George0e22c362017-01-30 07:15:00 -0500463 panic!(
464 "should not have a pending bool while writing another bool with id: \
Allen George8b96bfb2016-11-02 08:01:08 -0400465 {:?}",
Allen George0e22c362017-01-30 07:15:00 -0500466 identifier
467 )
Allen George8b96bfb2016-11-02 08:01:08 -0400468 }
469 self.pending_write_bool_field_identifier = Some(identifier.clone());
470 Ok(())
471 }
472 _ => {
473 let field_type = type_to_u8(identifier.field_type);
Allen George0e22c362017-01-30 07:15:00 -0500474 let field_id = identifier
475 .id
476 .expect("non-stop field should have field id");
Allen George8b96bfb2016-11-02 08:01:08 -0400477 self.write_field_header(field_type, field_id)
478 }
479 }
480 }
481
482 fn write_field_end(&mut self) -> ::Result<()> {
483 self.assert_no_pending_bool_write();
484 Ok(())
485 }
486
487 fn write_field_stop(&mut self) -> ::Result<()> {
488 self.assert_no_pending_bool_write();
489 self.write_byte(type_to_u8(TType::Stop))
490 }
491
492 fn write_bool(&mut self, b: bool) -> ::Result<()> {
493 match self.pending_write_bool_field_identifier.take() {
494 Some(pending) => {
495 let field_id = pending.id.expect("bool field should have a field id");
496 let field_type_as_u8 = if b { 0x01 } else { 0x02 };
497 self.write_field_header(field_type_as_u8, field_id)
498 }
499 None => {
500 if b {
501 self.write_byte(0x01)
502 } else {
503 self.write_byte(0x02)
504 }
505 }
506 }
507 }
508
509 fn write_bytes(&mut self, b: &[u8]) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500510 self.transport.write_varint(b.len() as u32)?;
511 self.transport.write_all(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400512 }
513
514 fn write_i8(&mut self, i: i8) -> ::Result<()> {
515 self.write_byte(i as u8)
516 }
517
518 fn write_i16(&mut self, i: i16) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500519 self.transport
520 .write_varint(i)
521 .map_err(From::from)
522 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400523 }
524
525 fn write_i32(&mut self, i: i32) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500526 self.transport
527 .write_varint(i)
528 .map_err(From::from)
529 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400530 }
531
532 fn write_i64(&mut self, i: i64) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500533 self.transport
534 .write_varint(i)
535 .map_err(From::from)
536 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400537 }
538
539 fn write_double(&mut self, d: f64) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500540 self.transport
541 .write_f64::<BigEndian>(d)
542 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400543 }
544
545 fn write_string(&mut self, s: &str) -> ::Result<()> {
546 self.write_bytes(s.as_bytes())
547 }
548
549 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> ::Result<()> {
550 self.write_list_set_begin(identifier.element_type, identifier.size)
551 }
552
553 fn write_list_end(&mut self) -> ::Result<()> {
554 Ok(())
555 }
556
557 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> ::Result<()> {
558 self.write_list_set_begin(identifier.element_type, identifier.size)
559 }
560
561 fn write_set_end(&mut self) -> ::Result<()> {
562 Ok(())
563 }
564
565 fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> ::Result<()> {
566 if identifier.size == 0 {
567 self.write_byte(0)
568 } else {
Allen George0e22c362017-01-30 07:15:00 -0500569 self.transport.write_varint(identifier.size as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400570
Allen George0e22c362017-01-30 07:15:00 -0500571 let key_type = identifier
572 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400573 .expect("map identifier to write should contain key type");
574 let key_type_byte = collection_type_to_u8(key_type) << 4;
575
Allen George0e22c362017-01-30 07:15:00 -0500576 let val_type = identifier
577 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400578 .expect("map identifier to write should contain value type");
579 let val_type_byte = collection_type_to_u8(val_type);
580
581 let map_type_header = key_type_byte | val_type_byte;
582 self.write_byte(map_type_header)
583 }
584 }
585
586 fn write_map_end(&mut self) -> ::Result<()> {
587 Ok(())
588 }
589
590 fn flush(&mut self) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500591 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400592 }
593
594 // utility
595 //
596
597 fn write_byte(&mut self, b: u8) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500598 self.transport
599 .write(&[b])
600 .map_err(From::from)
601 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400602 }
603}
604
605/// Factory for creating instances of `TCompactOutputProtocol`.
606#[derive(Default)]
607pub struct TCompactOutputProtocolFactory;
608
609impl TCompactOutputProtocolFactory {
610 /// Create a `TCompactOutputProtocolFactory`.
611 pub fn new() -> TCompactOutputProtocolFactory {
612 TCompactOutputProtocolFactory {}
613 }
614}
615
616impl TOutputProtocolFactory for TCompactOutputProtocolFactory {
Allen George0e22c362017-01-30 07:15:00 -0500617 fn create(&self, transport: Box<TWriteTransport + Send>) -> Box<TOutputProtocol + Send> {
618 Box::new(TCompactOutputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400619 }
620}
621
622fn collection_type_to_u8(field_type: TType) -> u8 {
623 match field_type {
624 TType::Bool => 0x01,
625 f => type_to_u8(f),
626 }
627}
628
629fn type_to_u8(field_type: TType) -> u8 {
630 match field_type {
631 TType::Stop => 0x00,
632 TType::I08 => 0x03, // equivalent to TType::Byte
633 TType::I16 => 0x04,
634 TType::I32 => 0x05,
635 TType::I64 => 0x06,
636 TType::Double => 0x07,
637 TType::String => 0x08,
638 TType::List => 0x09,
639 TType::Set => 0x0A,
640 TType::Map => 0x0B,
641 TType::Struct => 0x0C,
642 _ => panic!(format!("should not have attempted to convert {} to u8", field_type)),
643 }
644}
645
646fn collection_u8_to_type(b: u8) -> ::Result<TType> {
647 match b {
648 0x01 => Ok(TType::Bool),
649 o => u8_to_type(o),
650 }
651}
652
653fn u8_to_type(b: u8) -> ::Result<TType> {
654 match b {
655 0x00 => Ok(TType::Stop),
656 0x03 => Ok(TType::I08), // equivalent to TType::Byte
657 0x04 => Ok(TType::I16),
658 0x05 => Ok(TType::I32),
659 0x06 => Ok(TType::I64),
660 0x07 => Ok(TType::Double),
661 0x08 => Ok(TType::String),
662 0x09 => Ok(TType::List),
663 0x0A => Ok(TType::Set),
664 0x0B => Ok(TType::Map),
665 0x0C => Ok(TType::Struct),
666 unkn => {
Allen George0e22c362017-01-30 07:15:00 -0500667 Err(
668 ::Error::Protocol(
669 ::ProtocolError {
670 kind: ::ProtocolErrorKind::InvalidData,
671 message: format!("cannot convert {} into TType", unkn),
672 },
673 ),
674 )
Allen George8b96bfb2016-11-02 08:01:08 -0400675 }
676 }
677}
678
679#[cfg(test)]
680mod tests {
681
Allen George0e22c362017-01-30 07:15:00 -0500682 use protocol::{TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier,
683 TMessageIdentifier, TMessageType, TOutputProtocol, TSetIdentifier,
684 TStructIdentifier, TType};
685 use transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400686
687 use super::*;
688
689 #[test]
690 fn must_write_message_begin_0() {
Allen George0e22c362017-01-30 07:15:00 -0500691 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400692
693 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new("foo", TMessageType::Call, 431)));
694
Allen George0e22c362017-01-30 07:15:00 -0500695 let expected: [u8; 8] = [
696 0x82, /* protocol ID */
697 0x21, /* message type | protocol version */
698 0xDE,
699 0x06, /* zig-zag varint sequence number */
700 0x03, /* message-name length */
701 0x66,
702 0x6F,
703 0x6F /* "foo" */,
704 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400705
Allen George0e22c362017-01-30 07:15:00 -0500706 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400707 }
708
709 #[test]
710 fn must_write_message_begin_1() {
Allen George0e22c362017-01-30 07:15:00 -0500711 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400712
Allen George0e22c362017-01-30 07:15:00 -0500713 assert_success!(
714 o_prot.write_message_begin(&TMessageIdentifier::new("bar", TMessageType::Reply, 991828))
715 );
Allen George8b96bfb2016-11-02 08:01:08 -0400716
Allen George0e22c362017-01-30 07:15:00 -0500717 let expected: [u8; 9] = [
718 0x82, /* protocol ID */
719 0x41, /* message type | protocol version */
720 0xA8,
721 0x89,
722 0x79, /* zig-zag varint sequence number */
723 0x03, /* message-name length */
724 0x62,
725 0x61,
726 0x72 /* "bar" */,
727 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400728
Allen George0e22c362017-01-30 07:15:00 -0500729 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400730 }
731
732 #[test]
733 fn must_round_trip_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500734 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400735
736 let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1283948);
737
738 assert_success!(o_prot.write_message_begin(&ident));
739
Allen George0e22c362017-01-30 07:15:00 -0500740 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400741
742 let res = assert_success!(i_prot.read_message_begin());
743 assert_eq!(&res, &ident);
744 }
745
746 #[test]
747 fn must_write_message_end() {
748 assert_no_write(|o| o.write_message_end());
749 }
750
751 // NOTE: structs and fields are tested together
752 //
753
754 #[test]
755 fn must_write_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500756 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400757
758 // no bytes should be written however
759 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
760
761 // write three fields with tiny field ids
762 // since they're small the field ids will be encoded as deltas
763
764 // since this is the first field (and it's zero) it gets the full varint write
765 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
766 assert_success!(o_prot.write_field_end());
767
768 // since this delta > 0 and < 15 it can be encoded as a delta
769 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
770 assert_success!(o_prot.write_field_end());
771
772 // since this delta > 0 and < 15 it can be encoded as a delta
773 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
774 assert_success!(o_prot.write_field_end());
775
776 // now, finish the struct off
777 assert_success!(o_prot.write_field_stop());
778 assert_success!(o_prot.write_struct_end());
779
Allen George0e22c362017-01-30 07:15:00 -0500780 let expected: [u8; 5] = [
781 0x03, /* field type */
782 0x00, /* first field id */
783 0x44, /* field delta (4) | field type */
784 0x59, /* field delta (5) | field type */
785 0x00 /* field stop */,
786 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400787
Allen George0e22c362017-01-30 07:15:00 -0500788 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400789 }
790
791 #[test]
792 fn must_round_trip_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500793 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400794
795 // no bytes should be written however
796 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
797
798 // write three fields with tiny field ids
799 // since they're small the field ids will be encoded as deltas
800
801 // since this is the first field (and it's zero) it gets the full varint write
802 let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
803 assert_success!(o_prot.write_field_begin(&field_ident_1));
804 assert_success!(o_prot.write_field_end());
805
806 // since this delta > 0 and < 15 it can be encoded as a delta
807 let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
808 assert_success!(o_prot.write_field_begin(&field_ident_2));
809 assert_success!(o_prot.write_field_end());
810
811 // since this delta > 0 and < 15 it can be encoded as a delta
812 let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
813 assert_success!(o_prot.write_field_begin(&field_ident_3));
814 assert_success!(o_prot.write_field_end());
815
816 // now, finish the struct off
817 assert_success!(o_prot.write_field_stop());
818 assert_success!(o_prot.write_struct_end());
819
Allen George0e22c362017-01-30 07:15:00 -0500820 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400821
822 // read the struct back
823 assert_success!(i_prot.read_struct_begin());
824
825 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500826 assert_eq!(
827 read_ident_1,
828 TFieldIdentifier {
829 name: None,
830 ..field_ident_1
831 }
832 );
Allen George8b96bfb2016-11-02 08:01:08 -0400833 assert_success!(i_prot.read_field_end());
834
835 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500836 assert_eq!(
837 read_ident_2,
838 TFieldIdentifier {
839 name: None,
840 ..field_ident_2
841 }
842 );
Allen George8b96bfb2016-11-02 08:01:08 -0400843 assert_success!(i_prot.read_field_end());
844
845 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500846 assert_eq!(
847 read_ident_3,
848 TFieldIdentifier {
849 name: None,
850 ..field_ident_3
851 }
852 );
Allen George8b96bfb2016-11-02 08:01:08 -0400853 assert_success!(i_prot.read_field_end());
854
855 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500856 assert_eq!(
857 read_ident_4,
858 TFieldIdentifier {
859 name: None,
860 field_type: TType::Stop,
861 id: None,
862 }
863 );
Allen George8b96bfb2016-11-02 08:01:08 -0400864
865 assert_success!(i_prot.read_struct_end());
866 }
867
868 #[test]
869 fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500870 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400871
872 // no bytes should be written however
873 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
874
875 // write three fields with tiny field ids
876 // since they're small the field ids will be encoded as deltas
877
878 // gets a delta write
879 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
880 assert_success!(o_prot.write_field_end());
881
882 // since this delta > 0 and < 15 it can be encoded as a delta
883 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
884 assert_success!(o_prot.write_field_end());
885
886 // since this delta > 0 and < 15 it can be encoded as a delta
887 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
888 assert_success!(o_prot.write_field_end());
889
890 // now, finish the struct off
891 assert_success!(o_prot.write_field_stop());
892 assert_success!(o_prot.write_struct_end());
893
Allen George0e22c362017-01-30 07:15:00 -0500894 let expected: [u8; 4] = [
895 0x15, /* field delta (1) | field type */
896 0x1A, /* field delta (1) | field type */
897 0x48, /* field delta (4) | field type */
898 0x00 /* field stop */,
899 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400900
Allen George0e22c362017-01-30 07:15:00 -0500901 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400902 }
903
904 #[test]
905 fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500906 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400907
908 // no bytes should be written however
909 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
910
911 // write three fields with tiny field ids
912 // since they're small the field ids will be encoded as deltas
913
914 // gets a delta write
915 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
916 assert_success!(o_prot.write_field_begin(&field_ident_1));
917 assert_success!(o_prot.write_field_end());
918
919 // since this delta > 0 and < 15 it can be encoded as a delta
920 let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
921 assert_success!(o_prot.write_field_begin(&field_ident_2));
922 assert_success!(o_prot.write_field_end());
923
924 // since this delta > 0 and < 15 it can be encoded as a delta
925 let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
926 assert_success!(o_prot.write_field_begin(&field_ident_3));
927 assert_success!(o_prot.write_field_end());
928
929 // now, finish the struct off
930 assert_success!(o_prot.write_field_stop());
931 assert_success!(o_prot.write_struct_end());
932
Allen George0e22c362017-01-30 07:15:00 -0500933 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400934
935 // read the struct back
936 assert_success!(i_prot.read_struct_begin());
937
938 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500939 assert_eq!(
940 read_ident_1,
941 TFieldIdentifier {
942 name: None,
943 ..field_ident_1
944 }
945 );
Allen George8b96bfb2016-11-02 08:01:08 -0400946 assert_success!(i_prot.read_field_end());
947
948 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500949 assert_eq!(
950 read_ident_2,
951 TFieldIdentifier {
952 name: None,
953 ..field_ident_2
954 }
955 );
Allen George8b96bfb2016-11-02 08:01:08 -0400956 assert_success!(i_prot.read_field_end());
957
958 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500959 assert_eq!(
960 read_ident_3,
961 TFieldIdentifier {
962 name: None,
963 ..field_ident_3
964 }
965 );
Allen George8b96bfb2016-11-02 08:01:08 -0400966 assert_success!(i_prot.read_field_end());
967
968 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500969 assert_eq!(
970 read_ident_4,
971 TFieldIdentifier {
972 name: None,
973 field_type: TType::Stop,
974 id: None,
975 }
976 );
Allen George8b96bfb2016-11-02 08:01:08 -0400977
978 assert_success!(i_prot.read_struct_end());
979 }
980
981 #[test]
982 fn must_write_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500983 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400984
985 // no bytes should be written however
986 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
987
988 // write three fields with field ids that cannot be encoded as deltas
989
990 // since this is the first field (and it's zero) it gets the full varint write
991 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
992 assert_success!(o_prot.write_field_end());
993
994 // since this delta is > 15 it is encoded as a zig-zag varint
995 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
996 assert_success!(o_prot.write_field_end());
997
998 // since this delta is > 15 it is encoded as a zig-zag varint
999 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
1000 assert_success!(o_prot.write_field_end());
1001
1002 // now, finish the struct off
1003 assert_success!(o_prot.write_field_stop());
1004 assert_success!(o_prot.write_struct_end());
1005
Allen George0e22c362017-01-30 07:15:00 -05001006 let expected: [u8; 8] = [
1007 0x05, /* field type */
1008 0x00, /* first field id */
1009 0x06, /* field type */
1010 0x20, /* zig-zag varint field id */
1011 0x0A, /* field type */
1012 0xC6,
1013 0x01, /* zig-zag varint field id */
1014 0x00 /* field stop */,
1015 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001016
Allen George0e22c362017-01-30 07:15:00 -05001017 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001018 }
1019
1020 #[test]
1021 fn must_round_trip_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001022 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001023
1024 // no bytes should be written however
1025 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1026
1027 // write three fields with field ids that cannot be encoded as deltas
1028
1029 // since this is the first field (and it's zero) it gets the full varint write
1030 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
1031 assert_success!(o_prot.write_field_begin(&field_ident_1));
1032 assert_success!(o_prot.write_field_end());
1033
1034 // since this delta is > 15 it is encoded as a zig-zag varint
1035 let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
1036 assert_success!(o_prot.write_field_begin(&field_ident_2));
1037 assert_success!(o_prot.write_field_end());
1038
1039 // since this delta is > 15 it is encoded as a zig-zag varint
1040 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
1041 assert_success!(o_prot.write_field_begin(&field_ident_3));
1042 assert_success!(o_prot.write_field_end());
1043
1044 // now, finish the struct off
1045 assert_success!(o_prot.write_field_stop());
1046 assert_success!(o_prot.write_struct_end());
1047
Allen George0e22c362017-01-30 07:15:00 -05001048 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001049
1050 // read the struct back
1051 assert_success!(i_prot.read_struct_begin());
1052
1053 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001054 assert_eq!(
1055 read_ident_1,
1056 TFieldIdentifier {
1057 name: None,
1058 ..field_ident_1
1059 }
1060 );
Allen George8b96bfb2016-11-02 08:01:08 -04001061 assert_success!(i_prot.read_field_end());
1062
1063 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001064 assert_eq!(
1065 read_ident_2,
1066 TFieldIdentifier {
1067 name: None,
1068 ..field_ident_2
1069 }
1070 );
Allen George8b96bfb2016-11-02 08:01:08 -04001071 assert_success!(i_prot.read_field_end());
1072
1073 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001074 assert_eq!(
1075 read_ident_3,
1076 TFieldIdentifier {
1077 name: None,
1078 ..field_ident_3
1079 }
1080 );
Allen George8b96bfb2016-11-02 08:01:08 -04001081 assert_success!(i_prot.read_field_end());
1082
1083 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001084 assert_eq!(
1085 read_ident_4,
1086 TFieldIdentifier {
1087 name: None,
1088 field_type: TType::Stop,
1089 id: None,
1090 }
1091 );
Allen George8b96bfb2016-11-02 08:01:08 -04001092
1093 assert_success!(i_prot.read_struct_end());
1094 }
1095
1096 #[test]
1097 fn must_write_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001098 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001099
1100 // no bytes should be written however
1101 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1102
1103 // write three fields with field ids that cannot be encoded as deltas
1104
1105 // since the delta is > 0 and < 15 it gets a delta write
1106 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1107 assert_success!(o_prot.write_field_end());
1108
1109 // since this delta > 0 and < 15 it gets a delta write
1110 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1111 assert_success!(o_prot.write_field_end());
1112
1113 // since this delta is > 15 it is encoded as a zig-zag varint
1114 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
1115 assert_success!(o_prot.write_field_end());
1116
1117 // since this delta is > 15 it is encoded as a zig-zag varint
1118 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
1119 assert_success!(o_prot.write_field_end());
1120
1121 // since this is only 3 up from the previous it is recorded as a delta
1122 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
1123 assert_success!(o_prot.write_field_end());
1124
1125 // now, finish the struct off
1126 assert_success!(o_prot.write_field_stop());
1127 assert_success!(o_prot.write_struct_end());
1128
Allen George0e22c362017-01-30 07:15:00 -05001129 let expected: [u8; 10] = [
1130 0x16, /* field delta (1) | field type */
1131 0x85, /* field delta (8) | field type */
1132 0x0A, /* field type */
1133 0xD0,
1134 0x0F, /* zig-zag varint field id */
1135 0x0A, /* field type */
1136 0xA2,
1137 0x1F, /* zig-zag varint field id */
1138 0x3A, /* field delta (3) | field type */
1139 0x00 /* field stop */,
1140 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001141
Allen George0e22c362017-01-30 07:15:00 -05001142 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001143 }
1144
1145 #[test]
1146 fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001147 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001148
1149 // no bytes should be written however
1150 let struct_ident = TStructIdentifier::new("foo");
1151 assert_success!(o_prot.write_struct_begin(&struct_ident));
1152
1153 // write three fields with field ids that cannot be encoded as deltas
1154
1155 // since the delta is > 0 and < 15 it gets a delta write
1156 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1157 assert_success!(o_prot.write_field_begin(&field_ident_1));
1158 assert_success!(o_prot.write_field_end());
1159
1160 // since this delta > 0 and < 15 it gets a delta write
1161 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1162 assert_success!(o_prot.write_field_begin(&field_ident_2));
1163 assert_success!(o_prot.write_field_end());
1164
1165 // since this delta is > 15 it is encoded as a zig-zag varint
1166 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
1167 assert_success!(o_prot.write_field_begin(&field_ident_3));
1168 assert_success!(o_prot.write_field_end());
1169
1170 // since this delta is > 15 it is encoded as a zig-zag varint
1171 let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
1172 assert_success!(o_prot.write_field_begin(&field_ident_4));
1173 assert_success!(o_prot.write_field_end());
1174
1175 // since this is only 3 up from the previous it is recorded as a delta
1176 let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
1177 assert_success!(o_prot.write_field_begin(&field_ident_5));
1178 assert_success!(o_prot.write_field_end());
1179
1180 // now, finish the struct off
1181 assert_success!(o_prot.write_field_stop());
1182 assert_success!(o_prot.write_struct_end());
1183
Allen George0e22c362017-01-30 07:15:00 -05001184 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001185
1186 // read the struct back
1187 assert_success!(i_prot.read_struct_begin());
1188
1189 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001190 assert_eq!(
1191 read_ident_1,
1192 TFieldIdentifier {
1193 name: None,
1194 ..field_ident_1
1195 }
1196 );
Allen George8b96bfb2016-11-02 08:01:08 -04001197 assert_success!(i_prot.read_field_end());
1198
1199 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001200 assert_eq!(
1201 read_ident_2,
1202 TFieldIdentifier {
1203 name: None,
1204 ..field_ident_2
1205 }
1206 );
Allen George8b96bfb2016-11-02 08:01:08 -04001207 assert_success!(i_prot.read_field_end());
1208
1209 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001210 assert_eq!(
1211 read_ident_3,
1212 TFieldIdentifier {
1213 name: None,
1214 ..field_ident_3
1215 }
1216 );
Allen George8b96bfb2016-11-02 08:01:08 -04001217 assert_success!(i_prot.read_field_end());
1218
1219 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001220 assert_eq!(
1221 read_ident_4,
1222 TFieldIdentifier {
1223 name: None,
1224 ..field_ident_4
1225 }
1226 );
Allen George8b96bfb2016-11-02 08:01:08 -04001227 assert_success!(i_prot.read_field_end());
1228
1229 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001230 assert_eq!(
1231 read_ident_5,
1232 TFieldIdentifier {
1233 name: None,
1234 ..field_ident_5
1235 }
1236 );
Allen George8b96bfb2016-11-02 08:01:08 -04001237 assert_success!(i_prot.read_field_end());
1238
1239 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001240 assert_eq!(
1241 read_ident_6,
1242 TFieldIdentifier {
1243 name: None,
1244 field_type: TType::Stop,
1245 id: None,
1246 }
1247 );
Allen George8b96bfb2016-11-02 08:01:08 -04001248
1249 assert_success!(i_prot.read_struct_end());
1250 }
1251
1252 #[test]
1253 fn must_write_nested_structs_0() {
1254 // last field of the containing struct is a delta
1255 // first field of the the contained struct is a delta
1256
Allen George0e22c362017-01-30 07:15:00 -05001257 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001258
1259 // start containing struct
1260 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1261
1262 // containing struct
1263 // since the delta is > 0 and < 15 it gets a delta write
1264 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1265 assert_success!(o_prot.write_field_end());
1266
1267 // containing struct
1268 // since this delta > 0 and < 15 it gets a delta write
1269 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1270 assert_success!(o_prot.write_field_end());
1271
1272 // start contained struct
1273 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1274
1275 // contained struct
1276 // since the delta is > 0 and < 15 it gets a delta write
1277 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
1278 assert_success!(o_prot.write_field_end());
1279
1280 // contained struct
1281 // since this delta > 15 it gets a full write
1282 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1283 assert_success!(o_prot.write_field_end());
1284
1285 // end contained struct
1286 assert_success!(o_prot.write_field_stop());
1287 assert_success!(o_prot.write_struct_end());
1288
1289 // end containing struct
1290 assert_success!(o_prot.write_field_stop());
1291 assert_success!(o_prot.write_struct_end());
1292
Allen George0e22c362017-01-30 07:15:00 -05001293 let expected: [u8; 7] = [
1294 0x16, /* field delta (1) | field type */
1295 0x85, /* field delta (8) | field type */
1296 0x73, /* field delta (7) | field type */
1297 0x07, /* field type */
1298 0x30, /* zig-zag varint field id */
1299 0x00, /* field stop - contained */
1300 0x00 /* field stop - containing */,
1301 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001302
Allen George0e22c362017-01-30 07:15:00 -05001303 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001304 }
1305
1306 #[test]
1307 fn must_round_trip_nested_structs_0() {
1308 // last field of the containing struct is a delta
1309 // first field of the the contained struct is a delta
1310
Allen George0e22c362017-01-30 07:15:00 -05001311 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001312
1313 // start containing struct
1314 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1315
1316 // containing struct
1317 // since the delta is > 0 and < 15 it gets a delta write
1318 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1319 assert_success!(o_prot.write_field_begin(&field_ident_1));
1320 assert_success!(o_prot.write_field_end());
1321
1322 // containing struct
1323 // since this delta > 0 and < 15 it gets a delta write
1324 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1325 assert_success!(o_prot.write_field_begin(&field_ident_2));
1326 assert_success!(o_prot.write_field_end());
1327
1328 // start contained struct
1329 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1330
1331 // contained struct
1332 // since the delta is > 0 and < 15 it gets a delta write
1333 let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
1334 assert_success!(o_prot.write_field_begin(&field_ident_3));
1335 assert_success!(o_prot.write_field_end());
1336
1337 // contained struct
1338 // since this delta > 15 it gets a full write
1339 let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
1340 assert_success!(o_prot.write_field_begin(&field_ident_4));
1341 assert_success!(o_prot.write_field_end());
1342
1343 // end contained struct
1344 assert_success!(o_prot.write_field_stop());
1345 assert_success!(o_prot.write_struct_end());
1346
1347 // end containing struct
1348 assert_success!(o_prot.write_field_stop());
1349 assert_success!(o_prot.write_struct_end());
1350
Allen George0e22c362017-01-30 07:15:00 -05001351 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001352
1353 // read containing struct back
1354 assert_success!(i_prot.read_struct_begin());
1355
1356 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001357 assert_eq!(
1358 read_ident_1,
1359 TFieldIdentifier {
1360 name: None,
1361 ..field_ident_1
1362 }
1363 );
Allen George8b96bfb2016-11-02 08:01:08 -04001364 assert_success!(i_prot.read_field_end());
1365
1366 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001367 assert_eq!(
1368 read_ident_2,
1369 TFieldIdentifier {
1370 name: None,
1371 ..field_ident_2
1372 }
1373 );
Allen George8b96bfb2016-11-02 08:01:08 -04001374 assert_success!(i_prot.read_field_end());
1375
1376 // read contained struct back
1377 assert_success!(i_prot.read_struct_begin());
1378
1379 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001380 assert_eq!(
1381 read_ident_3,
1382 TFieldIdentifier {
1383 name: None,
1384 ..field_ident_3
1385 }
1386 );
Allen George8b96bfb2016-11-02 08:01:08 -04001387 assert_success!(i_prot.read_field_end());
1388
1389 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001390 assert_eq!(
1391 read_ident_4,
1392 TFieldIdentifier {
1393 name: None,
1394 ..field_ident_4
1395 }
1396 );
Allen George8b96bfb2016-11-02 08:01:08 -04001397 assert_success!(i_prot.read_field_end());
1398
1399 // end contained struct
1400 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001401 assert_eq!(
1402 read_ident_6,
1403 TFieldIdentifier {
1404 name: None,
1405 field_type: TType::Stop,
1406 id: None,
1407 }
1408 );
Allen George8b96bfb2016-11-02 08:01:08 -04001409 assert_success!(i_prot.read_struct_end());
1410
1411 // end containing struct
1412 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001413 assert_eq!(
1414 read_ident_7,
1415 TFieldIdentifier {
1416 name: None,
1417 field_type: TType::Stop,
1418 id: None,
1419 }
1420 );
Allen George8b96bfb2016-11-02 08:01:08 -04001421 assert_success!(i_prot.read_struct_end());
1422 }
1423
1424 #[test]
1425 fn must_write_nested_structs_1() {
1426 // last field of the containing struct is a delta
1427 // first field of the the contained struct is a full write
1428
Allen George0e22c362017-01-30 07:15:00 -05001429 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001430
1431 // start containing struct
1432 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1433
1434 // containing struct
1435 // since the delta is > 0 and < 15 it gets a delta write
1436 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1437 assert_success!(o_prot.write_field_end());
1438
1439 // containing struct
1440 // since this delta > 0 and < 15 it gets a delta write
1441 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1442 assert_success!(o_prot.write_field_end());
1443
1444 // start contained struct
1445 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1446
1447 // contained struct
1448 // since this delta > 15 it gets a full write
1449 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1450 assert_success!(o_prot.write_field_end());
1451
1452 // contained struct
1453 // since the delta is > 0 and < 15 it gets a delta write
1454 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1455 assert_success!(o_prot.write_field_end());
1456
1457 // end contained struct
1458 assert_success!(o_prot.write_field_stop());
1459 assert_success!(o_prot.write_struct_end());
1460
1461 // end containing struct
1462 assert_success!(o_prot.write_field_stop());
1463 assert_success!(o_prot.write_struct_end());
1464
Allen George0e22c362017-01-30 07:15:00 -05001465 let expected: [u8; 7] = [
1466 0x16, /* field delta (1) | field type */
1467 0x85, /* field delta (8) | field type */
1468 0x07, /* field type */
1469 0x30, /* zig-zag varint field id */
1470 0x33, /* field delta (3) | field type */
1471 0x00, /* field stop - contained */
1472 0x00 /* field stop - containing */,
1473 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001474
Allen George0e22c362017-01-30 07:15:00 -05001475 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001476 }
1477
1478 #[test]
1479 fn must_round_trip_nested_structs_1() {
1480 // last field of the containing struct is a delta
1481 // first field of the the contained struct is a full write
1482
Allen George0e22c362017-01-30 07:15:00 -05001483 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001484
1485 // start containing struct
1486 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1487
1488 // containing struct
1489 // since the delta is > 0 and < 15 it gets a delta write
1490 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1491 assert_success!(o_prot.write_field_begin(&field_ident_1));
1492 assert_success!(o_prot.write_field_end());
1493
1494 // containing struct
1495 // since this delta > 0 and < 15 it gets a delta write
1496 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1497 assert_success!(o_prot.write_field_begin(&field_ident_2));
1498 assert_success!(o_prot.write_field_end());
1499
1500 // start contained struct
1501 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1502
1503 // contained struct
1504 // since this delta > 15 it gets a full write
1505 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
1506 assert_success!(o_prot.write_field_begin(&field_ident_3));
1507 assert_success!(o_prot.write_field_end());
1508
1509 // contained struct
1510 // since the delta is > 0 and < 15 it gets a delta write
1511 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
1512 assert_success!(o_prot.write_field_begin(&field_ident_4));
1513 assert_success!(o_prot.write_field_end());
1514
1515 // end contained struct
1516 assert_success!(o_prot.write_field_stop());
1517 assert_success!(o_prot.write_struct_end());
1518
1519 // end containing struct
1520 assert_success!(o_prot.write_field_stop());
1521 assert_success!(o_prot.write_struct_end());
1522
Allen George0e22c362017-01-30 07:15:00 -05001523 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001524
1525 // read containing struct back
1526 assert_success!(i_prot.read_struct_begin());
1527
1528 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001529 assert_eq!(
1530 read_ident_1,
1531 TFieldIdentifier {
1532 name: None,
1533 ..field_ident_1
1534 }
1535 );
Allen George8b96bfb2016-11-02 08:01:08 -04001536 assert_success!(i_prot.read_field_end());
1537
1538 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001539 assert_eq!(
1540 read_ident_2,
1541 TFieldIdentifier {
1542 name: None,
1543 ..field_ident_2
1544 }
1545 );
Allen George8b96bfb2016-11-02 08:01:08 -04001546 assert_success!(i_prot.read_field_end());
1547
1548 // read contained struct back
1549 assert_success!(i_prot.read_struct_begin());
1550
1551 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001552 assert_eq!(
1553 read_ident_3,
1554 TFieldIdentifier {
1555 name: None,
1556 ..field_ident_3
1557 }
1558 );
Allen George8b96bfb2016-11-02 08:01:08 -04001559 assert_success!(i_prot.read_field_end());
1560
1561 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001562 assert_eq!(
1563 read_ident_4,
1564 TFieldIdentifier {
1565 name: None,
1566 ..field_ident_4
1567 }
1568 );
Allen George8b96bfb2016-11-02 08:01:08 -04001569 assert_success!(i_prot.read_field_end());
1570
1571 // end contained struct
1572 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001573 assert_eq!(
1574 read_ident_6,
1575 TFieldIdentifier {
1576 name: None,
1577 field_type: TType::Stop,
1578 id: None,
1579 }
1580 );
Allen George8b96bfb2016-11-02 08:01:08 -04001581 assert_success!(i_prot.read_struct_end());
1582
1583 // end containing struct
1584 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001585 assert_eq!(
1586 read_ident_7,
1587 TFieldIdentifier {
1588 name: None,
1589 field_type: TType::Stop,
1590 id: None,
1591 }
1592 );
Allen George8b96bfb2016-11-02 08:01:08 -04001593 assert_success!(i_prot.read_struct_end());
1594 }
1595
1596 #[test]
1597 fn must_write_nested_structs_2() {
1598 // last field of the containing struct is a full write
1599 // first field of the the contained struct is a delta write
1600
Allen George0e22c362017-01-30 07:15:00 -05001601 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001602
1603 // start containing struct
1604 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1605
1606 // containing struct
1607 // since the delta is > 0 and < 15 it gets a delta write
1608 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1609 assert_success!(o_prot.write_field_end());
1610
1611 // containing struct
1612 // since this delta > 15 it gets a full write
1613 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
1614 assert_success!(o_prot.write_field_end());
1615
1616 // start contained struct
1617 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1618
1619 // contained struct
1620 // since this delta > 0 and < 15 it gets a delta write
1621 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
1622 assert_success!(o_prot.write_field_end());
1623
1624 // contained struct
1625 // since the delta is > 0 and < 15 it gets a delta write
1626 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
1627 assert_success!(o_prot.write_field_end());
1628
1629 // end contained struct
1630 assert_success!(o_prot.write_field_stop());
1631 assert_success!(o_prot.write_struct_end());
1632
1633 // end containing struct
1634 assert_success!(o_prot.write_field_stop());
1635 assert_success!(o_prot.write_struct_end());
1636
Allen George0e22c362017-01-30 07:15:00 -05001637 let expected: [u8; 7] = [
1638 0x16, /* field delta (1) | field type */
1639 0x08, /* field type */
1640 0x2A, /* zig-zag varint field id */
1641 0x77, /* field delta(7) | field type */
1642 0x33, /* field delta (3) | field type */
1643 0x00, /* field stop - contained */
1644 0x00 /* field stop - containing */,
1645 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001646
Allen George0e22c362017-01-30 07:15:00 -05001647 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001648 }
1649
1650 #[test]
1651 fn must_round_trip_nested_structs_2() {
Allen George0e22c362017-01-30 07:15:00 -05001652 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001653
1654 // start containing struct
1655 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1656
1657 // containing struct
1658 // since the delta is > 0 and < 15 it gets a delta write
1659 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1660 assert_success!(o_prot.write_field_begin(&field_ident_1));
1661 assert_success!(o_prot.write_field_end());
1662
1663 // containing struct
1664 // since this delta > 15 it gets a full write
1665 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
1666 assert_success!(o_prot.write_field_begin(&field_ident_2));
1667 assert_success!(o_prot.write_field_end());
1668
1669 // start contained struct
1670 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1671
1672 // contained struct
1673 // since this delta > 0 and < 15 it gets a delta write
1674 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
1675 assert_success!(o_prot.write_field_begin(&field_ident_3));
1676 assert_success!(o_prot.write_field_end());
1677
1678 // contained struct
1679 // since the delta is > 0 and < 15 it gets a delta write
1680 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
1681 assert_success!(o_prot.write_field_begin(&field_ident_4));
1682 assert_success!(o_prot.write_field_end());
1683
1684 // end contained struct
1685 assert_success!(o_prot.write_field_stop());
1686 assert_success!(o_prot.write_struct_end());
1687
1688 // end containing struct
1689 assert_success!(o_prot.write_field_stop());
1690 assert_success!(o_prot.write_struct_end());
1691
Allen George0e22c362017-01-30 07:15:00 -05001692 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001693
1694 // read containing struct back
1695 assert_success!(i_prot.read_struct_begin());
1696
1697 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001698 assert_eq!(
1699 read_ident_1,
1700 TFieldIdentifier {
1701 name: None,
1702 ..field_ident_1
1703 }
1704 );
Allen George8b96bfb2016-11-02 08:01:08 -04001705 assert_success!(i_prot.read_field_end());
1706
1707 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001708 assert_eq!(
1709 read_ident_2,
1710 TFieldIdentifier {
1711 name: None,
1712 ..field_ident_2
1713 }
1714 );
Allen George8b96bfb2016-11-02 08:01:08 -04001715 assert_success!(i_prot.read_field_end());
1716
1717 // read contained struct back
1718 assert_success!(i_prot.read_struct_begin());
1719
1720 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001721 assert_eq!(
1722 read_ident_3,
1723 TFieldIdentifier {
1724 name: None,
1725 ..field_ident_3
1726 }
1727 );
Allen George8b96bfb2016-11-02 08:01:08 -04001728 assert_success!(i_prot.read_field_end());
1729
1730 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001731 assert_eq!(
1732 read_ident_4,
1733 TFieldIdentifier {
1734 name: None,
1735 ..field_ident_4
1736 }
1737 );
Allen George8b96bfb2016-11-02 08:01:08 -04001738 assert_success!(i_prot.read_field_end());
1739
1740 // end contained struct
1741 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001742 assert_eq!(
1743 read_ident_6,
1744 TFieldIdentifier {
1745 name: None,
1746 field_type: TType::Stop,
1747 id: None,
1748 }
1749 );
Allen George8b96bfb2016-11-02 08:01:08 -04001750 assert_success!(i_prot.read_struct_end());
1751
1752 // end containing struct
1753 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001754 assert_eq!(
1755 read_ident_7,
1756 TFieldIdentifier {
1757 name: None,
1758 field_type: TType::Stop,
1759 id: None,
1760 }
1761 );
Allen George8b96bfb2016-11-02 08:01:08 -04001762 assert_success!(i_prot.read_struct_end());
1763 }
1764
1765 #[test]
1766 fn must_write_nested_structs_3() {
1767 // last field of the containing struct is a full write
1768 // first field of the the contained struct is a full write
1769
Allen George0e22c362017-01-30 07:15:00 -05001770 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001771
1772 // start containing struct
1773 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1774
1775 // containing struct
1776 // since the delta is > 0 and < 15 it gets a delta write
1777 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1778 assert_success!(o_prot.write_field_end());
1779
1780 // containing struct
1781 // since this delta > 15 it gets a full write
1782 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
1783 assert_success!(o_prot.write_field_end());
1784
1785 // start contained struct
1786 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1787
1788 // contained struct
1789 // since this delta > 15 it gets a full write
1790 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
1791 assert_success!(o_prot.write_field_end());
1792
1793 // contained struct
1794 // since the delta is > 0 and < 15 it gets a delta write
1795 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1796 assert_success!(o_prot.write_field_end());
1797
1798 // end contained struct
1799 assert_success!(o_prot.write_field_stop());
1800 assert_success!(o_prot.write_struct_end());
1801
1802 // end containing struct
1803 assert_success!(o_prot.write_field_stop());
1804 assert_success!(o_prot.write_struct_end());
1805
Allen George0e22c362017-01-30 07:15:00 -05001806 let expected: [u8; 8] = [
1807 0x16, /* field delta (1) | field type */
1808 0x08, /* field type */
1809 0x2A, /* zig-zag varint field id */
1810 0x07, /* field type */
1811 0x2A, /* zig-zag varint field id */
1812 0x63, /* field delta (6) | field type */
1813 0x00, /* field stop - contained */
1814 0x00 /* field stop - containing */,
1815 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001816
Allen George0e22c362017-01-30 07:15:00 -05001817 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001818 }
1819
1820 #[test]
1821 fn must_round_trip_nested_structs_3() {
1822 // last field of the containing struct is a full write
1823 // first field of the the contained struct is a full write
1824
Allen George0e22c362017-01-30 07:15:00 -05001825 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001826
1827 // start containing struct
1828 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1829
1830 // containing struct
1831 // since the delta is > 0 and < 15 it gets a delta write
1832 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1833 assert_success!(o_prot.write_field_begin(&field_ident_1));
1834 assert_success!(o_prot.write_field_end());
1835
1836 // containing struct
1837 // since this delta > 15 it gets a full write
1838 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
1839 assert_success!(o_prot.write_field_begin(&field_ident_2));
1840 assert_success!(o_prot.write_field_end());
1841
1842 // start contained struct
1843 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1844
1845 // contained struct
1846 // since this delta > 15 it gets a full write
1847 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
1848 assert_success!(o_prot.write_field_begin(&field_ident_3));
1849 assert_success!(o_prot.write_field_end());
1850
1851 // contained struct
1852 // since the delta is > 0 and < 15 it gets a delta write
1853 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
1854 assert_success!(o_prot.write_field_begin(&field_ident_4));
1855 assert_success!(o_prot.write_field_end());
1856
1857 // end contained struct
1858 assert_success!(o_prot.write_field_stop());
1859 assert_success!(o_prot.write_struct_end());
1860
1861 // end containing struct
1862 assert_success!(o_prot.write_field_stop());
1863 assert_success!(o_prot.write_struct_end());
1864
Allen George0e22c362017-01-30 07:15:00 -05001865 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001866
1867 // read containing struct back
1868 assert_success!(i_prot.read_struct_begin());
1869
1870 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001871 assert_eq!(
1872 read_ident_1,
1873 TFieldIdentifier {
1874 name: None,
1875 ..field_ident_1
1876 }
1877 );
Allen George8b96bfb2016-11-02 08:01:08 -04001878 assert_success!(i_prot.read_field_end());
1879
1880 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001881 assert_eq!(
1882 read_ident_2,
1883 TFieldIdentifier {
1884 name: None,
1885 ..field_ident_2
1886 }
1887 );
Allen George8b96bfb2016-11-02 08:01:08 -04001888 assert_success!(i_prot.read_field_end());
1889
1890 // read contained struct back
1891 assert_success!(i_prot.read_struct_begin());
1892
1893 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001894 assert_eq!(
1895 read_ident_3,
1896 TFieldIdentifier {
1897 name: None,
1898 ..field_ident_3
1899 }
1900 );
Allen George8b96bfb2016-11-02 08:01:08 -04001901 assert_success!(i_prot.read_field_end());
1902
1903 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001904 assert_eq!(
1905 read_ident_4,
1906 TFieldIdentifier {
1907 name: None,
1908 ..field_ident_4
1909 }
1910 );
Allen George8b96bfb2016-11-02 08:01:08 -04001911 assert_success!(i_prot.read_field_end());
1912
1913 // end contained struct
1914 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001915 assert_eq!(
1916 read_ident_6,
1917 TFieldIdentifier {
1918 name: None,
1919 field_type: TType::Stop,
1920 id: None,
1921 }
1922 );
Allen George8b96bfb2016-11-02 08:01:08 -04001923 assert_success!(i_prot.read_struct_end());
1924
1925 // end containing struct
1926 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001927 assert_eq!(
1928 read_ident_7,
1929 TFieldIdentifier {
1930 name: None,
1931 field_type: TType::Stop,
1932 id: None,
1933 }
1934 );
Allen George8b96bfb2016-11-02 08:01:08 -04001935 assert_success!(i_prot.read_struct_end());
1936 }
1937
1938 #[test]
1939 fn must_write_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05001940 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001941
1942 // no bytes should be written however
1943 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1944
1945 // write three fields with field ids that cannot be encoded as deltas
1946
1947 // since the delta is > 0 and < 16 it gets a delta write
1948 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
1949 assert_success!(o_prot.write_bool(true));
1950 assert_success!(o_prot.write_field_end());
1951
1952 // since this delta > 0 and < 15 it gets a delta write
1953 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
1954 assert_success!(o_prot.write_bool(false));
1955 assert_success!(o_prot.write_field_end());
1956
1957 // since this delta > 15 it gets a full write
1958 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
1959 assert_success!(o_prot.write_bool(true));
1960 assert_success!(o_prot.write_field_end());
1961
1962 // since this delta > 15 it gets a full write
1963 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
1964 assert_success!(o_prot.write_bool(false));
1965 assert_success!(o_prot.write_field_end());
1966
1967 // now, finish the struct off
1968 assert_success!(o_prot.write_field_stop());
1969 assert_success!(o_prot.write_struct_end());
1970
Allen George0e22c362017-01-30 07:15:00 -05001971 let expected: [u8; 7] = [
1972 0x11, /* field delta (1) | true */
1973 0x82, /* field delta (8) | false */
1974 0x01, /* true */
1975 0x34, /* field id */
1976 0x02, /* false */
1977 0x5A, /* field id */
1978 0x00 /* stop field */,
1979 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001980
Allen George0e22c362017-01-30 07:15:00 -05001981 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001982 }
1983
1984 #[test]
1985 fn must_round_trip_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05001986 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001987
1988 // no bytes should be written however
1989 let struct_ident = TStructIdentifier::new("foo");
1990 assert_success!(o_prot.write_struct_begin(&struct_ident));
1991
1992 // write two fields
1993
1994 // since the delta is > 0 and < 16 it gets a delta write
1995 let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
1996 assert_success!(o_prot.write_field_begin(&field_ident_1));
1997 assert_success!(o_prot.write_bool(true));
1998 assert_success!(o_prot.write_field_end());
1999
2000 // since this delta > 0 and < 15 it gets a delta write
2001 let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
2002 assert_success!(o_prot.write_field_begin(&field_ident_2));
2003 assert_success!(o_prot.write_bool(false));
2004 assert_success!(o_prot.write_field_end());
2005
2006 // since this delta > 15 it gets a full write
2007 let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
2008 assert_success!(o_prot.write_field_begin(&field_ident_3));
2009 assert_success!(o_prot.write_bool(true));
2010 assert_success!(o_prot.write_field_end());
2011
2012 // since this delta > 15 it gets a full write
2013 let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
2014 assert_success!(o_prot.write_field_begin(&field_ident_4));
2015 assert_success!(o_prot.write_bool(false));
2016 assert_success!(o_prot.write_field_end());
2017
2018 // now, finish the struct off
2019 assert_success!(o_prot.write_field_stop());
2020 assert_success!(o_prot.write_struct_end());
2021
Allen George0e22c362017-01-30 07:15:00 -05002022 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002023
2024 // read the struct back
2025 assert_success!(i_prot.read_struct_begin());
2026
2027 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002028 assert_eq!(
2029 read_ident_1,
2030 TFieldIdentifier {
2031 name: None,
2032 ..field_ident_1
2033 }
2034 );
Allen George8b96bfb2016-11-02 08:01:08 -04002035 let read_value_1 = assert_success!(i_prot.read_bool());
2036 assert_eq!(read_value_1, true);
2037 assert_success!(i_prot.read_field_end());
2038
2039 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002040 assert_eq!(
2041 read_ident_2,
2042 TFieldIdentifier {
2043 name: None,
2044 ..field_ident_2
2045 }
2046 );
Allen George8b96bfb2016-11-02 08:01:08 -04002047 let read_value_2 = assert_success!(i_prot.read_bool());
2048 assert_eq!(read_value_2, false);
2049 assert_success!(i_prot.read_field_end());
2050
2051 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002052 assert_eq!(
2053 read_ident_3,
2054 TFieldIdentifier {
2055 name: None,
2056 ..field_ident_3
2057 }
2058 );
Allen George8b96bfb2016-11-02 08:01:08 -04002059 let read_value_3 = assert_success!(i_prot.read_bool());
2060 assert_eq!(read_value_3, true);
2061 assert_success!(i_prot.read_field_end());
2062
2063 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002064 assert_eq!(
2065 read_ident_4,
2066 TFieldIdentifier {
2067 name: None,
2068 ..field_ident_4
2069 }
2070 );
Allen George8b96bfb2016-11-02 08:01:08 -04002071 let read_value_4 = assert_success!(i_prot.read_bool());
2072 assert_eq!(read_value_4, false);
2073 assert_success!(i_prot.read_field_end());
2074
2075 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002076 assert_eq!(
2077 read_ident_5,
2078 TFieldIdentifier {
2079 name: None,
2080 field_type: TType::Stop,
2081 id: None,
2082 }
2083 );
Allen George8b96bfb2016-11-02 08:01:08 -04002084
2085 assert_success!(i_prot.read_struct_end());
2086 }
2087
2088 #[test]
2089 #[should_panic]
2090 fn must_fail_if_write_field_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002091 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002092 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2093 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2094 o_prot.write_field_end().unwrap();
2095 }
2096
2097 #[test]
2098 #[should_panic]
2099 fn must_fail_if_write_stop_field_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002100 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002101 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2102 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2103 o_prot.write_field_stop().unwrap();
2104 }
2105
2106 #[test]
2107 #[should_panic]
2108 fn must_fail_if_write_struct_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002109 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002110 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2111 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2112 o_prot.write_struct_end().unwrap();
2113 }
2114
2115 #[test]
2116 #[should_panic]
2117 fn must_fail_if_write_struct_end_without_any_fields() {
Allen George0e22c362017-01-30 07:15:00 -05002118 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002119 o_prot.write_struct_end().unwrap();
2120 }
2121
2122 #[test]
2123 fn must_write_field_end() {
2124 assert_no_write(|o| o.write_field_end());
2125 }
2126
2127 #[test]
2128 fn must_write_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002129 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002130
2131 assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
2132
2133 let expected: [u8; 1] = [0x46 /* size | elem_type */];
2134
Allen George0e22c362017-01-30 07:15:00 -05002135 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002136 }
2137
2138 #[test]
2139 fn must_round_trip_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002140 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002141
2142 let ident = TListIdentifier::new(TType::I08, 10);
2143
2144 assert_success!(o_prot.write_list_begin(&ident));
2145
Allen George0e22c362017-01-30 07:15:00 -05002146 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002147
2148 let res = assert_success!(i_prot.read_list_begin());
2149 assert_eq!(&res, &ident);
2150 }
2151
2152 #[test]
2153 fn must_write_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002154 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002155
2156 let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
2157 assert!(res.is_ok());
2158
Allen George0e22c362017-01-30 07:15:00 -05002159 let expected: [u8; 3] = [
2160 0xF9, /* 0xF0 | elem_type */
2161 0x8F,
2162 0x4E /* size as varint */,
2163 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002164
Allen George0e22c362017-01-30 07:15:00 -05002165 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002166 }
2167
2168 #[test]
2169 fn must_round_trip_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002170 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002171
2172 let ident = TListIdentifier::new(TType::Set, 47381);
2173
2174 assert_success!(o_prot.write_list_begin(&ident));
2175
Allen George0e22c362017-01-30 07:15:00 -05002176 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002177
2178 let res = assert_success!(i_prot.read_list_begin());
2179 assert_eq!(&res, &ident);
2180 }
2181
2182 #[test]
2183 fn must_write_list_end() {
2184 assert_no_write(|o| o.write_list_end());
2185 }
2186
2187 #[test]
2188 fn must_write_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002189 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002190
2191 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
2192
2193 let expected: [u8; 1] = [0x2C /* size | elem_type */];
2194
Allen George0e22c362017-01-30 07:15:00 -05002195 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002196 }
2197
2198 #[test]
2199 fn must_round_trip_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002200 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002201
2202 let ident = TSetIdentifier::new(TType::I16, 7);
2203
2204 assert_success!(o_prot.write_set_begin(&ident));
2205
Allen George0e22c362017-01-30 07:15:00 -05002206 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002207
2208 let res = assert_success!(i_prot.read_set_begin());
2209 assert_eq!(&res, &ident);
2210 }
2211
2212 #[test]
2213 fn must_write_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002214 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002215
2216 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
2217
Allen George0e22c362017-01-30 07:15:00 -05002218 let expected: [u8; 4] = [
2219 0xF7, /* 0xF0 | elem_type */
2220 0xD3,
2221 0xBA,
2222 0x01 /* size as varint */,
2223 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002224
Allen George0e22c362017-01-30 07:15:00 -05002225 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002226 }
2227
2228 #[test]
2229 fn must_round_trip_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002230 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002231
2232 let ident = TSetIdentifier::new(TType::Map, 3928429);
2233
2234 assert_success!(o_prot.write_set_begin(&ident));
2235
Allen George0e22c362017-01-30 07:15:00 -05002236 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002237
2238 let res = assert_success!(i_prot.read_set_begin());
2239 assert_eq!(&res, &ident);
2240 }
2241
2242 #[test]
2243 fn must_write_set_end() {
2244 assert_no_write(|o| o.write_set_end());
2245 }
2246
2247 #[test]
2248 fn must_write_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002249 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002250
2251 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
2252
2253 let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything
2254
Allen George0e22c362017-01-30 07:15:00 -05002255 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002256 }
2257
2258 #[test]
2259 fn must_read_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002260 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002261
2262 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
2263
Allen George0e22c362017-01-30 07:15:00 -05002264 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002265
2266 let res = assert_success!(i_prot.read_map_begin());
Allen George0e22c362017-01-30 07:15:00 -05002267 assert_eq!(
2268 &res,
2269 &TMapIdentifier {
2270 key_type: None,
2271 value_type: None,
2272 size: 0,
2273 }
2274 );
Allen George8b96bfb2016-11-02 08:01:08 -04002275 }
2276
2277 #[test]
2278 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002279 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002280
2281 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::String, 238)));
2282
Allen George0e22c362017-01-30 07:15:00 -05002283 let expected: [u8; 3] = [
2284 0xEE,
2285 0x01, /* size as varint */
2286 0x78 /* key type | val type */,
2287 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002288
Allen George0e22c362017-01-30 07:15:00 -05002289 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002290 }
2291
2292 #[test]
2293 fn must_round_trip_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002294 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002295
2296 let ident = TMapIdentifier::new(TType::Map, TType::List, 1928349);
2297
2298 assert_success!(o_prot.write_map_begin(&ident));
2299
Allen George0e22c362017-01-30 07:15:00 -05002300 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002301
2302 let res = assert_success!(i_prot.read_map_begin());
2303 assert_eq!(&res, &ident);
2304 }
2305
2306 #[test]
2307 fn must_write_map_end() {
2308 assert_no_write(|o| o.write_map_end());
2309 }
2310
2311 #[test]
2312 fn must_write_map_with_bool_key_and_value() {
Allen George0e22c362017-01-30 07:15:00 -05002313 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002314
2315 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
2316 assert_success!(o_prot.write_bool(true));
2317 assert_success!(o_prot.write_bool(false));
2318 assert_success!(o_prot.write_map_end());
2319
Allen George0e22c362017-01-30 07:15:00 -05002320 let expected: [u8; 4] = [
2321 0x01, /* size as varint */
2322 0x11, /* key type | val type */
2323 0x01, /* key: true */
2324 0x02 /* val: false */,
2325 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002326
Allen George0e22c362017-01-30 07:15:00 -05002327 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002328 }
2329
2330 #[test]
2331 fn must_round_trip_map_with_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002332 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002333
2334 let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
2335 assert_success!(o_prot.write_map_begin(&map_ident));
2336 assert_success!(o_prot.write_bool(true));
2337 assert_success!(o_prot.write_bool(false));
2338 assert_success!(o_prot.write_bool(false));
2339 assert_success!(o_prot.write_bool(true));
2340 assert_success!(o_prot.write_map_end());
2341
Allen George0e22c362017-01-30 07:15:00 -05002342 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002343
2344 // map header
2345 let rcvd_ident = assert_success!(i_prot.read_map_begin());
2346 assert_eq!(&rcvd_ident, &map_ident);
2347 // key 1
2348 let b = assert_success!(i_prot.read_bool());
2349 assert_eq!(b, true);
2350 // val 1
2351 let b = assert_success!(i_prot.read_bool());
2352 assert_eq!(b, false);
2353 // key 2
2354 let b = assert_success!(i_prot.read_bool());
2355 assert_eq!(b, false);
2356 // val 2
2357 let b = assert_success!(i_prot.read_bool());
2358 assert_eq!(b, true);
2359 // map end
2360 assert_success!(i_prot.read_map_end());
2361 }
2362
2363 #[test]
2364 fn must_read_map_end() {
Allen George0e22c362017-01-30 07:15:00 -05002365 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002366 assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
2367 }
2368
Allen George0e22c362017-01-30 07:15:00 -05002369 fn test_objects()
2370 -> (TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2371 TCompactOutputProtocol<WriteHalf<TBufferChannel>>)
Allen George8b96bfb2016-11-02 08:01:08 -04002372 {
Allen George0e22c362017-01-30 07:15:00 -05002373 let mem = TBufferChannel::with_capacity(80, 80);
Allen George8b96bfb2016-11-02 08:01:08 -04002374
Allen George0e22c362017-01-30 07:15:00 -05002375 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -04002376
Allen George0e22c362017-01-30 07:15:00 -05002377 let i_prot = TCompactInputProtocol::new(r_mem);
2378 let o_prot = TCompactOutputProtocol::new(w_mem);
Allen George8b96bfb2016-11-02 08:01:08 -04002379
Allen George0e22c362017-01-30 07:15:00 -05002380 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -04002381 }
2382
Allen George0e22c362017-01-30 07:15:00 -05002383 fn assert_no_write<F>(mut write_fn: F)
2384 where
2385 F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> ::Result<()>,
2386 {
2387 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002388 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -05002389 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -04002390 }
2391}