blob: 54613a532115220409f70fcbc7159f726d50d649 [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, ByteOrder, ReadBytesExt, WriteBytesExt};
19use std::cell::RefCell;
20use std::convert::From;
21use std::io::{Read, Write};
22use std::rc::Rc;
23use try_from::TryFrom;
24
25use ::{ProtocolError, ProtocolErrorKind};
26use ::transport::TTransport;
27use super::{TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier,
28 TMapIdentifier, TMessageIdentifier, TMessageType};
29use super::{TOutputProtocol, TOutputProtocolFactory, TSetIdentifier, TStructIdentifier, TType};
30
31const BINARY_PROTOCOL_VERSION_1: u32 = 0x80010000;
32
33/// Read messages encoded in the Thrift simple binary encoding.
34///
35/// There are two available modes: `strict` and `non-strict`, where the
36/// `non-strict` version does not check for the protocol version in the
37/// received message header.
38///
39/// # Examples
40///
41/// Create and use a `TBinaryInputProtocol`.
42///
43/// ```no_run
44/// use std::cell::RefCell;
45/// use std::rc::Rc;
46/// use thrift::protocol::{TBinaryInputProtocol, TInputProtocol};
47/// use thrift::transport::{TTcpTransport, TTransport};
48///
49/// let mut transport = TTcpTransport::new();
50/// transport.open("localhost:9090").unwrap();
51/// let transport = Rc::new(RefCell::new(Box::new(transport) as Box<TTransport>));
52///
53/// let mut i_prot = TBinaryInputProtocol::new(transport, true);
54///
55/// let recvd_bool = i_prot.read_bool().unwrap();
56/// let recvd_string = i_prot.read_string().unwrap();
57/// ```
Chao Sunc063b302017-03-12 12:21:05 -070058pub struct TBinaryInputProtocol<'a> {
Allen George8b96bfb2016-11-02 08:01:08 -040059 strict: bool,
Chao Sunc063b302017-03-12 12:21:05 -070060 transport: Rc<RefCell<Box<TTransport + 'a>>>,
Allen George8b96bfb2016-11-02 08:01:08 -040061}
62
Chao Sunc063b302017-03-12 12:21:05 -070063impl<'a> TBinaryInputProtocol<'a> {
Allen George8b96bfb2016-11-02 08:01:08 -040064 /// Create a `TBinaryInputProtocol` that reads bytes from `transport`.
65 ///
66 /// Set `strict` to `true` if all incoming messages contain the protocol
67 /// version number in the protocol header.
Chao Sunc063b302017-03-12 12:21:05 -070068 pub fn new(transport: Rc<RefCell<Box<TTransport + 'a>>>,
69 strict: bool) -> TBinaryInputProtocol<'a> {
Allen George8b96bfb2016-11-02 08:01:08 -040070 TBinaryInputProtocol {
71 strict: strict,
72 transport: transport,
73 }
74 }
75}
76
Chao Sunc063b302017-03-12 12:21:05 -070077impl<'a> TInputProtocol for TBinaryInputProtocol<'a> {
Allen George8b96bfb2016-11-02 08:01:08 -040078 #[cfg_attr(feature = "cargo-clippy", allow(collapsible_if))]
79 fn read_message_begin(&mut self) -> ::Result<TMessageIdentifier> {
80 let mut first_bytes = vec![0; 4];
81 self.transport.borrow_mut().read_exact(&mut first_bytes[..])?;
82
83 // the thrift version header is intentionally negative
84 // so the first check we'll do is see if the sign bit is set
85 // and if so - assume it's the protocol-version header
86 if first_bytes[0] >= 8 {
87 // apparently we got a protocol-version header - check
88 // it, and if it matches, read the rest of the fields
89 if first_bytes[0..2] != [0x80, 0x01] {
90 Err(::Error::Protocol(ProtocolError {
91 kind: ProtocolErrorKind::BadVersion,
92 message: format!("received bad version: {:?}", &first_bytes[0..2]),
93 }))
94 } else {
95 let message_type: TMessageType = TryFrom::try_from(first_bytes[3])?;
96 let name = self.read_string()?;
97 let sequence_number = self.read_i32()?;
98 Ok(TMessageIdentifier::new(name, message_type, sequence_number))
99 }
100 } else {
101 // apparently we didn't get a protocol-version header,
102 // which happens if the sender is not using the strict protocol
103 if self.strict {
104 // we're in strict mode however, and that always
105 // requires the protocol-version header to be written first
106 Err(::Error::Protocol(ProtocolError {
107 kind: ProtocolErrorKind::BadVersion,
108 message: format!("received bad version: {:?}", &first_bytes[0..2]),
109 }))
110 } else {
111 // in the non-strict version the first message field
112 // is the message name. strings (byte arrays) are length-prefixed,
113 // so we've just read the length in the first 4 bytes
114 let name_size = BigEndian::read_i32(&first_bytes) as usize;
115 let mut name_buf: Vec<u8> = Vec::with_capacity(name_size);
116 self.transport.borrow_mut().read_exact(&mut name_buf)?;
117 let name = String::from_utf8(name_buf)?;
118
119 // read the rest of the fields
120 let message_type: TMessageType = self.read_byte().and_then(TryFrom::try_from)?;
121 let sequence_number = self.read_i32()?;
122 Ok(TMessageIdentifier::new(name, message_type, sequence_number))
123 }
124 }
125 }
126
127 fn read_message_end(&mut self) -> ::Result<()> {
128 Ok(())
129 }
130
131 fn read_struct_begin(&mut self) -> ::Result<Option<TStructIdentifier>> {
132 Ok(None)
133 }
134
135 fn read_struct_end(&mut self) -> ::Result<()> {
136 Ok(())
137 }
138
139 fn read_field_begin(&mut self) -> ::Result<TFieldIdentifier> {
140 let field_type_byte = self.read_byte()?;
141 let field_type = field_type_from_u8(field_type_byte)?;
142 let id = match field_type {
143 TType::Stop => Ok(0),
144 _ => self.read_i16(),
145 }?;
146 Ok(TFieldIdentifier::new::<Option<String>, String, i16>(None, field_type, id))
147 }
148
149 fn read_field_end(&mut self) -> ::Result<()> {
150 Ok(())
151 }
152
153 fn read_bytes(&mut self) -> ::Result<Vec<u8>> {
154 let num_bytes = self.transport.borrow_mut().read_i32::<BigEndian>()? as usize;
155 let mut buf = vec![0u8; num_bytes];
156 self.transport.borrow_mut().read_exact(&mut buf).map(|_| buf).map_err(From::from)
157 }
158
159 fn read_bool(&mut self) -> ::Result<bool> {
160 let b = self.read_i8()?;
161 match b {
162 0 => Ok(false),
163 _ => Ok(true),
164 }
165 }
166
167 fn read_i8(&mut self) -> ::Result<i8> {
168 self.transport.borrow_mut().read_i8().map_err(From::from)
169 }
170
171 fn read_i16(&mut self) -> ::Result<i16> {
172 self.transport.borrow_mut().read_i16::<BigEndian>().map_err(From::from)
173 }
174
175 fn read_i32(&mut self) -> ::Result<i32> {
176 self.transport.borrow_mut().read_i32::<BigEndian>().map_err(From::from)
177 }
178
179 fn read_i64(&mut self) -> ::Result<i64> {
180 self.transport.borrow_mut().read_i64::<BigEndian>().map_err(From::from)
181 }
182
183 fn read_double(&mut self) -> ::Result<f64> {
184 self.transport.borrow_mut().read_f64::<BigEndian>().map_err(From::from)
185 }
186
187 fn read_string(&mut self) -> ::Result<String> {
188 let bytes = self.read_bytes()?;
189 String::from_utf8(bytes).map_err(From::from)
190 }
191
192 fn read_list_begin(&mut self) -> ::Result<TListIdentifier> {
193 let element_type: TType = self.read_byte().and_then(field_type_from_u8)?;
194 let size = self.read_i32()?;
195 Ok(TListIdentifier::new(element_type, size))
196 }
197
198 fn read_list_end(&mut self) -> ::Result<()> {
199 Ok(())
200 }
201
202 fn read_set_begin(&mut self) -> ::Result<TSetIdentifier> {
203 let element_type: TType = self.read_byte().and_then(field_type_from_u8)?;
204 let size = self.read_i32()?;
205 Ok(TSetIdentifier::new(element_type, size))
206 }
207
208 fn read_set_end(&mut self) -> ::Result<()> {
209 Ok(())
210 }
211
212 fn read_map_begin(&mut self) -> ::Result<TMapIdentifier> {
213 let key_type: TType = self.read_byte().and_then(field_type_from_u8)?;
214 let value_type: TType = self.read_byte().and_then(field_type_from_u8)?;
215 let size = self.read_i32()?;
216 Ok(TMapIdentifier::new(key_type, value_type, size))
217 }
218
219 fn read_map_end(&mut self) -> ::Result<()> {
220 Ok(())
221 }
222
223 // utility
224 //
225
226 fn read_byte(&mut self) -> ::Result<u8> {
227 self.transport.borrow_mut().read_u8().map_err(From::from)
228 }
229}
230
231/// Factory for creating instances of `TBinaryInputProtocol`.
232#[derive(Default)]
233pub struct TBinaryInputProtocolFactory;
234
235impl TBinaryInputProtocolFactory {
236 /// Create a `TBinaryInputProtocolFactory`.
237 pub fn new() -> TBinaryInputProtocolFactory {
238 TBinaryInputProtocolFactory {}
239 }
240}
241
242impl TInputProtocolFactory for TBinaryInputProtocolFactory {
Chao Sunc063b302017-03-12 12:21:05 -0700243 fn create<'a>(&mut self, transport: Rc<RefCell<Box<TTransport + 'a>>>) -> Box<TInputProtocol + 'a> {
244 Box::new(TBinaryInputProtocol::new(transport, true)) as Box<TInputProtocol + 'a>
Allen George8b96bfb2016-11-02 08:01:08 -0400245 }
246}
247
248/// Write messages using the Thrift simple binary encoding.
249///
250/// There are two available modes: `strict` and `non-strict`, where the
251/// `strict` version writes the protocol version number in the outgoing message
252/// header and the `non-strict` version does not.
253///
254/// # Examples
255///
256/// Create and use a `TBinaryOutputProtocol`.
257///
258/// ```no_run
259/// use std::cell::RefCell;
260/// use std::rc::Rc;
261/// use thrift::protocol::{TBinaryOutputProtocol, TOutputProtocol};
262/// use thrift::transport::{TTcpTransport, TTransport};
263///
264/// let mut transport = TTcpTransport::new();
265/// transport.open("localhost:9090").unwrap();
266/// let transport = Rc::new(RefCell::new(Box::new(transport) as Box<TTransport>));
267///
268/// let mut o_prot = TBinaryOutputProtocol::new(transport, true);
269///
270/// o_prot.write_bool(true).unwrap();
271/// o_prot.write_string("test_string").unwrap();
272/// ```
Chao Sunc063b302017-03-12 12:21:05 -0700273pub struct TBinaryOutputProtocol<'a> {
Allen George8b96bfb2016-11-02 08:01:08 -0400274 strict: bool,
Chao Sunc063b302017-03-12 12:21:05 -0700275 transport: Rc<RefCell<Box<TTransport + 'a>>>,
Allen George8b96bfb2016-11-02 08:01:08 -0400276}
277
Chao Sunc063b302017-03-12 12:21:05 -0700278impl<'a> TBinaryOutputProtocol<'a> {
Allen George8b96bfb2016-11-02 08:01:08 -0400279 /// Create a `TBinaryOutputProtocol` that writes bytes to `transport`.
280 ///
281 /// Set `strict` to `true` if all outgoing messages should contain the
282 /// protocol version number in the protocol header.
Chao Sunc063b302017-03-12 12:21:05 -0700283 pub fn new(transport: Rc<RefCell<Box<TTransport + 'a>>>,
284 strict: bool) -> TBinaryOutputProtocol<'a> {
Allen George8b96bfb2016-11-02 08:01:08 -0400285 TBinaryOutputProtocol {
286 strict: strict,
287 transport: transport,
288 }
289 }
290
291 fn write_transport(&mut self, buf: &[u8]) -> ::Result<()> {
292 self.transport.borrow_mut().write(buf).map(|_| ()).map_err(From::from)
293 }
294}
295
Chao Sunc063b302017-03-12 12:21:05 -0700296impl<'a> TOutputProtocol for TBinaryOutputProtocol<'a> {
Allen George8b96bfb2016-11-02 08:01:08 -0400297 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> ::Result<()> {
298 if self.strict {
299 let message_type: u8 = identifier.message_type.into();
300 let header = BINARY_PROTOCOL_VERSION_1 | (message_type as u32);
301 self.transport.borrow_mut().write_u32::<BigEndian>(header)?;
302 self.write_string(&identifier.name)?;
303 self.write_i32(identifier.sequence_number)
304 } else {
305 self.write_string(&identifier.name)?;
306 self.write_byte(identifier.message_type.into())?;
307 self.write_i32(identifier.sequence_number)
308 }
309 }
310
311 fn write_message_end(&mut self) -> ::Result<()> {
312 Ok(())
313 }
314
315 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> ::Result<()> {
316 Ok(())
317 }
318
319 fn write_struct_end(&mut self) -> ::Result<()> {
320 Ok(())
321 }
322
323 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> ::Result<()> {
324 if identifier.id.is_none() && identifier.field_type != TType::Stop {
325 return Err(::Error::Protocol(ProtocolError {
326 kind: ProtocolErrorKind::Unknown,
327 message: format!("cannot write identifier {:?} without sequence number",
328 &identifier),
329 }));
330 }
331
332 self.write_byte(field_type_to_u8(identifier.field_type))?;
333 if let Some(id) = identifier.id {
334 self.write_i16(id)
335 } else {
336 Ok(())
337 }
338 }
339
340 fn write_field_end(&mut self) -> ::Result<()> {
341 Ok(())
342 }
343
344 fn write_field_stop(&mut self) -> ::Result<()> {
345 self.write_byte(field_type_to_u8(TType::Stop))
346 }
347
348 fn write_bytes(&mut self, b: &[u8]) -> ::Result<()> {
349 self.write_i32(b.len() as i32)?;
350 self.write_transport(b)
351 }
352
353 fn write_bool(&mut self, b: bool) -> ::Result<()> {
354 if b {
355 self.write_i8(1)
356 } else {
357 self.write_i8(0)
358 }
359 }
360
361 fn write_i8(&mut self, i: i8) -> ::Result<()> {
362 self.transport.borrow_mut().write_i8(i).map_err(From::from)
363 }
364
365 fn write_i16(&mut self, i: i16) -> ::Result<()> {
366 self.transport.borrow_mut().write_i16::<BigEndian>(i).map_err(From::from)
367 }
368
369 fn write_i32(&mut self, i: i32) -> ::Result<()> {
370 self.transport.borrow_mut().write_i32::<BigEndian>(i).map_err(From::from)
371 }
372
373 fn write_i64(&mut self, i: i64) -> ::Result<()> {
374 self.transport.borrow_mut().write_i64::<BigEndian>(i).map_err(From::from)
375 }
376
377 fn write_double(&mut self, d: f64) -> ::Result<()> {
378 self.transport.borrow_mut().write_f64::<BigEndian>(d).map_err(From::from)
379 }
380
381 fn write_string(&mut self, s: &str) -> ::Result<()> {
382 self.write_bytes(s.as_bytes())
383 }
384
385 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> ::Result<()> {
386 self.write_byte(field_type_to_u8(identifier.element_type))?;
387 self.write_i32(identifier.size)
388 }
389
390 fn write_list_end(&mut self) -> ::Result<()> {
391 Ok(())
392 }
393
394 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> ::Result<()> {
395 self.write_byte(field_type_to_u8(identifier.element_type))?;
396 self.write_i32(identifier.size)
397 }
398
399 fn write_set_end(&mut self) -> ::Result<()> {
400 Ok(())
401 }
402
403 fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> ::Result<()> {
404 let key_type = identifier.key_type
405 .expect("map identifier to write should contain key type");
406 self.write_byte(field_type_to_u8(key_type))?;
407 let val_type = identifier.value_type
408 .expect("map identifier to write should contain value type");
409 self.write_byte(field_type_to_u8(val_type))?;
410 self.write_i32(identifier.size)
411 }
412
413 fn write_map_end(&mut self) -> ::Result<()> {
414 Ok(())
415 }
416
417 fn flush(&mut self) -> ::Result<()> {
418 self.transport.borrow_mut().flush().map_err(From::from)
419 }
420
421 // utility
422 //
423
424 fn write_byte(&mut self, b: u8) -> ::Result<()> {
425 self.transport.borrow_mut().write_u8(b).map_err(From::from)
426 }
427}
428
429/// Factory for creating instances of `TBinaryOutputProtocol`.
430#[derive(Default)]
431pub struct TBinaryOutputProtocolFactory;
432
433impl TBinaryOutputProtocolFactory {
434 /// Create a `TBinaryOutputProtocolFactory`.
435 pub fn new() -> TBinaryOutputProtocolFactory {
436 TBinaryOutputProtocolFactory {}
437 }
438}
439
440impl TOutputProtocolFactory for TBinaryOutputProtocolFactory {
441 fn create(&mut self, transport: Rc<RefCell<Box<TTransport>>>) -> Box<TOutputProtocol> {
442 Box::new(TBinaryOutputProtocol::new(transport, true)) as Box<TOutputProtocol>
443 }
444}
445
446fn field_type_to_u8(field_type: TType) -> u8 {
447 match field_type {
448 TType::Stop => 0x00,
449 TType::Void => 0x01,
450 TType::Bool => 0x02,
451 TType::I08 => 0x03, // equivalent to TType::Byte
452 TType::Double => 0x04,
453 TType::I16 => 0x06,
454 TType::I32 => 0x08,
455 TType::I64 => 0x0A,
456 TType::String | TType::Utf7 => 0x0B,
457 TType::Struct => 0x0C,
458 TType::Map => 0x0D,
459 TType::Set => 0x0E,
460 TType::List => 0x0F,
461 TType::Utf8 => 0x10,
462 TType::Utf16 => 0x11,
463 }
464}
465
466fn field_type_from_u8(b: u8) -> ::Result<TType> {
467 match b {
468 0x00 => Ok(TType::Stop),
469 0x01 => Ok(TType::Void),
470 0x02 => Ok(TType::Bool),
471 0x03 => Ok(TType::I08), // Equivalent to TType::Byte
472 0x04 => Ok(TType::Double),
473 0x06 => Ok(TType::I16),
474 0x08 => Ok(TType::I32),
475 0x0A => Ok(TType::I64),
476 0x0B => Ok(TType::String), // technically, also a UTF7, but we'll treat it as string
477 0x0C => Ok(TType::Struct),
478 0x0D => Ok(TType::Map),
479 0x0E => Ok(TType::Set),
480 0x0F => Ok(TType::List),
481 0x10 => Ok(TType::Utf8),
482 0x11 => Ok(TType::Utf16),
483 unkn => {
484 Err(::Error::Protocol(ProtocolError {
485 kind: ProtocolErrorKind::InvalidData,
486 message: format!("cannot convert {} to TType", unkn),
487 }))
488 }
489 }
490}
491
492#[cfg(test)]
493mod tests {
494
495 use std::rc::Rc;
496 use std::cell::RefCell;
497
498 use ::protocol::{TFieldIdentifier, TMessageIdentifier, TMessageType, TInputProtocol,
499 TListIdentifier, TMapIdentifier, TOutputProtocol, TSetIdentifier,
500 TStructIdentifier, TType};
501 use ::transport::{TPassThruTransport, TTransport};
502 use ::transport::mem::TBufferTransport;
503
504 use super::*;
505
506 #[test]
507 fn must_write_message_call_begin() {
508 let (trans, _, mut o_prot) = test_objects();
509
510 let ident = TMessageIdentifier::new("test", TMessageType::Call, 1);
511 assert!(o_prot.write_message_begin(&ident).is_ok());
512
513 let buf = trans.borrow().write_buffer_to_vec();
514
515 let expected: [u8; 16] = [0x80, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x74, 0x65,
516 0x73, 0x74, 0x00, 0x00, 0x00, 0x01];
517
518 assert_eq!(&expected, buf.as_slice());
519 }
520
521
522 #[test]
523 fn must_write_message_reply_begin() {
524 let (trans, _, mut o_prot) = test_objects();
525
526 let ident = TMessageIdentifier::new("test", TMessageType::Reply, 10);
527 assert!(o_prot.write_message_begin(&ident).is_ok());
528
529 let buf = trans.borrow().write_buffer_to_vec();
530
531 let expected: [u8; 16] = [0x80, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x74, 0x65,
532 0x73, 0x74, 0x00, 0x00, 0x00, 0x0A];
533
534 assert_eq!(&expected, buf.as_slice());
535 }
536
537 #[test]
538 fn must_round_trip_strict_message_begin() {
539 let (trans, mut i_prot, mut o_prot) = test_objects();
540
541 let sent_ident = TMessageIdentifier::new("test", TMessageType::Call, 1);
542 assert!(o_prot.write_message_begin(&sent_ident).is_ok());
543
544 trans.borrow_mut().copy_write_buffer_to_read_buffer();
545
546 let received_ident = assert_success!(i_prot.read_message_begin());
547 assert_eq!(&received_ident, &sent_ident);
548 }
549
550 #[test]
551 fn must_write_message_end() {
552 assert_no_write(|o| o.write_message_end());
553 }
554
555 #[test]
556 fn must_write_struct_begin() {
557 assert_no_write(|o| o.write_struct_begin(&TStructIdentifier::new("foo")));
558 }
559
560 #[test]
561 fn must_write_struct_end() {
562 assert_no_write(|o| o.write_struct_end());
563 }
564
565 #[test]
566 fn must_write_field_begin() {
567 let (trans, _, mut o_prot) = test_objects();
568
569 assert!(o_prot.write_field_begin(&TFieldIdentifier::new("some_field", TType::String, 22))
570 .is_ok());
571
572 let expected: [u8; 3] = [0x0B, 0x00, 0x16];
573 let buf = trans.borrow().write_buffer_to_vec();
574 assert_eq!(&expected, buf.as_slice());
575 }
576
577 #[test]
578 fn must_round_trip_field_begin() {
579 let (trans, mut i_prot, mut o_prot) = test_objects();
580
581 let sent_field_ident = TFieldIdentifier::new("foo", TType::I64, 20);
582 assert!(o_prot.write_field_begin(&sent_field_ident).is_ok());
583
584 trans.borrow_mut().copy_write_buffer_to_read_buffer();
585
586 let expected_ident = TFieldIdentifier {
587 name: None,
588 field_type: TType::I64,
589 id: Some(20),
590 }; // no name
591 let received_ident = assert_success!(i_prot.read_field_begin());
592 assert_eq!(&received_ident, &expected_ident);
593 }
594
595 #[test]
596 fn must_write_stop_field() {
597 let (trans, _, mut o_prot) = test_objects();
598
599 assert!(o_prot.write_field_stop().is_ok());
600
601 let expected: [u8; 1] = [0x00];
602 let buf = trans.borrow().write_buffer_to_vec();
603 assert_eq!(&expected, buf.as_slice());
604 }
605
606 #[test]
607 fn must_round_trip_field_stop() {
608 let (trans, mut i_prot, mut o_prot) = test_objects();
609
610 assert!(o_prot.write_field_stop().is_ok());
611
612 trans.borrow_mut().copy_write_buffer_to_read_buffer();
613
614 let expected_ident = TFieldIdentifier {
615 name: None,
616 field_type: TType::Stop,
617 id: Some(0),
618 }; // we get id 0
619
620 let received_ident = assert_success!(i_prot.read_field_begin());
621 assert_eq!(&received_ident, &expected_ident);
622 }
623
624 #[test]
625 fn must_write_field_end() {
626 assert_no_write(|o| o.write_field_end());
627 }
628
629 #[test]
630 fn must_write_list_begin() {
631 let (trans, _, mut o_prot) = test_objects();
632
633 assert!(o_prot.write_list_begin(&TListIdentifier::new(TType::Bool, 5)).is_ok());
634
635 let expected: [u8; 5] = [0x02, 0x00, 0x00, 0x00, 0x05];
636 let buf = trans.borrow().write_buffer_to_vec();
637 assert_eq!(&expected, buf.as_slice());
638 }
639
640 #[test]
641 fn must_round_trip_list_begin() {
642 let (trans, mut i_prot, mut o_prot) = test_objects();
643
644 let ident = TListIdentifier::new(TType::List, 900);
645 assert!(o_prot.write_list_begin(&ident).is_ok());
646
647 trans.borrow_mut().copy_write_buffer_to_read_buffer();
648
649 let received_ident = assert_success!(i_prot.read_list_begin());
650 assert_eq!(&received_ident, &ident);
651 }
652
653 #[test]
654 fn must_write_list_end() {
655 assert_no_write(|o| o.write_list_end());
656 }
657
658 #[test]
659 fn must_write_set_begin() {
660 let (trans, _, mut o_prot) = test_objects();
661
662 assert!(o_prot.write_set_begin(&TSetIdentifier::new(TType::I16, 7)).is_ok());
663
664 let expected: [u8; 5] = [0x06, 0x00, 0x00, 0x00, 0x07];
665 let buf = trans.borrow().write_buffer_to_vec();
666 assert_eq!(&expected, buf.as_slice());
667 }
668
669 #[test]
670 fn must_round_trip_set_begin() {
671 let (trans, mut i_prot, mut o_prot) = test_objects();
672
673 let ident = TSetIdentifier::new(TType::I64, 2000);
674 assert!(o_prot.write_set_begin(&ident).is_ok());
675
676 trans.borrow_mut().copy_write_buffer_to_read_buffer();
677
678 let received_ident_result = i_prot.read_set_begin();
679 assert!(received_ident_result.is_ok());
680 assert_eq!(&received_ident_result.unwrap(), &ident);
681 }
682
683 #[test]
684 fn must_write_set_end() {
685 assert_no_write(|o| o.write_set_end());
686 }
687
688 #[test]
689 fn must_write_map_begin() {
690 let (trans, _, mut o_prot) = test_objects();
691
692 assert!(o_prot.write_map_begin(&TMapIdentifier::new(TType::I64, TType::Struct, 32))
693 .is_ok());
694
695 let expected: [u8; 6] = [0x0A, 0x0C, 0x00, 0x00, 0x00, 0x20];
696 let buf = trans.borrow().write_buffer_to_vec();
697 assert_eq!(&expected, buf.as_slice());
698 }
699
700 #[test]
701 fn must_round_trip_map_begin() {
702 let (trans, mut i_prot, mut o_prot) = test_objects();
703
704 let ident = TMapIdentifier::new(TType::Map, TType::Set, 100);
705 assert!(o_prot.write_map_begin(&ident).is_ok());
706
707 trans.borrow_mut().copy_write_buffer_to_read_buffer();
708
709 let received_ident = assert_success!(i_prot.read_map_begin());
710 assert_eq!(&received_ident, &ident);
711 }
712
713 #[test]
714 fn must_write_map_end() {
715 assert_no_write(|o| o.write_map_end());
716 }
717
718 #[test]
719 fn must_write_bool_true() {
720 let (trans, _, mut o_prot) = test_objects();
721
722 assert!(o_prot.write_bool(true).is_ok());
723
724 let expected: [u8; 1] = [0x01];
725 let buf = trans.borrow().write_buffer_to_vec();
726 assert_eq!(&expected, buf.as_slice());
727 }
728
729 #[test]
730 fn must_write_bool_false() {
731 let (trans, _, mut o_prot) = test_objects();
732
733 assert!(o_prot.write_bool(false).is_ok());
734
735 let expected: [u8; 1] = [0x00];
736 let buf = trans.borrow().write_buffer_to_vec();
737 assert_eq!(&expected, buf.as_slice());
738 }
739
740 #[test]
741 fn must_read_bool_true() {
742 let (trans, mut i_prot, _) = test_objects();
743
744 trans.borrow_mut().set_readable_bytes(&[0x01]);
745
746 let read_bool = assert_success!(i_prot.read_bool());
747 assert_eq!(read_bool, true);
748 }
749
750 #[test]
751 fn must_read_bool_false() {
752 let (trans, mut i_prot, _) = test_objects();
753
754 trans.borrow_mut().set_readable_bytes(&[0x00]);
755
756 let read_bool = assert_success!(i_prot.read_bool());
757 assert_eq!(read_bool, false);
758 }
759
760 #[test]
761 fn must_allow_any_non_zero_value_to_be_interpreted_as_bool_true() {
762 let (trans, mut i_prot, _) = test_objects();
763
764 trans.borrow_mut().set_readable_bytes(&[0xAC]);
765
766 let read_bool = assert_success!(i_prot.read_bool());
767 assert_eq!(read_bool, true);
768 }
769
770 #[test]
771 fn must_write_bytes() {
772 let (trans, _, mut o_prot) = test_objects();
773
774 let bytes: [u8; 10] = [0x0A, 0xCC, 0xD1, 0x84, 0x99, 0x12, 0xAB, 0xBB, 0x45, 0xDF];
775
776 assert!(o_prot.write_bytes(&bytes).is_ok());
777
778 let buf = trans.borrow().write_buffer_to_vec();
779 assert_eq!(&buf[0..4], [0x00, 0x00, 0x00, 0x0A]); // length
780 assert_eq!(&buf[4..], bytes); // actual bytes
781 }
782
783 #[test]
784 fn must_round_trip_bytes() {
785 let (trans, mut i_prot, mut o_prot) = test_objects();
786
787 let bytes: [u8; 25] = [0x20, 0xFD, 0x18, 0x84, 0x99, 0x12, 0xAB, 0xBB, 0x45, 0xDF, 0x34,
788 0xDC, 0x98, 0xA4, 0x6D, 0xF3, 0x99, 0xB4, 0xB7, 0xD4, 0x9C, 0xA5,
789 0xB3, 0xC9, 0x88];
790
791 assert!(o_prot.write_bytes(&bytes).is_ok());
792
793 trans.borrow_mut().copy_write_buffer_to_read_buffer();
794
795 let received_bytes = assert_success!(i_prot.read_bytes());
796 assert_eq!(&received_bytes, &bytes);
797 }
798
Chao Sunc063b302017-03-12 12:21:05 -0700799 fn test_objects<'a>
Allen George8b96bfb2016-11-02 08:01:08 -0400800 ()
Chao Sunc063b302017-03-12 12:21:05 -0700801 -> (Rc<RefCell<Box<TBufferTransport>>>, TBinaryInputProtocol<'a>, TBinaryOutputProtocol<'a>)
Allen George8b96bfb2016-11-02 08:01:08 -0400802 {
Chao Sunc063b302017-03-12 12:21:05 -0700803
Allen George8b96bfb2016-11-02 08:01:08 -0400804 let mem = Rc::new(RefCell::new(Box::new(TBufferTransport::with_capacity(40, 40))));
805
806 let inner: Box<TTransport> = Box::new(TPassThruTransport { inner: mem.clone() });
807 let inner = Rc::new(RefCell::new(inner));
808
809 let i_prot = TBinaryInputProtocol::new(inner.clone(), true);
810 let o_prot = TBinaryOutputProtocol::new(inner.clone(), true);
811
812 (mem, i_prot, o_prot)
813 }
814
815 fn assert_no_write<F: FnMut(&mut TBinaryOutputProtocol) -> ::Result<()>>(mut write_fn: F) {
816 let (trans, _, mut o_prot) = test_objects();
817 assert!(write_fn(&mut o_prot).is_ok());
818 assert_eq!(trans.borrow().write_buffer_as_ref().len(), 0);
819 }
820}