blob: 334e8201b9a3145f554ada51fde2933dc6e0d9b7 [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};
Danny Browningddec4312019-03-08 14:20:41 -070020use std::convert::{From, TryFrom};
Vadim Chekand3355af2018-01-05 23:12:47 -050021use std::io;
Allen George8b96bfb2016-11-02 08:01:08 -040022
Allen Georgeef7a1892018-12-16 18:01:37 -050023use super::{
24 TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier, TMapIdentifier,
25 TMessageIdentifier, TMessageType,
26};
Allen George8b96bfb2016-11-02 08:01:08 -040027use super::{TOutputProtocol, TOutputProtocolFactory, TSetIdentifier, TStructIdentifier, TType};
Allen Georgeef7a1892018-12-16 18:01:37 -050028use transport::{TReadTransport, TWriteTransport};
Allen George8b96bfb2016-11-02 08:01:08 -040029
30const COMPACT_PROTOCOL_ID: u8 = 0x82;
31const COMPACT_VERSION: u8 = 0x01;
32const COMPACT_VERSION_MASK: u8 = 0x1F;
33
34/// Read messages encoded in the Thrift compact protocol.
35///
36/// # Examples
37///
38/// Create and use a `TCompactInputProtocol`.
39///
40/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -040041/// use thrift::protocol::{TCompactInputProtocol, TInputProtocol};
Allen George0e22c362017-01-30 07:15:00 -050042/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -040043///
Allen George0e22c362017-01-30 07:15:00 -050044/// let mut channel = TTcpChannel::new();
45/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040046///
Allen George0e22c362017-01-30 07:15:00 -050047/// let mut protocol = TCompactInputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -040048///
Allen George0e22c362017-01-30 07:15:00 -050049/// let recvd_bool = protocol.read_bool().unwrap();
50/// let recvd_string = protocol.read_string().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040051/// ```
Allen George0e22c362017-01-30 07:15:00 -050052#[derive(Debug)]
53pub struct TCompactInputProtocol<T>
54where
55 T: TReadTransport,
56{
Allen George8b96bfb2016-11-02 08:01:08 -040057 // Identifier of the last field deserialized for a struct.
58 last_read_field_id: i16,
59 // Stack of the last read field ids (a new entry is added each time a nested struct is read).
60 read_field_id_stack: Vec<i16>,
61 // Boolean value for a field.
62 // Saved because boolean fields and their value are encoded in a single byte,
63 // and reading the field only occurs after the field id is read.
64 pending_read_bool_value: Option<bool>,
65 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -050066 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -040067}
68
Allen George0e22c362017-01-30 07:15:00 -050069impl<T> TCompactInputProtocol<T>
70where
71 T: TReadTransport,
72{
Allen George8b96bfb2016-11-02 08:01:08 -040073 /// Create a `TCompactInputProtocol` that reads bytes from `transport`.
Allen George0e22c362017-01-30 07:15:00 -050074 pub fn new(transport: T) -> TCompactInputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -040075 TCompactInputProtocol {
76 last_read_field_id: 0,
77 read_field_id_stack: Vec::new(),
78 pending_read_bool_value: None,
79 transport: transport,
80 }
81 }
82
83 fn read_list_set_begin(&mut self) -> ::Result<(TType, i32)> {
84 let header = self.read_byte()?;
85 let element_type = collection_u8_to_type(header & 0x0F)?;
86
87 let element_count;
88 let possible_element_count = (header & 0xF0) >> 4;
89 if possible_element_count != 15 {
90 // high bits set high if count and type encoded separately
91 element_count = possible_element_count as i32;
92 } else {
Allen George0e22c362017-01-30 07:15:00 -050093 element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -040094 }
95
96 Ok((element_type, element_count))
97 }
98}
99
Allen George0e22c362017-01-30 07:15:00 -0500100impl<T> TInputProtocol for TCompactInputProtocol<T>
101where
102 T: TReadTransport,
103{
Allen George8b96bfb2016-11-02 08:01:08 -0400104 fn read_message_begin(&mut self) -> ::Result<TMessageIdentifier> {
105 let compact_id = self.read_byte()?;
106 if compact_id != COMPACT_PROTOCOL_ID {
Allen Georgeef7a1892018-12-16 18:01:37 -0500107 Err(::Error::Protocol(::ProtocolError {
108 kind: ::ProtocolErrorKind::BadVersion,
109 message: format!("invalid compact protocol header {:?}", compact_id),
110 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400111 } else {
112 Ok(())
113 }?;
114
115 let type_and_byte = self.read_byte()?;
116 let received_version = type_and_byte & COMPACT_VERSION_MASK;
117 if received_version != COMPACT_VERSION {
Allen Georgeef7a1892018-12-16 18:01:37 -0500118 Err(::Error::Protocol(::ProtocolError {
119 kind: ::ProtocolErrorKind::BadVersion,
120 message: format!(
121 "cannot process compact protocol version {:?}",
122 received_version
Allen George0e22c362017-01-30 07:15:00 -0500123 ),
Allen Georgeef7a1892018-12-16 18:01:37 -0500124 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400125 } else {
126 Ok(())
127 }?;
128
129 // NOTE: unsigned right shift will pad with 0s
130 let message_type: TMessageType = TMessageType::try_from(type_and_byte >> 5)?;
131 let sequence_number = self.read_i32()?;
132 let service_call_name = self.read_string()?;
133
134 self.last_read_field_id = 0;
135
Allen Georgeef7a1892018-12-16 18:01:37 -0500136 Ok(TMessageIdentifier::new(
137 service_call_name,
138 message_type,
139 sequence_number,
140 ))
Allen George8b96bfb2016-11-02 08:01:08 -0400141 }
142
143 fn read_message_end(&mut self) -> ::Result<()> {
144 Ok(())
145 }
146
147 fn read_struct_begin(&mut self) -> ::Result<Option<TStructIdentifier>> {
148 self.read_field_id_stack.push(self.last_read_field_id);
149 self.last_read_field_id = 0;
150 Ok(None)
151 }
152
153 fn read_struct_end(&mut self) -> ::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500154 self.last_read_field_id = self
155 .read_field_id_stack
Allen George8b96bfb2016-11-02 08:01:08 -0400156 .pop()
157 .expect("should have previous field ids");
158 Ok(())
159 }
160
161 fn read_field_begin(&mut self) -> ::Result<TFieldIdentifier> {
162 // we can read at least one byte, which is:
163 // - the type
164 // - the field delta and the type
165 let field_type = self.read_byte()?;
166 let field_delta = (field_type & 0xF0) >> 4;
167 let field_type = match field_type & 0x0F {
168 0x01 => {
169 self.pending_read_bool_value = Some(true);
170 Ok(TType::Bool)
171 }
172 0x02 => {
173 self.pending_read_bool_value = Some(false);
174 Ok(TType::Bool)
175 }
176 ttu8 => u8_to_type(ttu8),
177 }?;
178
179 match field_type {
Allen Georgeef7a1892018-12-16 18:01:37 -0500180 TType::Stop => Ok(
181 TFieldIdentifier::new::<Option<String>, String, Option<i16>>(
182 None,
183 TType::Stop,
184 None,
185 ),
186 ),
Allen George8b96bfb2016-11-02 08:01:08 -0400187 _ => {
188 if field_delta != 0 {
189 self.last_read_field_id += field_delta as i16;
190 } else {
191 self.last_read_field_id = self.read_i16()?;
192 };
193
Allen Georgeef7a1892018-12-16 18:01:37 -0500194 Ok(TFieldIdentifier {
195 name: None,
196 field_type: field_type,
197 id: Some(self.last_read_field_id),
198 })
Allen George8b96bfb2016-11-02 08:01:08 -0400199 }
200 }
201 }
202
203 fn read_field_end(&mut self) -> ::Result<()> {
204 Ok(())
205 }
206
207 fn read_bool(&mut self) -> ::Result<bool> {
208 match self.pending_read_bool_value.take() {
209 Some(b) => Ok(b),
210 None => {
211 let b = self.read_byte()?;
212 match b {
213 0x01 => Ok(true),
214 0x02 => Ok(false),
Allen Georgeef7a1892018-12-16 18:01:37 -0500215 unkn => Err(::Error::Protocol(::ProtocolError {
216 kind: ::ProtocolErrorKind::InvalidData,
217 message: format!("cannot convert {} into bool", unkn),
218 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400219 }
220 }
221 }
222 }
223
224 fn read_bytes(&mut self) -> ::Result<Vec<u8>> {
Allen George0e22c362017-01-30 07:15:00 -0500225 let len = self.transport.read_varint::<u32>()?;
Allen George8b96bfb2016-11-02 08:01:08 -0400226 let mut buf = vec![0u8; len as usize];
Allen George0e22c362017-01-30 07:15:00 -0500227 self.transport
228 .read_exact(&mut buf)
229 .map_err(From::from)
230 .map(|_| buf)
Allen George8b96bfb2016-11-02 08:01:08 -0400231 }
232
233 fn read_i8(&mut self) -> ::Result<i8> {
234 self.read_byte().map(|i| i as i8)
235 }
236
237 fn read_i16(&mut self) -> ::Result<i16> {
Allen George0e22c362017-01-30 07:15:00 -0500238 self.transport.read_varint::<i16>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400239 }
240
241 fn read_i32(&mut self) -> ::Result<i32> {
Allen George0e22c362017-01-30 07:15:00 -0500242 self.transport.read_varint::<i32>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400243 }
244
245 fn read_i64(&mut self) -> ::Result<i64> {
Allen George0e22c362017-01-30 07:15:00 -0500246 self.transport.read_varint::<i64>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400247 }
248
249 fn read_double(&mut self) -> ::Result<f64> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500250 self.transport.read_f64::<BigEndian>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400251 }
252
253 fn read_string(&mut self) -> ::Result<String> {
254 let bytes = self.read_bytes()?;
255 String::from_utf8(bytes).map_err(From::from)
256 }
257
258 fn read_list_begin(&mut self) -> ::Result<TListIdentifier> {
259 let (element_type, element_count) = self.read_list_set_begin()?;
260 Ok(TListIdentifier::new(element_type, element_count))
261 }
262
263 fn read_list_end(&mut self) -> ::Result<()> {
264 Ok(())
265 }
266
267 fn read_set_begin(&mut self) -> ::Result<TSetIdentifier> {
268 let (element_type, element_count) = self.read_list_set_begin()?;
269 Ok(TSetIdentifier::new(element_type, element_count))
270 }
271
272 fn read_set_end(&mut self) -> ::Result<()> {
273 Ok(())
274 }
275
276 fn read_map_begin(&mut self) -> ::Result<TMapIdentifier> {
Allen George0e22c362017-01-30 07:15:00 -0500277 let element_count = self.transport.read_varint::<u32>()? as i32;
Allen George8b96bfb2016-11-02 08:01:08 -0400278 if element_count == 0 {
279 Ok(TMapIdentifier::new(None, None, 0))
280 } else {
281 let type_header = self.read_byte()?;
282 let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
283 let val_type = collection_u8_to_type(type_header & 0x0F)?;
284 Ok(TMapIdentifier::new(key_type, val_type, element_count))
285 }
286 }
287
288 fn read_map_end(&mut self) -> ::Result<()> {
289 Ok(())
290 }
291
292 // utility
293 //
294
295 fn read_byte(&mut self) -> ::Result<u8> {
296 let mut buf = [0u8; 1];
Allen George0e22c362017-01-30 07:15:00 -0500297 self.transport
298 .read_exact(&mut buf)
299 .map_err(From::from)
300 .map(|_| buf[0])
Allen George8b96bfb2016-11-02 08:01:08 -0400301 }
302}
303
Vadim Chekand3355af2018-01-05 23:12:47 -0500304impl<T> io::Seek for TCompactInputProtocol<T>
305where
306 T: io::Seek + TReadTransport,
307{
308 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
309 self.transport.seek(pos)
310 }
311}
312
Allen George8b96bfb2016-11-02 08:01:08 -0400313/// Factory for creating instances of `TCompactInputProtocol`.
314#[derive(Default)]
315pub struct TCompactInputProtocolFactory;
316
317impl TCompactInputProtocolFactory {
318 /// Create a `TCompactInputProtocolFactory`.
319 pub fn new() -> TCompactInputProtocolFactory {
320 TCompactInputProtocolFactory {}
321 }
322}
323
324impl TInputProtocolFactory for TCompactInputProtocolFactory {
Allen George0e22c362017-01-30 07:15:00 -0500325 fn create(&self, transport: Box<TReadTransport + Send>) -> Box<TInputProtocol + Send> {
326 Box::new(TCompactInputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400327 }
328}
329
330/// Write messages using the Thrift compact protocol.
331///
332/// # Examples
333///
334/// Create and use a `TCompactOutputProtocol`.
335///
336/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -0400337/// use thrift::protocol::{TCompactOutputProtocol, TOutputProtocol};
Allen George0e22c362017-01-30 07:15:00 -0500338/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -0400339///
Allen George0e22c362017-01-30 07:15:00 -0500340/// let mut channel = TTcpChannel::new();
341/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400342///
Allen George0e22c362017-01-30 07:15:00 -0500343/// let mut protocol = TCompactOutputProtocol::new(channel);
Allen George8b96bfb2016-11-02 08:01:08 -0400344///
Allen George0e22c362017-01-30 07:15:00 -0500345/// protocol.write_bool(true).unwrap();
346/// protocol.write_string("test_string").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400347/// ```
Allen George0e22c362017-01-30 07:15:00 -0500348#[derive(Debug)]
349pub struct TCompactOutputProtocol<T>
350where
351 T: TWriteTransport,
352{
Allen George8b96bfb2016-11-02 08:01:08 -0400353 // Identifier of the last field serialized for a struct.
354 last_write_field_id: i16,
Allen George0e22c362017-01-30 07:15:00 -0500355 // Stack of the last written field ids (new entry added each time a nested struct is written).
Allen George8b96bfb2016-11-02 08:01:08 -0400356 write_field_id_stack: Vec<i16>,
357 // Field identifier of the boolean field to be written.
358 // Saved because boolean fields and their value are encoded in a single byte
359 pending_write_bool_field_identifier: Option<TFieldIdentifier>,
360 // Underlying transport used for byte-level operations.
Allen George0e22c362017-01-30 07:15:00 -0500361 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -0400362}
363
Allen George0e22c362017-01-30 07:15:00 -0500364impl<T> TCompactOutputProtocol<T>
365where
366 T: TWriteTransport,
367{
Allen George8b96bfb2016-11-02 08:01:08 -0400368 /// Create a `TCompactOutputProtocol` that writes bytes to `transport`.
Allen George0e22c362017-01-30 07:15:00 -0500369 pub fn new(transport: T) -> TCompactOutputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -0400370 TCompactOutputProtocol {
371 last_write_field_id: 0,
372 write_field_id_stack: Vec::new(),
373 pending_write_bool_field_identifier: None,
374 transport: transport,
375 }
376 }
377
378 // FIXME: field_type as unconstrained u8 is bad
379 fn write_field_header(&mut self, field_type: u8, field_id: i16) -> ::Result<()> {
380 let field_delta = field_id - self.last_write_field_id;
381 if field_delta > 0 && field_delta < 15 {
382 self.write_byte(((field_delta as u8) << 4) | field_type)?;
383 } else {
384 self.write_byte(field_type)?;
385 self.write_i16(field_id)?;
386 }
387 self.last_write_field_id = field_id;
388 Ok(())
389 }
390
391 fn write_list_set_begin(&mut self, element_type: TType, element_count: i32) -> ::Result<()> {
392 let elem_identifier = collection_type_to_u8(element_type);
393 if element_count <= 14 {
394 let header = (element_count as u8) << 4 | elem_identifier;
395 self.write_byte(header)
396 } else {
397 let header = 0xF0 | elem_identifier;
398 self.write_byte(header)?;
399 self.transport
Allen George8b96bfb2016-11-02 08:01:08 -0400400 .write_varint(element_count as u32)
401 .map_err(From::from)
402 .map(|_| ())
403 }
404 }
405
406 fn assert_no_pending_bool_write(&self) {
407 if let Some(ref f) = self.pending_write_bool_field_identifier {
408 panic!("pending bool field {:?} not written", f)
409 }
410 }
411}
412
Allen George0e22c362017-01-30 07:15:00 -0500413impl<T> TOutputProtocol for TCompactOutputProtocol<T>
414where
415 T: TWriteTransport,
416{
Allen George8b96bfb2016-11-02 08:01:08 -0400417 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> ::Result<()> {
418 self.write_byte(COMPACT_PROTOCOL_ID)?;
419 self.write_byte((u8::from(identifier.message_type) << 5) | COMPACT_VERSION)?;
420 self.write_i32(identifier.sequence_number)?;
421 self.write_string(&identifier.name)?;
422 Ok(())
423 }
424
425 fn write_message_end(&mut self) -> ::Result<()> {
426 self.assert_no_pending_bool_write();
427 Ok(())
428 }
429
430 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> ::Result<()> {
431 self.write_field_id_stack.push(self.last_write_field_id);
432 self.last_write_field_id = 0;
433 Ok(())
434 }
435
436 fn write_struct_end(&mut self) -> ::Result<()> {
437 self.assert_no_pending_bool_write();
Allen Georgeef7a1892018-12-16 18:01:37 -0500438 self.last_write_field_id = self
439 .write_field_id_stack
Allen George0e22c362017-01-30 07:15:00 -0500440 .pop()
441 .expect("should have previous field ids");
Allen George8b96bfb2016-11-02 08:01:08 -0400442 Ok(())
443 }
444
445 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> ::Result<()> {
446 match identifier.field_type {
447 TType::Bool => {
448 if self.pending_write_bool_field_identifier.is_some() {
Allen George0e22c362017-01-30 07:15:00 -0500449 panic!(
450 "should not have a pending bool while writing another bool with id: \
Allen Georgeef7a1892018-12-16 18:01:37 -0500451 {:?}",
Allen George0e22c362017-01-30 07:15:00 -0500452 identifier
453 )
Allen George8b96bfb2016-11-02 08:01:08 -0400454 }
455 self.pending_write_bool_field_identifier = Some(identifier.clone());
456 Ok(())
457 }
458 _ => {
459 let field_type = type_to_u8(identifier.field_type);
Allen Georgeef7a1892018-12-16 18:01:37 -0500460 let field_id = identifier.id.expect("non-stop field should have field id");
Allen George8b96bfb2016-11-02 08:01:08 -0400461 self.write_field_header(field_type, field_id)
462 }
463 }
464 }
465
466 fn write_field_end(&mut self) -> ::Result<()> {
467 self.assert_no_pending_bool_write();
468 Ok(())
469 }
470
471 fn write_field_stop(&mut self) -> ::Result<()> {
472 self.assert_no_pending_bool_write();
473 self.write_byte(type_to_u8(TType::Stop))
474 }
475
476 fn write_bool(&mut self, b: bool) -> ::Result<()> {
477 match self.pending_write_bool_field_identifier.take() {
478 Some(pending) => {
479 let field_id = pending.id.expect("bool field should have a field id");
480 let field_type_as_u8 = if b { 0x01 } else { 0x02 };
481 self.write_field_header(field_type_as_u8, field_id)
482 }
483 None => {
484 if b {
485 self.write_byte(0x01)
486 } else {
487 self.write_byte(0x02)
488 }
489 }
490 }
491 }
492
493 fn write_bytes(&mut self, b: &[u8]) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500494 self.transport.write_varint(b.len() as u32)?;
495 self.transport.write_all(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400496 }
497
498 fn write_i8(&mut self, i: i8) -> ::Result<()> {
499 self.write_byte(i as u8)
500 }
501
502 fn write_i16(&mut self, i: i16) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500503 self.transport
504 .write_varint(i)
505 .map_err(From::from)
506 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400507 }
508
509 fn write_i32(&mut self, i: i32) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500510 self.transport
511 .write_varint(i)
512 .map_err(From::from)
513 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400514 }
515
516 fn write_i64(&mut self, i: i64) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500517 self.transport
518 .write_varint(i)
519 .map_err(From::from)
520 .map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400521 }
522
523 fn write_double(&mut self, d: f64) -> ::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500524 self.transport.write_f64::<BigEndian>(d).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400525 }
526
527 fn write_string(&mut self, s: &str) -> ::Result<()> {
528 self.write_bytes(s.as_bytes())
529 }
530
531 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> ::Result<()> {
532 self.write_list_set_begin(identifier.element_type, identifier.size)
533 }
534
535 fn write_list_end(&mut self) -> ::Result<()> {
536 Ok(())
537 }
538
539 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> ::Result<()> {
540 self.write_list_set_begin(identifier.element_type, identifier.size)
541 }
542
543 fn write_set_end(&mut self) -> ::Result<()> {
544 Ok(())
545 }
546
547 fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> ::Result<()> {
548 if identifier.size == 0 {
549 self.write_byte(0)
550 } else {
Allen George0e22c362017-01-30 07:15:00 -0500551 self.transport.write_varint(identifier.size as u32)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400552
Allen George0e22c362017-01-30 07:15:00 -0500553 let key_type = identifier
554 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400555 .expect("map identifier to write should contain key type");
556 let key_type_byte = collection_type_to_u8(key_type) << 4;
557
Allen George0e22c362017-01-30 07:15:00 -0500558 let val_type = identifier
559 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400560 .expect("map identifier to write should contain value type");
561 let val_type_byte = collection_type_to_u8(val_type);
562
563 let map_type_header = key_type_byte | val_type_byte;
564 self.write_byte(map_type_header)
565 }
566 }
567
568 fn write_map_end(&mut self) -> ::Result<()> {
569 Ok(())
570 }
571
572 fn flush(&mut self) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500573 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400574 }
575
576 // utility
577 //
578
579 fn write_byte(&mut self, b: u8) -> ::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500580 self.transport.write(&[b]).map_err(From::from).map(|_| ())
Allen George8b96bfb2016-11-02 08:01:08 -0400581 }
582}
583
584/// Factory for creating instances of `TCompactOutputProtocol`.
585#[derive(Default)]
586pub struct TCompactOutputProtocolFactory;
587
588impl TCompactOutputProtocolFactory {
589 /// Create a `TCompactOutputProtocolFactory`.
590 pub fn new() -> TCompactOutputProtocolFactory {
591 TCompactOutputProtocolFactory {}
592 }
593}
594
595impl TOutputProtocolFactory for TCompactOutputProtocolFactory {
Allen George0e22c362017-01-30 07:15:00 -0500596 fn create(&self, transport: Box<TWriteTransport + Send>) -> Box<TOutputProtocol + Send> {
597 Box::new(TCompactOutputProtocol::new(transport))
Allen George8b96bfb2016-11-02 08:01:08 -0400598 }
599}
600
601fn collection_type_to_u8(field_type: TType) -> u8 {
602 match field_type {
603 TType::Bool => 0x01,
604 f => type_to_u8(f),
605 }
606}
607
608fn type_to_u8(field_type: TType) -> u8 {
609 match field_type {
610 TType::Stop => 0x00,
611 TType::I08 => 0x03, // equivalent to TType::Byte
612 TType::I16 => 0x04,
613 TType::I32 => 0x05,
614 TType::I64 => 0x06,
615 TType::Double => 0x07,
616 TType::String => 0x08,
617 TType::List => 0x09,
618 TType::Set => 0x0A,
619 TType::Map => 0x0B,
620 TType::Struct => 0x0C,
Allen Georgeef7a1892018-12-16 18:01:37 -0500621 _ => panic!(format!(
622 "should not have attempted to convert {} to u8",
623 field_type
624 )),
Allen George8b96bfb2016-11-02 08:01:08 -0400625 }
626}
627
628fn collection_u8_to_type(b: u8) -> ::Result<TType> {
629 match b {
630 0x01 => Ok(TType::Bool),
631 o => u8_to_type(o),
632 }
633}
634
635fn u8_to_type(b: u8) -> ::Result<TType> {
636 match b {
637 0x00 => Ok(TType::Stop),
638 0x03 => Ok(TType::I08), // equivalent to TType::Byte
639 0x04 => Ok(TType::I16),
640 0x05 => Ok(TType::I32),
641 0x06 => Ok(TType::I64),
642 0x07 => Ok(TType::Double),
643 0x08 => Ok(TType::String),
644 0x09 => Ok(TType::List),
645 0x0A => Ok(TType::Set),
646 0x0B => Ok(TType::Map),
647 0x0C => Ok(TType::Struct),
Allen Georgeef7a1892018-12-16 18:01:37 -0500648 unkn => Err(::Error::Protocol(::ProtocolError {
649 kind: ::ProtocolErrorKind::InvalidData,
650 message: format!("cannot convert {} into TType", unkn),
651 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400652 }
653}
654
655#[cfg(test)]
656mod tests {
657
Allen Georgeef7a1892018-12-16 18:01:37 -0500658 use protocol::{
659 TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
660 TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
661 };
Allen George0e22c362017-01-30 07:15:00 -0500662 use transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400663
664 use super::*;
665
666 #[test]
667 fn must_write_message_begin_0() {
Allen George0e22c362017-01-30 07:15:00 -0500668 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400669
Allen Georgeef7a1892018-12-16 18:01:37 -0500670 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
671 "foo",
672 TMessageType::Call,
673 431
674 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400675
Allen Georgeef7a1892018-12-16 18:01:37 -0500676 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -0500677 let expected: [u8; 8] = [
678 0x82, /* protocol ID */
679 0x21, /* message type | protocol version */
680 0xDE,
681 0x06, /* zig-zag varint sequence number */
682 0x03, /* message-name length */
683 0x66,
684 0x6F,
685 0x6F /* "foo" */,
686 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400687
Allen George0e22c362017-01-30 07:15:00 -0500688 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400689 }
690
691 #[test]
692 fn must_write_message_begin_1() {
Allen George0e22c362017-01-30 07:15:00 -0500693 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400694
Allen Georgeef7a1892018-12-16 18:01:37 -0500695 assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
696 "bar",
697 TMessageType::Reply,
698 991828
699 )));
Allen George8b96bfb2016-11-02 08:01:08 -0400700
Allen Georgeef7a1892018-12-16 18:01:37 -0500701 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -0500702 let expected: [u8; 9] = [
703 0x82, /* protocol ID */
704 0x41, /* message type | protocol version */
705 0xA8,
706 0x89,
707 0x79, /* zig-zag varint sequence number */
708 0x03, /* message-name length */
709 0x62,
710 0x61,
711 0x72 /* "bar" */,
712 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400713
Allen George0e22c362017-01-30 07:15:00 -0500714 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400715 }
716
717 #[test]
718 fn must_round_trip_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500719 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400720
721 let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1283948);
722
723 assert_success!(o_prot.write_message_begin(&ident));
724
Allen George0e22c362017-01-30 07:15:00 -0500725 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400726
727 let res = assert_success!(i_prot.read_message_begin());
728 assert_eq!(&res, &ident);
729 }
730
731 #[test]
732 fn must_write_message_end() {
733 assert_no_write(|o| o.write_message_end());
734 }
735
736 // NOTE: structs and fields are tested together
737 //
738
739 #[test]
740 fn must_write_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500741 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400742
743 // no bytes should be written however
744 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
745
746 // write three fields with tiny field ids
747 // since they're small the field ids will be encoded as deltas
748
749 // since this is the first field (and it's zero) it gets the full varint write
750 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
751 assert_success!(o_prot.write_field_end());
752
753 // since this delta > 0 and < 15 it can be encoded as a delta
754 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
755 assert_success!(o_prot.write_field_end());
756
757 // since this delta > 0 and < 15 it can be encoded as a delta
758 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
759 assert_success!(o_prot.write_field_end());
760
761 // now, finish the struct off
762 assert_success!(o_prot.write_field_stop());
763 assert_success!(o_prot.write_struct_end());
764
Allen Georgeef7a1892018-12-16 18:01:37 -0500765 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -0500766 let expected: [u8; 5] = [
767 0x03, /* field type */
768 0x00, /* first field id */
769 0x44, /* field delta (4) | field type */
770 0x59, /* field delta (5) | field type */
771 0x00 /* field stop */,
772 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400773
Allen George0e22c362017-01-30 07:15:00 -0500774 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400775 }
776
777 #[test]
778 fn must_round_trip_struct_with_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500779 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400780
781 // no bytes should be written however
782 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
783
784 // write three fields with tiny field ids
785 // since they're small the field ids will be encoded as deltas
786
787 // since this is the first field (and it's zero) it gets the full varint write
788 let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
789 assert_success!(o_prot.write_field_begin(&field_ident_1));
790 assert_success!(o_prot.write_field_end());
791
792 // since this delta > 0 and < 15 it can be encoded as a delta
793 let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
794 assert_success!(o_prot.write_field_begin(&field_ident_2));
795 assert_success!(o_prot.write_field_end());
796
797 // since this delta > 0 and < 15 it can be encoded as a delta
798 let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
799 assert_success!(o_prot.write_field_begin(&field_ident_3));
800 assert_success!(o_prot.write_field_end());
801
802 // now, finish the struct off
803 assert_success!(o_prot.write_field_stop());
804 assert_success!(o_prot.write_struct_end());
805
Allen George0e22c362017-01-30 07:15:00 -0500806 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400807
808 // read the struct back
809 assert_success!(i_prot.read_struct_begin());
810
811 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500812 assert_eq!(
813 read_ident_1,
814 TFieldIdentifier {
815 name: None,
816 ..field_ident_1
817 }
818 );
Allen George8b96bfb2016-11-02 08:01:08 -0400819 assert_success!(i_prot.read_field_end());
820
821 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500822 assert_eq!(
823 read_ident_2,
824 TFieldIdentifier {
825 name: None,
826 ..field_ident_2
827 }
828 );
Allen George8b96bfb2016-11-02 08:01:08 -0400829 assert_success!(i_prot.read_field_end());
830
831 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500832 assert_eq!(
833 read_ident_3,
834 TFieldIdentifier {
835 name: None,
836 ..field_ident_3
837 }
838 );
Allen George8b96bfb2016-11-02 08:01:08 -0400839 assert_success!(i_prot.read_field_end());
840
841 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500842 assert_eq!(
843 read_ident_4,
844 TFieldIdentifier {
845 name: None,
846 field_type: TType::Stop,
847 id: None,
848 }
849 );
Allen George8b96bfb2016-11-02 08:01:08 -0400850
851 assert_success!(i_prot.read_struct_end());
852 }
853
854 #[test]
855 fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500856 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400857
858 // no bytes should be written however
859 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
860
861 // write three fields with tiny field ids
862 // since they're small the field ids will be encoded as deltas
863
864 // gets a delta write
865 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
866 assert_success!(o_prot.write_field_end());
867
868 // since this delta > 0 and < 15 it can be encoded as a delta
869 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
870 assert_success!(o_prot.write_field_end());
871
872 // since this delta > 0 and < 15 it can be encoded as a delta
873 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
874 assert_success!(o_prot.write_field_end());
875
876 // now, finish the struct off
877 assert_success!(o_prot.write_field_stop());
878 assert_success!(o_prot.write_struct_end());
879
Allen Georgeef7a1892018-12-16 18:01:37 -0500880 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -0500881 let expected: [u8; 4] = [
882 0x15, /* field delta (1) | field type */
883 0x1A, /* field delta (1) | field type */
884 0x48, /* field delta (4) | field type */
885 0x00 /* field stop */,
886 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400887
Allen George0e22c362017-01-30 07:15:00 -0500888 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400889 }
890
891 #[test]
892 fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500893 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400894
895 // no bytes should be written however
896 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
897
898 // write three fields with tiny field ids
899 // since they're small the field ids will be encoded as deltas
900
901 // gets a delta write
902 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
903 assert_success!(o_prot.write_field_begin(&field_ident_1));
904 assert_success!(o_prot.write_field_end());
905
906 // since this delta > 0 and < 15 it can be encoded as a delta
907 let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
908 assert_success!(o_prot.write_field_begin(&field_ident_2));
909 assert_success!(o_prot.write_field_end());
910
911 // since this delta > 0 and < 15 it can be encoded as a delta
912 let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
913 assert_success!(o_prot.write_field_begin(&field_ident_3));
914 assert_success!(o_prot.write_field_end());
915
916 // now, finish the struct off
917 assert_success!(o_prot.write_field_stop());
918 assert_success!(o_prot.write_struct_end());
919
Allen George0e22c362017-01-30 07:15:00 -0500920 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400921
922 // read the struct back
923 assert_success!(i_prot.read_struct_begin());
924
925 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500926 assert_eq!(
927 read_ident_1,
928 TFieldIdentifier {
929 name: None,
930 ..field_ident_1
931 }
932 );
Allen George8b96bfb2016-11-02 08:01:08 -0400933 assert_success!(i_prot.read_field_end());
934
935 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500936 assert_eq!(
937 read_ident_2,
938 TFieldIdentifier {
939 name: None,
940 ..field_ident_2
941 }
942 );
Allen George8b96bfb2016-11-02 08:01:08 -0400943 assert_success!(i_prot.read_field_end());
944
945 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500946 assert_eq!(
947 read_ident_3,
948 TFieldIdentifier {
949 name: None,
950 ..field_ident_3
951 }
952 );
Allen George8b96bfb2016-11-02 08:01:08 -0400953 assert_success!(i_prot.read_field_end());
954
955 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -0500956 assert_eq!(
957 read_ident_4,
958 TFieldIdentifier {
959 name: None,
960 field_type: TType::Stop,
961 id: None,
962 }
963 );
Allen George8b96bfb2016-11-02 08:01:08 -0400964
965 assert_success!(i_prot.read_struct_end());
966 }
967
968 #[test]
969 fn must_write_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -0500970 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400971
972 // no bytes should be written however
973 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
974
975 // write three fields with field ids that cannot be encoded as deltas
976
977 // since this is the first field (and it's zero) it gets the full varint write
978 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
979 assert_success!(o_prot.write_field_end());
980
981 // since this delta is > 15 it is encoded as a zig-zag varint
982 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
983 assert_success!(o_prot.write_field_end());
984
985 // since this delta is > 15 it is encoded as a zig-zag varint
986 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
987 assert_success!(o_prot.write_field_end());
988
989 // now, finish the struct off
990 assert_success!(o_prot.write_field_stop());
991 assert_success!(o_prot.write_struct_end());
992
Allen Georgeef7a1892018-12-16 18:01:37 -0500993 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -0500994 let expected: [u8; 8] = [
995 0x05, /* field type */
996 0x00, /* first field id */
997 0x06, /* field type */
998 0x20, /* zig-zag varint field id */
999 0x0A, /* field type */
1000 0xC6,
1001 0x01, /* zig-zag varint field id */
1002 0x00 /* field stop */,
1003 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001004
Allen George0e22c362017-01-30 07:15:00 -05001005 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001006 }
1007
1008 #[test]
1009 fn must_round_trip_struct_with_long_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001010 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001011
1012 // no bytes should be written however
1013 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1014
1015 // write three fields with field ids that cannot be encoded as deltas
1016
1017 // since this is the first field (and it's zero) it gets the full varint write
1018 let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
1019 assert_success!(o_prot.write_field_begin(&field_ident_1));
1020 assert_success!(o_prot.write_field_end());
1021
1022 // since this delta is > 15 it is encoded as a zig-zag varint
1023 let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
1024 assert_success!(o_prot.write_field_begin(&field_ident_2));
1025 assert_success!(o_prot.write_field_end());
1026
1027 // since this delta is > 15 it is encoded as a zig-zag varint
1028 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
1029 assert_success!(o_prot.write_field_begin(&field_ident_3));
1030 assert_success!(o_prot.write_field_end());
1031
1032 // now, finish the struct off
1033 assert_success!(o_prot.write_field_stop());
1034 assert_success!(o_prot.write_struct_end());
1035
Allen George0e22c362017-01-30 07:15:00 -05001036 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001037
1038 // read the struct back
1039 assert_success!(i_prot.read_struct_begin());
1040
1041 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001042 assert_eq!(
1043 read_ident_1,
1044 TFieldIdentifier {
1045 name: None,
1046 ..field_ident_1
1047 }
1048 );
Allen George8b96bfb2016-11-02 08:01:08 -04001049 assert_success!(i_prot.read_field_end());
1050
1051 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001052 assert_eq!(
1053 read_ident_2,
1054 TFieldIdentifier {
1055 name: None,
1056 ..field_ident_2
1057 }
1058 );
Allen George8b96bfb2016-11-02 08:01:08 -04001059 assert_success!(i_prot.read_field_end());
1060
1061 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001062 assert_eq!(
1063 read_ident_3,
1064 TFieldIdentifier {
1065 name: None,
1066 ..field_ident_3
1067 }
1068 );
Allen George8b96bfb2016-11-02 08:01:08 -04001069 assert_success!(i_prot.read_field_end());
1070
1071 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001072 assert_eq!(
1073 read_ident_4,
1074 TFieldIdentifier {
1075 name: None,
1076 field_type: TType::Stop,
1077 id: None,
1078 }
1079 );
Allen George8b96bfb2016-11-02 08:01:08 -04001080
1081 assert_success!(i_prot.read_struct_end());
1082 }
1083
1084 #[test]
1085 fn must_write_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001086 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001087
1088 // no bytes should be written however
1089 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1090
1091 // write three fields with field ids that cannot be encoded as deltas
1092
1093 // since the delta is > 0 and < 15 it gets a delta write
1094 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1095 assert_success!(o_prot.write_field_end());
1096
1097 // since this delta > 0 and < 15 it gets a delta write
1098 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1099 assert_success!(o_prot.write_field_end());
1100
1101 // since this delta is > 15 it is encoded as a zig-zag varint
1102 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
1103 assert_success!(o_prot.write_field_end());
1104
1105 // since this delta is > 15 it is encoded as a zig-zag varint
1106 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
1107 assert_success!(o_prot.write_field_end());
1108
1109 // since this is only 3 up from the previous it is recorded as a delta
1110 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
1111 assert_success!(o_prot.write_field_end());
1112
1113 // now, finish the struct off
1114 assert_success!(o_prot.write_field_stop());
1115 assert_success!(o_prot.write_struct_end());
1116
Allen Georgeef7a1892018-12-16 18:01:37 -05001117 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -05001118 let expected: [u8; 10] = [
1119 0x16, /* field delta (1) | field type */
1120 0x85, /* field delta (8) | field type */
1121 0x0A, /* field type */
1122 0xD0,
1123 0x0F, /* zig-zag varint field id */
1124 0x0A, /* field type */
1125 0xA2,
1126 0x1F, /* zig-zag varint field id */
1127 0x3A, /* field delta (3) | field type */
1128 0x00 /* field stop */,
1129 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001130
Allen George0e22c362017-01-30 07:15:00 -05001131 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001132 }
1133
1134 #[test]
1135 fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
Allen George0e22c362017-01-30 07:15:00 -05001136 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001137
1138 // no bytes should be written however
1139 let struct_ident = TStructIdentifier::new("foo");
1140 assert_success!(o_prot.write_struct_begin(&struct_ident));
1141
1142 // write three fields with field ids that cannot be encoded as deltas
1143
1144 // since the delta is > 0 and < 15 it gets a delta write
1145 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1146 assert_success!(o_prot.write_field_begin(&field_ident_1));
1147 assert_success!(o_prot.write_field_end());
1148
1149 // since this delta > 0 and < 15 it gets a delta write
1150 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1151 assert_success!(o_prot.write_field_begin(&field_ident_2));
1152 assert_success!(o_prot.write_field_end());
1153
1154 // since this delta is > 15 it is encoded as a zig-zag varint
1155 let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
1156 assert_success!(o_prot.write_field_begin(&field_ident_3));
1157 assert_success!(o_prot.write_field_end());
1158
1159 // since this delta is > 15 it is encoded as a zig-zag varint
1160 let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
1161 assert_success!(o_prot.write_field_begin(&field_ident_4));
1162 assert_success!(o_prot.write_field_end());
1163
1164 // since this is only 3 up from the previous it is recorded as a delta
1165 let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
1166 assert_success!(o_prot.write_field_begin(&field_ident_5));
1167 assert_success!(o_prot.write_field_end());
1168
1169 // now, finish the struct off
1170 assert_success!(o_prot.write_field_stop());
1171 assert_success!(o_prot.write_struct_end());
1172
Allen George0e22c362017-01-30 07:15:00 -05001173 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001174
1175 // read the struct back
1176 assert_success!(i_prot.read_struct_begin());
1177
1178 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001179 assert_eq!(
1180 read_ident_1,
1181 TFieldIdentifier {
1182 name: None,
1183 ..field_ident_1
1184 }
1185 );
Allen George8b96bfb2016-11-02 08:01:08 -04001186 assert_success!(i_prot.read_field_end());
1187
1188 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001189 assert_eq!(
1190 read_ident_2,
1191 TFieldIdentifier {
1192 name: None,
1193 ..field_ident_2
1194 }
1195 );
Allen George8b96bfb2016-11-02 08:01:08 -04001196 assert_success!(i_prot.read_field_end());
1197
1198 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001199 assert_eq!(
1200 read_ident_3,
1201 TFieldIdentifier {
1202 name: None,
1203 ..field_ident_3
1204 }
1205 );
Allen George8b96bfb2016-11-02 08:01:08 -04001206 assert_success!(i_prot.read_field_end());
1207
1208 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001209 assert_eq!(
1210 read_ident_4,
1211 TFieldIdentifier {
1212 name: None,
1213 ..field_ident_4
1214 }
1215 );
Allen George8b96bfb2016-11-02 08:01:08 -04001216 assert_success!(i_prot.read_field_end());
1217
1218 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001219 assert_eq!(
1220 read_ident_5,
1221 TFieldIdentifier {
1222 name: None,
1223 ..field_ident_5
1224 }
1225 );
Allen George8b96bfb2016-11-02 08:01:08 -04001226 assert_success!(i_prot.read_field_end());
1227
1228 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001229 assert_eq!(
1230 read_ident_6,
1231 TFieldIdentifier {
1232 name: None,
1233 field_type: TType::Stop,
1234 id: None,
1235 }
1236 );
Allen George8b96bfb2016-11-02 08:01:08 -04001237
1238 assert_success!(i_prot.read_struct_end());
1239 }
1240
1241 #[test]
1242 fn must_write_nested_structs_0() {
1243 // last field of the containing struct is a delta
1244 // first field of the the contained struct is a delta
1245
Allen George0e22c362017-01-30 07:15:00 -05001246 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001247
1248 // start containing struct
1249 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1250
1251 // containing struct
1252 // since the delta is > 0 and < 15 it gets a delta write
1253 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1254 assert_success!(o_prot.write_field_end());
1255
1256 // containing struct
1257 // since this delta > 0 and < 15 it gets a delta write
1258 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1259 assert_success!(o_prot.write_field_end());
1260
1261 // start contained struct
1262 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1263
1264 // contained struct
1265 // since the delta is > 0 and < 15 it gets a delta write
1266 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
1267 assert_success!(o_prot.write_field_end());
1268
1269 // contained struct
1270 // since this delta > 15 it gets a full write
1271 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1272 assert_success!(o_prot.write_field_end());
1273
1274 // end contained struct
1275 assert_success!(o_prot.write_field_stop());
1276 assert_success!(o_prot.write_struct_end());
1277
1278 // end containing struct
1279 assert_success!(o_prot.write_field_stop());
1280 assert_success!(o_prot.write_struct_end());
1281
Allen Georgeef7a1892018-12-16 18:01:37 -05001282 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -05001283 let expected: [u8; 7] = [
1284 0x16, /* field delta (1) | field type */
1285 0x85, /* field delta (8) | field type */
1286 0x73, /* field delta (7) | field type */
1287 0x07, /* field type */
1288 0x30, /* zig-zag varint field id */
1289 0x00, /* field stop - contained */
1290 0x00 /* field stop - containing */,
1291 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001292
Allen George0e22c362017-01-30 07:15:00 -05001293 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001294 }
1295
1296 #[test]
1297 fn must_round_trip_nested_structs_0() {
1298 // last field of the containing struct is a delta
1299 // first field of the the contained struct is a delta
1300
Allen George0e22c362017-01-30 07:15:00 -05001301 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001302
1303 // start containing struct
1304 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1305
1306 // containing struct
1307 // since the delta is > 0 and < 15 it gets a delta write
1308 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1309 assert_success!(o_prot.write_field_begin(&field_ident_1));
1310 assert_success!(o_prot.write_field_end());
1311
1312 // containing struct
1313 // since this delta > 0 and < 15 it gets a delta write
1314 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1315 assert_success!(o_prot.write_field_begin(&field_ident_2));
1316 assert_success!(o_prot.write_field_end());
1317
1318 // start contained struct
1319 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1320
1321 // contained struct
1322 // since the delta is > 0 and < 15 it gets a delta write
1323 let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
1324 assert_success!(o_prot.write_field_begin(&field_ident_3));
1325 assert_success!(o_prot.write_field_end());
1326
1327 // contained struct
1328 // since this delta > 15 it gets a full write
1329 let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
1330 assert_success!(o_prot.write_field_begin(&field_ident_4));
1331 assert_success!(o_prot.write_field_end());
1332
1333 // end contained struct
1334 assert_success!(o_prot.write_field_stop());
1335 assert_success!(o_prot.write_struct_end());
1336
1337 // end containing struct
1338 assert_success!(o_prot.write_field_stop());
1339 assert_success!(o_prot.write_struct_end());
1340
Allen George0e22c362017-01-30 07:15:00 -05001341 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001342
1343 // read containing struct back
1344 assert_success!(i_prot.read_struct_begin());
1345
1346 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001347 assert_eq!(
1348 read_ident_1,
1349 TFieldIdentifier {
1350 name: None,
1351 ..field_ident_1
1352 }
1353 );
Allen George8b96bfb2016-11-02 08:01:08 -04001354 assert_success!(i_prot.read_field_end());
1355
1356 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001357 assert_eq!(
1358 read_ident_2,
1359 TFieldIdentifier {
1360 name: None,
1361 ..field_ident_2
1362 }
1363 );
Allen George8b96bfb2016-11-02 08:01:08 -04001364 assert_success!(i_prot.read_field_end());
1365
1366 // read contained struct back
1367 assert_success!(i_prot.read_struct_begin());
1368
1369 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001370 assert_eq!(
1371 read_ident_3,
1372 TFieldIdentifier {
1373 name: None,
1374 ..field_ident_3
1375 }
1376 );
Allen George8b96bfb2016-11-02 08:01:08 -04001377 assert_success!(i_prot.read_field_end());
1378
1379 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001380 assert_eq!(
1381 read_ident_4,
1382 TFieldIdentifier {
1383 name: None,
1384 ..field_ident_4
1385 }
1386 );
Allen George8b96bfb2016-11-02 08:01:08 -04001387 assert_success!(i_prot.read_field_end());
1388
1389 // end contained struct
1390 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001391 assert_eq!(
1392 read_ident_6,
1393 TFieldIdentifier {
1394 name: None,
1395 field_type: TType::Stop,
1396 id: None,
1397 }
1398 );
Allen George8b96bfb2016-11-02 08:01:08 -04001399 assert_success!(i_prot.read_struct_end());
1400
1401 // end containing struct
1402 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001403 assert_eq!(
1404 read_ident_7,
1405 TFieldIdentifier {
1406 name: None,
1407 field_type: TType::Stop,
1408 id: None,
1409 }
1410 );
Allen George8b96bfb2016-11-02 08:01:08 -04001411 assert_success!(i_prot.read_struct_end());
1412 }
1413
1414 #[test]
1415 fn must_write_nested_structs_1() {
1416 // last field of the containing struct is a delta
1417 // first field of the the contained struct is a full write
1418
Allen George0e22c362017-01-30 07:15:00 -05001419 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001420
1421 // start containing struct
1422 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1423
1424 // containing struct
1425 // since the delta is > 0 and < 15 it gets a delta write
1426 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1427 assert_success!(o_prot.write_field_end());
1428
1429 // containing struct
1430 // since this delta > 0 and < 15 it gets a delta write
1431 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1432 assert_success!(o_prot.write_field_end());
1433
1434 // start contained struct
1435 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1436
1437 // contained struct
1438 // since this delta > 15 it gets a full write
1439 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1440 assert_success!(o_prot.write_field_end());
1441
1442 // contained struct
1443 // since the delta is > 0 and < 15 it gets a delta write
1444 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1445 assert_success!(o_prot.write_field_end());
1446
1447 // end contained struct
1448 assert_success!(o_prot.write_field_stop());
1449 assert_success!(o_prot.write_struct_end());
1450
1451 // end containing struct
1452 assert_success!(o_prot.write_field_stop());
1453 assert_success!(o_prot.write_struct_end());
1454
Allen Georgeef7a1892018-12-16 18:01:37 -05001455 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -05001456 let expected: [u8; 7] = [
1457 0x16, /* field delta (1) | field type */
1458 0x85, /* field delta (8) | field type */
1459 0x07, /* field type */
1460 0x30, /* zig-zag varint field id */
1461 0x33, /* field delta (3) | field type */
1462 0x00, /* field stop - contained */
1463 0x00 /* field stop - containing */,
1464 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001465
Allen George0e22c362017-01-30 07:15:00 -05001466 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001467 }
1468
1469 #[test]
1470 fn must_round_trip_nested_structs_1() {
1471 // last field of the containing struct is a delta
1472 // first field of the the contained struct is a full write
1473
Allen George0e22c362017-01-30 07:15:00 -05001474 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001475
1476 // start containing struct
1477 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1478
1479 // containing struct
1480 // since the delta is > 0 and < 15 it gets a delta write
1481 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1482 assert_success!(o_prot.write_field_begin(&field_ident_1));
1483 assert_success!(o_prot.write_field_end());
1484
1485 // containing struct
1486 // since this delta > 0 and < 15 it gets a delta write
1487 let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1488 assert_success!(o_prot.write_field_begin(&field_ident_2));
1489 assert_success!(o_prot.write_field_end());
1490
1491 // start contained struct
1492 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1493
1494 // contained struct
1495 // since this delta > 15 it gets a full write
1496 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
1497 assert_success!(o_prot.write_field_begin(&field_ident_3));
1498 assert_success!(o_prot.write_field_end());
1499
1500 // contained struct
1501 // since the delta is > 0 and < 15 it gets a delta write
1502 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
1503 assert_success!(o_prot.write_field_begin(&field_ident_4));
1504 assert_success!(o_prot.write_field_end());
1505
1506 // end contained struct
1507 assert_success!(o_prot.write_field_stop());
1508 assert_success!(o_prot.write_struct_end());
1509
1510 // end containing struct
1511 assert_success!(o_prot.write_field_stop());
1512 assert_success!(o_prot.write_struct_end());
1513
Allen George0e22c362017-01-30 07:15:00 -05001514 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001515
1516 // read containing struct back
1517 assert_success!(i_prot.read_struct_begin());
1518
1519 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001520 assert_eq!(
1521 read_ident_1,
1522 TFieldIdentifier {
1523 name: None,
1524 ..field_ident_1
1525 }
1526 );
Allen George8b96bfb2016-11-02 08:01:08 -04001527 assert_success!(i_prot.read_field_end());
1528
1529 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001530 assert_eq!(
1531 read_ident_2,
1532 TFieldIdentifier {
1533 name: None,
1534 ..field_ident_2
1535 }
1536 );
Allen George8b96bfb2016-11-02 08:01:08 -04001537 assert_success!(i_prot.read_field_end());
1538
1539 // read contained struct back
1540 assert_success!(i_prot.read_struct_begin());
1541
1542 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001543 assert_eq!(
1544 read_ident_3,
1545 TFieldIdentifier {
1546 name: None,
1547 ..field_ident_3
1548 }
1549 );
Allen George8b96bfb2016-11-02 08:01:08 -04001550 assert_success!(i_prot.read_field_end());
1551
1552 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001553 assert_eq!(
1554 read_ident_4,
1555 TFieldIdentifier {
1556 name: None,
1557 ..field_ident_4
1558 }
1559 );
Allen George8b96bfb2016-11-02 08:01:08 -04001560 assert_success!(i_prot.read_field_end());
1561
1562 // end contained struct
1563 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001564 assert_eq!(
1565 read_ident_6,
1566 TFieldIdentifier {
1567 name: None,
1568 field_type: TType::Stop,
1569 id: None,
1570 }
1571 );
Allen George8b96bfb2016-11-02 08:01:08 -04001572 assert_success!(i_prot.read_struct_end());
1573
1574 // end containing struct
1575 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001576 assert_eq!(
1577 read_ident_7,
1578 TFieldIdentifier {
1579 name: None,
1580 field_type: TType::Stop,
1581 id: None,
1582 }
1583 );
Allen George8b96bfb2016-11-02 08:01:08 -04001584 assert_success!(i_prot.read_struct_end());
1585 }
1586
1587 #[test]
1588 fn must_write_nested_structs_2() {
1589 // last field of the containing struct is a full write
1590 // first field of the the contained struct is a delta write
1591
Allen George0e22c362017-01-30 07:15:00 -05001592 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001593
1594 // start containing struct
1595 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1596
1597 // containing struct
1598 // since the delta is > 0 and < 15 it gets a delta write
1599 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1600 assert_success!(o_prot.write_field_end());
1601
1602 // containing struct
1603 // since this delta > 15 it gets a full write
1604 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
1605 assert_success!(o_prot.write_field_end());
1606
1607 // start contained struct
1608 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1609
1610 // contained struct
1611 // since this delta > 0 and < 15 it gets a delta write
1612 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
1613 assert_success!(o_prot.write_field_end());
1614
1615 // contained struct
1616 // since the delta is > 0 and < 15 it gets a delta write
1617 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
1618 assert_success!(o_prot.write_field_end());
1619
1620 // end contained struct
1621 assert_success!(o_prot.write_field_stop());
1622 assert_success!(o_prot.write_struct_end());
1623
1624 // end containing struct
1625 assert_success!(o_prot.write_field_stop());
1626 assert_success!(o_prot.write_struct_end());
1627
Allen Georgeef7a1892018-12-16 18:01:37 -05001628 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -05001629 let expected: [u8; 7] = [
1630 0x16, /* field delta (1) | field type */
1631 0x08, /* field type */
1632 0x2A, /* zig-zag varint field id */
1633 0x77, /* field delta(7) | field type */
1634 0x33, /* field delta (3) | field type */
1635 0x00, /* field stop - contained */
1636 0x00 /* field stop - containing */,
1637 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001638
Allen George0e22c362017-01-30 07:15:00 -05001639 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001640 }
1641
1642 #[test]
1643 fn must_round_trip_nested_structs_2() {
Allen George0e22c362017-01-30 07:15:00 -05001644 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001645
1646 // start containing struct
1647 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1648
1649 // containing struct
1650 // since the delta is > 0 and < 15 it gets a delta write
1651 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1652 assert_success!(o_prot.write_field_begin(&field_ident_1));
1653 assert_success!(o_prot.write_field_end());
1654
1655 // containing struct
1656 // since this delta > 15 it gets a full write
1657 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
1658 assert_success!(o_prot.write_field_begin(&field_ident_2));
1659 assert_success!(o_prot.write_field_end());
1660
1661 // start contained struct
1662 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1663
1664 // contained struct
1665 // since this delta > 0 and < 15 it gets a delta write
1666 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
1667 assert_success!(o_prot.write_field_begin(&field_ident_3));
1668 assert_success!(o_prot.write_field_end());
1669
1670 // contained struct
1671 // since the delta is > 0 and < 15 it gets a delta write
1672 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
1673 assert_success!(o_prot.write_field_begin(&field_ident_4));
1674 assert_success!(o_prot.write_field_end());
1675
1676 // end contained struct
1677 assert_success!(o_prot.write_field_stop());
1678 assert_success!(o_prot.write_struct_end());
1679
1680 // end containing struct
1681 assert_success!(o_prot.write_field_stop());
1682 assert_success!(o_prot.write_struct_end());
1683
Allen George0e22c362017-01-30 07:15:00 -05001684 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001685
1686 // read containing struct back
1687 assert_success!(i_prot.read_struct_begin());
1688
1689 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001690 assert_eq!(
1691 read_ident_1,
1692 TFieldIdentifier {
1693 name: None,
1694 ..field_ident_1
1695 }
1696 );
Allen George8b96bfb2016-11-02 08:01:08 -04001697 assert_success!(i_prot.read_field_end());
1698
1699 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001700 assert_eq!(
1701 read_ident_2,
1702 TFieldIdentifier {
1703 name: None,
1704 ..field_ident_2
1705 }
1706 );
Allen George8b96bfb2016-11-02 08:01:08 -04001707 assert_success!(i_prot.read_field_end());
1708
1709 // read contained struct back
1710 assert_success!(i_prot.read_struct_begin());
1711
1712 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001713 assert_eq!(
1714 read_ident_3,
1715 TFieldIdentifier {
1716 name: None,
1717 ..field_ident_3
1718 }
1719 );
Allen George8b96bfb2016-11-02 08:01:08 -04001720 assert_success!(i_prot.read_field_end());
1721
1722 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001723 assert_eq!(
1724 read_ident_4,
1725 TFieldIdentifier {
1726 name: None,
1727 ..field_ident_4
1728 }
1729 );
Allen George8b96bfb2016-11-02 08:01:08 -04001730 assert_success!(i_prot.read_field_end());
1731
1732 // end contained struct
1733 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001734 assert_eq!(
1735 read_ident_6,
1736 TFieldIdentifier {
1737 name: None,
1738 field_type: TType::Stop,
1739 id: None,
1740 }
1741 );
Allen George8b96bfb2016-11-02 08:01:08 -04001742 assert_success!(i_prot.read_struct_end());
1743
1744 // end containing struct
1745 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001746 assert_eq!(
1747 read_ident_7,
1748 TFieldIdentifier {
1749 name: None,
1750 field_type: TType::Stop,
1751 id: None,
1752 }
1753 );
Allen George8b96bfb2016-11-02 08:01:08 -04001754 assert_success!(i_prot.read_struct_end());
1755 }
1756
1757 #[test]
1758 fn must_write_nested_structs_3() {
1759 // last field of the containing struct is a full write
1760 // first field of the the contained struct is a full write
1761
Allen George0e22c362017-01-30 07:15:00 -05001762 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001763
1764 // start containing struct
1765 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1766
1767 // containing struct
1768 // since the delta is > 0 and < 15 it gets a delta write
1769 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1770 assert_success!(o_prot.write_field_end());
1771
1772 // containing struct
1773 // since this delta > 15 it gets a full write
1774 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
1775 assert_success!(o_prot.write_field_end());
1776
1777 // start contained struct
1778 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1779
1780 // contained struct
1781 // since this delta > 15 it gets a full write
1782 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
1783 assert_success!(o_prot.write_field_end());
1784
1785 // contained struct
1786 // since the delta is > 0 and < 15 it gets a delta write
1787 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
1788 assert_success!(o_prot.write_field_end());
1789
1790 // end contained struct
1791 assert_success!(o_prot.write_field_stop());
1792 assert_success!(o_prot.write_struct_end());
1793
1794 // end containing struct
1795 assert_success!(o_prot.write_field_stop());
1796 assert_success!(o_prot.write_struct_end());
1797
Allen Georgeef7a1892018-12-16 18:01:37 -05001798 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -05001799 let expected: [u8; 8] = [
1800 0x16, /* field delta (1) | field type */
1801 0x08, /* field type */
1802 0x2A, /* zig-zag varint field id */
1803 0x07, /* field type */
1804 0x2A, /* zig-zag varint field id */
1805 0x63, /* field delta (6) | field type */
1806 0x00, /* field stop - contained */
1807 0x00 /* field stop - containing */,
1808 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001809
Allen George0e22c362017-01-30 07:15:00 -05001810 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001811 }
1812
1813 #[test]
1814 fn must_round_trip_nested_structs_3() {
1815 // last field of the containing struct is a full write
1816 // first field of the the contained struct is a full write
1817
Allen George0e22c362017-01-30 07:15:00 -05001818 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001819
1820 // start containing struct
1821 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1822
1823 // containing struct
1824 // since the delta is > 0 and < 15 it gets a delta write
1825 let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1826 assert_success!(o_prot.write_field_begin(&field_ident_1));
1827 assert_success!(o_prot.write_field_end());
1828
1829 // containing struct
1830 // since this delta > 15 it gets a full write
1831 let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
1832 assert_success!(o_prot.write_field_begin(&field_ident_2));
1833 assert_success!(o_prot.write_field_end());
1834
1835 // start contained struct
1836 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1837
1838 // contained struct
1839 // since this delta > 15 it gets a full write
1840 let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
1841 assert_success!(o_prot.write_field_begin(&field_ident_3));
1842 assert_success!(o_prot.write_field_end());
1843
1844 // contained struct
1845 // since the delta is > 0 and < 15 it gets a delta write
1846 let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
1847 assert_success!(o_prot.write_field_begin(&field_ident_4));
1848 assert_success!(o_prot.write_field_end());
1849
1850 // end contained struct
1851 assert_success!(o_prot.write_field_stop());
1852 assert_success!(o_prot.write_struct_end());
1853
1854 // end containing struct
1855 assert_success!(o_prot.write_field_stop());
1856 assert_success!(o_prot.write_struct_end());
1857
Allen George0e22c362017-01-30 07:15:00 -05001858 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001859
1860 // read containing struct back
1861 assert_success!(i_prot.read_struct_begin());
1862
1863 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001864 assert_eq!(
1865 read_ident_1,
1866 TFieldIdentifier {
1867 name: None,
1868 ..field_ident_1
1869 }
1870 );
Allen George8b96bfb2016-11-02 08:01:08 -04001871 assert_success!(i_prot.read_field_end());
1872
1873 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001874 assert_eq!(
1875 read_ident_2,
1876 TFieldIdentifier {
1877 name: None,
1878 ..field_ident_2
1879 }
1880 );
Allen George8b96bfb2016-11-02 08:01:08 -04001881 assert_success!(i_prot.read_field_end());
1882
1883 // read contained struct back
1884 assert_success!(i_prot.read_struct_begin());
1885
1886 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001887 assert_eq!(
1888 read_ident_3,
1889 TFieldIdentifier {
1890 name: None,
1891 ..field_ident_3
1892 }
1893 );
Allen George8b96bfb2016-11-02 08:01:08 -04001894 assert_success!(i_prot.read_field_end());
1895
1896 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001897 assert_eq!(
1898 read_ident_4,
1899 TFieldIdentifier {
1900 name: None,
1901 ..field_ident_4
1902 }
1903 );
Allen George8b96bfb2016-11-02 08:01:08 -04001904 assert_success!(i_prot.read_field_end());
1905
1906 // end contained struct
1907 let read_ident_6 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001908 assert_eq!(
1909 read_ident_6,
1910 TFieldIdentifier {
1911 name: None,
1912 field_type: TType::Stop,
1913 id: None,
1914 }
1915 );
Allen George8b96bfb2016-11-02 08:01:08 -04001916 assert_success!(i_prot.read_struct_end());
1917
1918 // end containing struct
1919 let read_ident_7 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05001920 assert_eq!(
1921 read_ident_7,
1922 TFieldIdentifier {
1923 name: None,
1924 field_type: TType::Stop,
1925 id: None,
1926 }
1927 );
Allen George8b96bfb2016-11-02 08:01:08 -04001928 assert_success!(i_prot.read_struct_end());
1929 }
1930
1931 #[test]
1932 fn must_write_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05001933 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001934
1935 // no bytes should be written however
1936 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1937
1938 // write three fields with field ids that cannot be encoded as deltas
1939
1940 // since the delta is > 0 and < 16 it gets a delta write
1941 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
1942 assert_success!(o_prot.write_bool(true));
1943 assert_success!(o_prot.write_field_end());
1944
1945 // since this delta > 0 and < 15 it gets a delta write
1946 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
1947 assert_success!(o_prot.write_bool(false));
1948 assert_success!(o_prot.write_field_end());
1949
1950 // since this delta > 15 it gets a full write
1951 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
1952 assert_success!(o_prot.write_bool(true));
1953 assert_success!(o_prot.write_field_end());
1954
1955 // since this delta > 15 it gets a full write
1956 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
1957 assert_success!(o_prot.write_bool(false));
1958 assert_success!(o_prot.write_field_end());
1959
1960 // now, finish the struct off
1961 assert_success!(o_prot.write_field_stop());
1962 assert_success!(o_prot.write_struct_end());
1963
Allen Georgeef7a1892018-12-16 18:01:37 -05001964 #[cfg_attr(rustfmt, rustfmt::skip)]
Allen George0e22c362017-01-30 07:15:00 -05001965 let expected: [u8; 7] = [
1966 0x11, /* field delta (1) | true */
1967 0x82, /* field delta (8) | false */
1968 0x01, /* true */
1969 0x34, /* field id */
1970 0x02, /* false */
1971 0x5A, /* field id */
1972 0x00 /* stop field */,
1973 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001974
Allen George0e22c362017-01-30 07:15:00 -05001975 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04001976 }
1977
1978 #[test]
1979 fn must_round_trip_bool_field() {
Allen George0e22c362017-01-30 07:15:00 -05001980 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04001981
1982 // no bytes should be written however
1983 let struct_ident = TStructIdentifier::new("foo");
1984 assert_success!(o_prot.write_struct_begin(&struct_ident));
1985
1986 // write two fields
1987
1988 // since the delta is > 0 and < 16 it gets a delta write
1989 let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
1990 assert_success!(o_prot.write_field_begin(&field_ident_1));
1991 assert_success!(o_prot.write_bool(true));
1992 assert_success!(o_prot.write_field_end());
1993
1994 // since this delta > 0 and < 15 it gets a delta write
1995 let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
1996 assert_success!(o_prot.write_field_begin(&field_ident_2));
1997 assert_success!(o_prot.write_bool(false));
1998 assert_success!(o_prot.write_field_end());
1999
2000 // since this delta > 15 it gets a full write
2001 let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
2002 assert_success!(o_prot.write_field_begin(&field_ident_3));
2003 assert_success!(o_prot.write_bool(true));
2004 assert_success!(o_prot.write_field_end());
2005
2006 // since this delta > 15 it gets a full write
2007 let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
2008 assert_success!(o_prot.write_field_begin(&field_ident_4));
2009 assert_success!(o_prot.write_bool(false));
2010 assert_success!(o_prot.write_field_end());
2011
2012 // now, finish the struct off
2013 assert_success!(o_prot.write_field_stop());
2014 assert_success!(o_prot.write_struct_end());
2015
Allen George0e22c362017-01-30 07:15:00 -05002016 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002017
2018 // read the struct back
2019 assert_success!(i_prot.read_struct_begin());
2020
2021 let read_ident_1 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002022 assert_eq!(
2023 read_ident_1,
2024 TFieldIdentifier {
2025 name: None,
2026 ..field_ident_1
2027 }
2028 );
Allen George8b96bfb2016-11-02 08:01:08 -04002029 let read_value_1 = assert_success!(i_prot.read_bool());
2030 assert_eq!(read_value_1, true);
2031 assert_success!(i_prot.read_field_end());
2032
2033 let read_ident_2 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002034 assert_eq!(
2035 read_ident_2,
2036 TFieldIdentifier {
2037 name: None,
2038 ..field_ident_2
2039 }
2040 );
Allen George8b96bfb2016-11-02 08:01:08 -04002041 let read_value_2 = assert_success!(i_prot.read_bool());
2042 assert_eq!(read_value_2, false);
2043 assert_success!(i_prot.read_field_end());
2044
2045 let read_ident_3 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002046 assert_eq!(
2047 read_ident_3,
2048 TFieldIdentifier {
2049 name: None,
2050 ..field_ident_3
2051 }
2052 );
Allen George8b96bfb2016-11-02 08:01:08 -04002053 let read_value_3 = assert_success!(i_prot.read_bool());
2054 assert_eq!(read_value_3, true);
2055 assert_success!(i_prot.read_field_end());
2056
2057 let read_ident_4 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002058 assert_eq!(
2059 read_ident_4,
2060 TFieldIdentifier {
2061 name: None,
2062 ..field_ident_4
2063 }
2064 );
Allen George8b96bfb2016-11-02 08:01:08 -04002065 let read_value_4 = assert_success!(i_prot.read_bool());
2066 assert_eq!(read_value_4, false);
2067 assert_success!(i_prot.read_field_end());
2068
2069 let read_ident_5 = assert_success!(i_prot.read_field_begin());
Allen George0e22c362017-01-30 07:15:00 -05002070 assert_eq!(
2071 read_ident_5,
2072 TFieldIdentifier {
2073 name: None,
2074 field_type: TType::Stop,
2075 id: None,
2076 }
2077 );
Allen George8b96bfb2016-11-02 08:01:08 -04002078
2079 assert_success!(i_prot.read_struct_end());
2080 }
2081
2082 #[test]
2083 #[should_panic]
2084 fn must_fail_if_write_field_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002085 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002086 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2087 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2088 o_prot.write_field_end().unwrap();
2089 }
2090
2091 #[test]
2092 #[should_panic]
2093 fn must_fail_if_write_stop_field_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002094 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002095 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2096 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2097 o_prot.write_field_stop().unwrap();
2098 }
2099
2100 #[test]
2101 #[should_panic]
2102 fn must_fail_if_write_struct_end_without_writing_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002103 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002104 assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2105 assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2106 o_prot.write_struct_end().unwrap();
2107 }
2108
2109 #[test]
2110 #[should_panic]
2111 fn must_fail_if_write_struct_end_without_any_fields() {
Allen George0e22c362017-01-30 07:15:00 -05002112 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002113 o_prot.write_struct_end().unwrap();
2114 }
2115
2116 #[test]
2117 fn must_write_field_end() {
2118 assert_no_write(|o| o.write_field_end());
2119 }
2120
2121 #[test]
2122 fn must_write_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002123 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002124
2125 assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
2126
2127 let expected: [u8; 1] = [0x46 /* size | elem_type */];
2128
Allen George0e22c362017-01-30 07:15:00 -05002129 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002130 }
2131
2132 #[test]
2133 fn must_round_trip_small_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002134 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002135
2136 let ident = TListIdentifier::new(TType::I08, 10);
2137
2138 assert_success!(o_prot.write_list_begin(&ident));
2139
Allen George0e22c362017-01-30 07:15:00 -05002140 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002141
2142 let res = assert_success!(i_prot.read_list_begin());
2143 assert_eq!(&res, &ident);
2144 }
2145
2146 #[test]
2147 fn must_write_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002148 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002149
2150 let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
2151 assert!(res.is_ok());
2152
Allen George0e22c362017-01-30 07:15:00 -05002153 let expected: [u8; 3] = [
2154 0xF9, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002155 0x8F, 0x4E, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002156 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002157
Allen George0e22c362017-01-30 07:15:00 -05002158 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002159 }
2160
2161 #[test]
2162 fn must_round_trip_large_sized_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002163 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002164
2165 let ident = TListIdentifier::new(TType::Set, 47381);
2166
2167 assert_success!(o_prot.write_list_begin(&ident));
2168
Allen George0e22c362017-01-30 07:15:00 -05002169 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002170
2171 let res = assert_success!(i_prot.read_list_begin());
2172 assert_eq!(&res, &ident);
2173 }
2174
2175 #[test]
2176 fn must_write_list_end() {
2177 assert_no_write(|o| o.write_list_end());
2178 }
2179
2180 #[test]
2181 fn must_write_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002182 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002183
2184 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
2185
2186 let expected: [u8; 1] = [0x2C /* size | elem_type */];
2187
Allen George0e22c362017-01-30 07:15:00 -05002188 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002189 }
2190
2191 #[test]
2192 fn must_round_trip_small_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002193 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002194
2195 let ident = TSetIdentifier::new(TType::I16, 7);
2196
2197 assert_success!(o_prot.write_set_begin(&ident));
2198
Allen George0e22c362017-01-30 07:15:00 -05002199 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002200
2201 let res = assert_success!(i_prot.read_set_begin());
2202 assert_eq!(&res, &ident);
2203 }
2204
2205 #[test]
2206 fn must_write_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002207 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002208
2209 assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
2210
Allen George0e22c362017-01-30 07:15:00 -05002211 let expected: [u8; 4] = [
2212 0xF7, /* 0xF0 | elem_type */
Allen Georgeef7a1892018-12-16 18:01:37 -05002213 0xD3, 0xBA, 0x01, /* size as varint */
Allen George0e22c362017-01-30 07:15:00 -05002214 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002215
Allen George0e22c362017-01-30 07:15:00 -05002216 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002217 }
2218
2219 #[test]
2220 fn must_round_trip_large_sized_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002221 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002222
2223 let ident = TSetIdentifier::new(TType::Map, 3928429);
2224
2225 assert_success!(o_prot.write_set_begin(&ident));
2226
Allen George0e22c362017-01-30 07:15:00 -05002227 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002228
2229 let res = assert_success!(i_prot.read_set_begin());
2230 assert_eq!(&res, &ident);
2231 }
2232
2233 #[test]
2234 fn must_write_set_end() {
2235 assert_no_write(|o| o.write_set_end());
2236 }
2237
2238 #[test]
2239 fn must_write_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002240 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002241
2242 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
2243
2244 let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything
2245
Allen George0e22c362017-01-30 07:15:00 -05002246 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002247 }
2248
2249 #[test]
2250 fn must_read_zero_sized_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002251 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002252
2253 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
2254
Allen George0e22c362017-01-30 07:15:00 -05002255 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002256
2257 let res = assert_success!(i_prot.read_map_begin());
Allen George0e22c362017-01-30 07:15:00 -05002258 assert_eq!(
2259 &res,
2260 &TMapIdentifier {
Allen Georgeef7a1892018-12-16 18:01:37 -05002261 key_type: None,
2262 value_type: None,
2263 size: 0,
2264 }
Allen George0e22c362017-01-30 07:15:00 -05002265 );
Allen George8b96bfb2016-11-02 08:01:08 -04002266 }
2267
2268 #[test]
2269 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002270 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002271
Allen Georgeef7a1892018-12-16 18:01:37 -05002272 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
2273 TType::Double,
2274 TType::String,
2275 238
2276 )));
Allen George8b96bfb2016-11-02 08:01:08 -04002277
Allen George0e22c362017-01-30 07:15:00 -05002278 let expected: [u8; 3] = [
Allen Georgeef7a1892018-12-16 18:01:37 -05002279 0xEE, 0x01, /* size as varint */
2280 0x78, /* key type | val type */
Allen George0e22c362017-01-30 07:15:00 -05002281 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002282
Allen George0e22c362017-01-30 07:15:00 -05002283 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002284 }
2285
2286 #[test]
2287 fn must_round_trip_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -05002288 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002289
2290 let ident = TMapIdentifier::new(TType::Map, TType::List, 1928349);
2291
2292 assert_success!(o_prot.write_map_begin(&ident));
2293
Allen George0e22c362017-01-30 07:15:00 -05002294 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002295
2296 let res = assert_success!(i_prot.read_map_begin());
2297 assert_eq!(&res, &ident);
2298 }
2299
2300 #[test]
2301 fn must_write_map_end() {
2302 assert_no_write(|o| o.write_map_end());
2303 }
2304
2305 #[test]
2306 fn must_write_map_with_bool_key_and_value() {
Allen George0e22c362017-01-30 07:15:00 -05002307 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002308
2309 assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
2310 assert_success!(o_prot.write_bool(true));
2311 assert_success!(o_prot.write_bool(false));
2312 assert_success!(o_prot.write_map_end());
2313
Allen George0e22c362017-01-30 07:15:00 -05002314 let expected: [u8; 4] = [
2315 0x01, /* size as varint */
2316 0x11, /* key type | val type */
2317 0x01, /* key: true */
Allen Georgeef7a1892018-12-16 18:01:37 -05002318 0x02, /* val: false */
Allen George0e22c362017-01-30 07:15:00 -05002319 ];
Allen George8b96bfb2016-11-02 08:01:08 -04002320
Allen George0e22c362017-01-30 07:15:00 -05002321 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -04002322 }
2323
2324 #[test]
2325 fn must_round_trip_map_with_bool_value() {
Allen George0e22c362017-01-30 07:15:00 -05002326 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002327
2328 let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
2329 assert_success!(o_prot.write_map_begin(&map_ident));
2330 assert_success!(o_prot.write_bool(true));
2331 assert_success!(o_prot.write_bool(false));
2332 assert_success!(o_prot.write_bool(false));
2333 assert_success!(o_prot.write_bool(true));
2334 assert_success!(o_prot.write_map_end());
2335
Allen George0e22c362017-01-30 07:15:00 -05002336 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04002337
2338 // map header
2339 let rcvd_ident = assert_success!(i_prot.read_map_begin());
2340 assert_eq!(&rcvd_ident, &map_ident);
2341 // key 1
2342 let b = assert_success!(i_prot.read_bool());
2343 assert_eq!(b, true);
2344 // val 1
2345 let b = assert_success!(i_prot.read_bool());
2346 assert_eq!(b, false);
2347 // key 2
2348 let b = assert_success!(i_prot.read_bool());
2349 assert_eq!(b, false);
2350 // val 2
2351 let b = assert_success!(i_prot.read_bool());
2352 assert_eq!(b, true);
2353 // map end
2354 assert_success!(i_prot.read_map_end());
2355 }
2356
2357 #[test]
2358 fn must_read_map_end() {
Allen George0e22c362017-01-30 07:15:00 -05002359 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002360 assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
2361 }
2362
Allen Georgeef7a1892018-12-16 18:01:37 -05002363 fn test_objects() -> (
2364 TCompactInputProtocol<ReadHalf<TBufferChannel>>,
2365 TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
2366 ) {
Allen George0e22c362017-01-30 07:15:00 -05002367 let mem = TBufferChannel::with_capacity(80, 80);
Allen George8b96bfb2016-11-02 08:01:08 -04002368
Allen George0e22c362017-01-30 07:15:00 -05002369 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -04002370
Allen George0e22c362017-01-30 07:15:00 -05002371 let i_prot = TCompactInputProtocol::new(r_mem);
2372 let o_prot = TCompactOutputProtocol::new(w_mem);
Allen George8b96bfb2016-11-02 08:01:08 -04002373
Allen George0e22c362017-01-30 07:15:00 -05002374 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -04002375 }
2376
Allen George0e22c362017-01-30 07:15:00 -05002377 fn assert_no_write<F>(mut write_fn: F)
2378 where
2379 F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> ::Result<()>,
2380 {
2381 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -04002382 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -05002383 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -04002384 }
2385}