blob: e03ec943788d523ee9c6f3dbc292f4e35a84af7a [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};
Allen George8b96bfb2016-11-02 08:01:08 -040019use std::convert::From;
Allen George8b96bfb2016-11-02 08:01:08 -040020use try_from::TryFrom;
21
Allen George0e22c362017-01-30 07:15:00 -050022use {ProtocolError, ProtocolErrorKind};
23use transport::{TReadTransport, TWriteTransport};
Allen George8b96bfb2016-11-02 08:01:08 -040024use super::{TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier,
25 TMapIdentifier, TMessageIdentifier, TMessageType};
26use super::{TOutputProtocol, TOutputProtocolFactory, TSetIdentifier, TStructIdentifier, TType};
27
28const BINARY_PROTOCOL_VERSION_1: u32 = 0x80010000;
29
30/// Read messages encoded in the Thrift simple binary encoding.
31///
32/// There are two available modes: `strict` and `non-strict`, where the
33/// `non-strict` version does not check for the protocol version in the
34/// received message header.
35///
36/// # Examples
37///
38/// Create and use a `TBinaryInputProtocol`.
39///
40/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -040041/// use thrift::protocol::{TBinaryInputProtocol, 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 = TBinaryInputProtocol::new(channel, true);
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 TBinaryInputProtocol<T>
54where
55 T: TReadTransport,
56{
Allen George8b96bfb2016-11-02 08:01:08 -040057 strict: bool,
Allen George0e22c362017-01-30 07:15:00 -050058 transport: T,
Allen George8b96bfb2016-11-02 08:01:08 -040059}
60
Allen George0e22c362017-01-30 07:15:00 -050061impl<'a, T> TBinaryInputProtocol<T>
62where
63 T: TReadTransport,
64{
Allen George8b96bfb2016-11-02 08:01:08 -040065 /// Create a `TBinaryInputProtocol` that reads bytes from `transport`.
66 ///
67 /// Set `strict` to `true` if all incoming messages contain the protocol
68 /// version number in the protocol header.
Allen George0e22c362017-01-30 07:15:00 -050069 pub fn new(transport: T, strict: bool) -> TBinaryInputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -040070 TBinaryInputProtocol {
71 strict: strict,
72 transport: transport,
73 }
74 }
75}
76
Allen George0e22c362017-01-30 07:15:00 -050077impl<T> TInputProtocol for TBinaryInputProtocol<T>
78where
79 T: TReadTransport,
80{
Allen George8b96bfb2016-11-02 08:01:08 -040081 #[cfg_attr(feature = "cargo-clippy", allow(collapsible_if))]
82 fn read_message_begin(&mut self) -> ::Result<TMessageIdentifier> {
83 let mut first_bytes = vec![0; 4];
Allen George0e22c362017-01-30 07:15:00 -050084 self.transport.read_exact(&mut first_bytes[..])?;
Allen George8b96bfb2016-11-02 08:01:08 -040085
86 // the thrift version header is intentionally negative
87 // so the first check we'll do is see if the sign bit is set
88 // and if so - assume it's the protocol-version header
89 if first_bytes[0] >= 8 {
90 // apparently we got a protocol-version header - check
91 // it, and if it matches, read the rest of the fields
92 if first_bytes[0..2] != [0x80, 0x01] {
Allen George0e22c362017-01-30 07:15:00 -050093 Err(
94 ::Error::Protocol(
95 ProtocolError {
96 kind: ProtocolErrorKind::BadVersion,
97 message: format!("received bad version: {:?}", &first_bytes[0..2]),
98 },
99 ),
100 )
Allen George8b96bfb2016-11-02 08:01:08 -0400101 } else {
102 let message_type: TMessageType = TryFrom::try_from(first_bytes[3])?;
103 let name = self.read_string()?;
104 let sequence_number = self.read_i32()?;
105 Ok(TMessageIdentifier::new(name, message_type, sequence_number))
106 }
107 } else {
108 // apparently we didn't get a protocol-version header,
109 // which happens if the sender is not using the strict protocol
110 if self.strict {
111 // we're in strict mode however, and that always
112 // requires the protocol-version header to be written first
Allen George0e22c362017-01-30 07:15:00 -0500113 Err(
114 ::Error::Protocol(
115 ProtocolError {
116 kind: ProtocolErrorKind::BadVersion,
117 message: format!("received bad version: {:?}", &first_bytes[0..2]),
118 },
119 ),
120 )
Allen George8b96bfb2016-11-02 08:01:08 -0400121 } else {
122 // in the non-strict version the first message field
123 // is the message name. strings (byte arrays) are length-prefixed,
124 // so we've just read the length in the first 4 bytes
125 let name_size = BigEndian::read_i32(&first_bytes) as usize;
126 let mut name_buf: Vec<u8> = Vec::with_capacity(name_size);
Allen George0e22c362017-01-30 07:15:00 -0500127 self.transport.read_exact(&mut name_buf)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400128 let name = String::from_utf8(name_buf)?;
129
130 // read the rest of the fields
131 let message_type: TMessageType = self.read_byte().and_then(TryFrom::try_from)?;
132 let sequence_number = self.read_i32()?;
133 Ok(TMessageIdentifier::new(name, message_type, sequence_number))
134 }
135 }
136 }
137
138 fn read_message_end(&mut self) -> ::Result<()> {
139 Ok(())
140 }
141
142 fn read_struct_begin(&mut self) -> ::Result<Option<TStructIdentifier>> {
143 Ok(None)
144 }
145
146 fn read_struct_end(&mut self) -> ::Result<()> {
147 Ok(())
148 }
149
150 fn read_field_begin(&mut self) -> ::Result<TFieldIdentifier> {
151 let field_type_byte = self.read_byte()?;
152 let field_type = field_type_from_u8(field_type_byte)?;
153 let id = match field_type {
154 TType::Stop => Ok(0),
155 _ => self.read_i16(),
156 }?;
Allen George0e22c362017-01-30 07:15:00 -0500157 Ok(TFieldIdentifier::new::<Option<String>, String, i16>(None, field_type, id),)
Allen George8b96bfb2016-11-02 08:01:08 -0400158 }
159
160 fn read_field_end(&mut self) -> ::Result<()> {
161 Ok(())
162 }
163
164 fn read_bytes(&mut self) -> ::Result<Vec<u8>> {
Allen George0e22c362017-01-30 07:15:00 -0500165 let num_bytes = self.transport.read_i32::<BigEndian>()? as usize;
Allen George8b96bfb2016-11-02 08:01:08 -0400166 let mut buf = vec![0u8; num_bytes];
Allen George0e22c362017-01-30 07:15:00 -0500167 self.transport
168 .read_exact(&mut buf)
169 .map(|_| buf)
170 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400171 }
172
173 fn read_bool(&mut self) -> ::Result<bool> {
174 let b = self.read_i8()?;
175 match b {
176 0 => Ok(false),
177 _ => Ok(true),
178 }
179 }
180
181 fn read_i8(&mut self) -> ::Result<i8> {
Allen George0e22c362017-01-30 07:15:00 -0500182 self.transport.read_i8().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400183 }
184
185 fn read_i16(&mut self) -> ::Result<i16> {
Allen George0e22c362017-01-30 07:15:00 -0500186 self.transport
187 .read_i16::<BigEndian>()
188 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400189 }
190
191 fn read_i32(&mut self) -> ::Result<i32> {
Allen George0e22c362017-01-30 07:15:00 -0500192 self.transport
193 .read_i32::<BigEndian>()
194 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400195 }
196
197 fn read_i64(&mut self) -> ::Result<i64> {
Allen George0e22c362017-01-30 07:15:00 -0500198 self.transport
199 .read_i64::<BigEndian>()
200 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400201 }
202
203 fn read_double(&mut self) -> ::Result<f64> {
Allen George0e22c362017-01-30 07:15:00 -0500204 self.transport
205 .read_f64::<BigEndian>()
206 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400207 }
208
209 fn read_string(&mut self) -> ::Result<String> {
210 let bytes = self.read_bytes()?;
211 String::from_utf8(bytes).map_err(From::from)
212 }
213
214 fn read_list_begin(&mut self) -> ::Result<TListIdentifier> {
215 let element_type: TType = self.read_byte().and_then(field_type_from_u8)?;
216 let size = self.read_i32()?;
217 Ok(TListIdentifier::new(element_type, size))
218 }
219
220 fn read_list_end(&mut self) -> ::Result<()> {
221 Ok(())
222 }
223
224 fn read_set_begin(&mut self) -> ::Result<TSetIdentifier> {
225 let element_type: TType = self.read_byte().and_then(field_type_from_u8)?;
226 let size = self.read_i32()?;
227 Ok(TSetIdentifier::new(element_type, size))
228 }
229
230 fn read_set_end(&mut self) -> ::Result<()> {
231 Ok(())
232 }
233
234 fn read_map_begin(&mut self) -> ::Result<TMapIdentifier> {
235 let key_type: TType = self.read_byte().and_then(field_type_from_u8)?;
236 let value_type: TType = self.read_byte().and_then(field_type_from_u8)?;
237 let size = self.read_i32()?;
238 Ok(TMapIdentifier::new(key_type, value_type, size))
239 }
240
241 fn read_map_end(&mut self) -> ::Result<()> {
242 Ok(())
243 }
244
245 // utility
246 //
247
248 fn read_byte(&mut self) -> ::Result<u8> {
Allen George0e22c362017-01-30 07:15:00 -0500249 self.transport.read_u8().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400250 }
251}
252
253/// Factory for creating instances of `TBinaryInputProtocol`.
254#[derive(Default)]
255pub struct TBinaryInputProtocolFactory;
256
257impl TBinaryInputProtocolFactory {
258 /// Create a `TBinaryInputProtocolFactory`.
259 pub fn new() -> TBinaryInputProtocolFactory {
260 TBinaryInputProtocolFactory {}
261 }
262}
263
264impl TInputProtocolFactory for TBinaryInputProtocolFactory {
Allen George0e22c362017-01-30 07:15:00 -0500265 fn create(&self, transport: Box<TReadTransport + Send>) -> Box<TInputProtocol + Send> {
266 Box::new(TBinaryInputProtocol::new(transport, true))
Allen George8b96bfb2016-11-02 08:01:08 -0400267 }
268}
269
270/// Write messages using the Thrift simple binary encoding.
271///
272/// There are two available modes: `strict` and `non-strict`, where the
273/// `strict` version writes the protocol version number in the outgoing message
274/// header and the `non-strict` version does not.
275///
276/// # Examples
277///
278/// Create and use a `TBinaryOutputProtocol`.
279///
280/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -0400281/// use thrift::protocol::{TBinaryOutputProtocol, TOutputProtocol};
Allen George0e22c362017-01-30 07:15:00 -0500282/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -0400283///
Allen George0e22c362017-01-30 07:15:00 -0500284/// let mut channel = TTcpChannel::new();
285/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400286///
Allen George0e22c362017-01-30 07:15:00 -0500287/// let mut protocol = TBinaryOutputProtocol::new(channel, true);
Allen George8b96bfb2016-11-02 08:01:08 -0400288///
Allen George0e22c362017-01-30 07:15:00 -0500289/// protocol.write_bool(true).unwrap();
290/// protocol.write_string("test_string").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400291/// ```
Allen George0e22c362017-01-30 07:15:00 -0500292#[derive(Debug)]
293pub struct TBinaryOutputProtocol<T>
294where
295 T: TWriteTransport,
296{
Allen George8b96bfb2016-11-02 08:01:08 -0400297 strict: bool,
Allen George0e22c362017-01-30 07:15:00 -0500298 pub transport: T, // FIXME: do not make public; only public for testing!
Allen George8b96bfb2016-11-02 08:01:08 -0400299}
300
Allen George0e22c362017-01-30 07:15:00 -0500301impl<T> TBinaryOutputProtocol<T>
302where
303 T: TWriteTransport,
304{
Allen George8b96bfb2016-11-02 08:01:08 -0400305 /// Create a `TBinaryOutputProtocol` that writes bytes to `transport`.
306 ///
307 /// Set `strict` to `true` if all outgoing messages should contain the
308 /// protocol version number in the protocol header.
Allen George0e22c362017-01-30 07:15:00 -0500309 pub fn new(transport: T, strict: bool) -> TBinaryOutputProtocol<T> {
Allen George8b96bfb2016-11-02 08:01:08 -0400310 TBinaryOutputProtocol {
311 strict: strict,
312 transport: transport,
313 }
314 }
315
316 fn write_transport(&mut self, buf: &[u8]) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500317 self.transport
318 .write(buf)
319 .map(|_| ())
320 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400321 }
322}
323
Allen George0e22c362017-01-30 07:15:00 -0500324impl<T> TOutputProtocol for TBinaryOutputProtocol<T>
325where
326 T: TWriteTransport,
327{
Allen George8b96bfb2016-11-02 08:01:08 -0400328 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> ::Result<()> {
329 if self.strict {
330 let message_type: u8 = identifier.message_type.into();
331 let header = BINARY_PROTOCOL_VERSION_1 | (message_type as u32);
Allen George0e22c362017-01-30 07:15:00 -0500332 self.transport.write_u32::<BigEndian>(header)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400333 self.write_string(&identifier.name)?;
334 self.write_i32(identifier.sequence_number)
335 } else {
336 self.write_string(&identifier.name)?;
337 self.write_byte(identifier.message_type.into())?;
338 self.write_i32(identifier.sequence_number)
339 }
340 }
341
342 fn write_message_end(&mut self) -> ::Result<()> {
343 Ok(())
344 }
345
346 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> ::Result<()> {
347 Ok(())
348 }
349
350 fn write_struct_end(&mut self) -> ::Result<()> {
351 Ok(())
352 }
353
354 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> ::Result<()> {
355 if identifier.id.is_none() && identifier.field_type != TType::Stop {
Allen George0e22c362017-01-30 07:15:00 -0500356 return Err(
357 ::Error::Protocol(
358 ProtocolError {
359 kind: ProtocolErrorKind::Unknown,
360 message: format!(
361 "cannot write identifier {:?} without sequence number",
362 &identifier
363 ),
364 },
365 ),
366 );
Allen George8b96bfb2016-11-02 08:01:08 -0400367 }
368
369 self.write_byte(field_type_to_u8(identifier.field_type))?;
370 if let Some(id) = identifier.id {
371 self.write_i16(id)
372 } else {
373 Ok(())
374 }
375 }
376
377 fn write_field_end(&mut self) -> ::Result<()> {
378 Ok(())
379 }
380
381 fn write_field_stop(&mut self) -> ::Result<()> {
382 self.write_byte(field_type_to_u8(TType::Stop))
383 }
384
385 fn write_bytes(&mut self, b: &[u8]) -> ::Result<()> {
386 self.write_i32(b.len() as i32)?;
387 self.write_transport(b)
388 }
389
390 fn write_bool(&mut self, b: bool) -> ::Result<()> {
391 if b {
392 self.write_i8(1)
393 } else {
394 self.write_i8(0)
395 }
396 }
397
398 fn write_i8(&mut self, i: i8) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500399 self.transport.write_i8(i).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400400 }
401
402 fn write_i16(&mut self, i: i16) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500403 self.transport
404 .write_i16::<BigEndian>(i)
405 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400406 }
407
408 fn write_i32(&mut self, i: i32) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500409 self.transport
410 .write_i32::<BigEndian>(i)
411 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400412 }
413
414 fn write_i64(&mut self, i: i64) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500415 self.transport
416 .write_i64::<BigEndian>(i)
417 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400418 }
419
420 fn write_double(&mut self, d: f64) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500421 self.transport
422 .write_f64::<BigEndian>(d)
423 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400424 }
425
426 fn write_string(&mut self, s: &str) -> ::Result<()> {
427 self.write_bytes(s.as_bytes())
428 }
429
430 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> ::Result<()> {
431 self.write_byte(field_type_to_u8(identifier.element_type))?;
432 self.write_i32(identifier.size)
433 }
434
435 fn write_list_end(&mut self) -> ::Result<()> {
436 Ok(())
437 }
438
439 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> ::Result<()> {
440 self.write_byte(field_type_to_u8(identifier.element_type))?;
441 self.write_i32(identifier.size)
442 }
443
444 fn write_set_end(&mut self) -> ::Result<()> {
445 Ok(())
446 }
447
448 fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500449 let key_type = identifier
450 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400451 .expect("map identifier to write should contain key type");
452 self.write_byte(field_type_to_u8(key_type))?;
Allen George0e22c362017-01-30 07:15:00 -0500453 let val_type = identifier
454 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400455 .expect("map identifier to write should contain value type");
456 self.write_byte(field_type_to_u8(val_type))?;
457 self.write_i32(identifier.size)
458 }
459
460 fn write_map_end(&mut self) -> ::Result<()> {
461 Ok(())
462 }
463
464 fn flush(&mut self) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500465 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400466 }
467
468 // utility
469 //
470
471 fn write_byte(&mut self, b: u8) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500472 self.transport.write_u8(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400473 }
474}
475
476/// Factory for creating instances of `TBinaryOutputProtocol`.
477#[derive(Default)]
478pub struct TBinaryOutputProtocolFactory;
479
480impl TBinaryOutputProtocolFactory {
481 /// Create a `TBinaryOutputProtocolFactory`.
482 pub fn new() -> TBinaryOutputProtocolFactory {
483 TBinaryOutputProtocolFactory {}
484 }
485}
486
487impl TOutputProtocolFactory for TBinaryOutputProtocolFactory {
Allen George0e22c362017-01-30 07:15:00 -0500488 fn create(&self, transport: Box<TWriteTransport + Send>) -> Box<TOutputProtocol + Send> {
489 Box::new(TBinaryOutputProtocol::new(transport, true))
Allen George8b96bfb2016-11-02 08:01:08 -0400490 }
491}
492
493fn field_type_to_u8(field_type: TType) -> u8 {
494 match field_type {
495 TType::Stop => 0x00,
496 TType::Void => 0x01,
497 TType::Bool => 0x02,
498 TType::I08 => 0x03, // equivalent to TType::Byte
499 TType::Double => 0x04,
500 TType::I16 => 0x06,
501 TType::I32 => 0x08,
502 TType::I64 => 0x0A,
503 TType::String | TType::Utf7 => 0x0B,
504 TType::Struct => 0x0C,
505 TType::Map => 0x0D,
506 TType::Set => 0x0E,
507 TType::List => 0x0F,
508 TType::Utf8 => 0x10,
509 TType::Utf16 => 0x11,
510 }
511}
512
513fn field_type_from_u8(b: u8) -> ::Result<TType> {
514 match b {
515 0x00 => Ok(TType::Stop),
516 0x01 => Ok(TType::Void),
517 0x02 => Ok(TType::Bool),
518 0x03 => Ok(TType::I08), // Equivalent to TType::Byte
519 0x04 => Ok(TType::Double),
520 0x06 => Ok(TType::I16),
521 0x08 => Ok(TType::I32),
522 0x0A => Ok(TType::I64),
523 0x0B => Ok(TType::String), // technically, also a UTF7, but we'll treat it as string
524 0x0C => Ok(TType::Struct),
525 0x0D => Ok(TType::Map),
526 0x0E => Ok(TType::Set),
527 0x0F => Ok(TType::List),
528 0x10 => Ok(TType::Utf8),
529 0x11 => Ok(TType::Utf16),
530 unkn => {
Allen George0e22c362017-01-30 07:15:00 -0500531 Err(
532 ::Error::Protocol(
533 ProtocolError {
534 kind: ProtocolErrorKind::InvalidData,
535 message: format!("cannot convert {} to TType", unkn),
536 },
537 ),
538 )
Allen George8b96bfb2016-11-02 08:01:08 -0400539 }
540 }
541}
542
543#[cfg(test)]
544mod tests {
545
Allen George0e22c362017-01-30 07:15:00 -0500546 use protocol::{TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier,
547 TMessageIdentifier, TMessageType, TOutputProtocol, TSetIdentifier,
548 TStructIdentifier, TType};
549 use transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400550
551 use super::*;
552
553 #[test]
554 fn must_write_message_call_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500555 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400556
557 let ident = TMessageIdentifier::new("test", TMessageType::Call, 1);
558 assert!(o_prot.write_message_begin(&ident).is_ok());
559
Allen George0e22c362017-01-30 07:15:00 -0500560 let expected: [u8; 16] = [
561 0x80,
562 0x01,
563 0x00,
564 0x01,
565 0x00,
566 0x00,
567 0x00,
568 0x04,
569 0x74,
570 0x65,
571 0x73,
572 0x74,
573 0x00,
574 0x00,
575 0x00,
576 0x01,
577 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400578
Allen George0e22c362017-01-30 07:15:00 -0500579 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400580 }
581
Allen George8b96bfb2016-11-02 08:01:08 -0400582 #[test]
583 fn must_write_message_reply_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500584 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400585
586 let ident = TMessageIdentifier::new("test", TMessageType::Reply, 10);
587 assert!(o_prot.write_message_begin(&ident).is_ok());
588
Allen George0e22c362017-01-30 07:15:00 -0500589 let expected: [u8; 16] = [
590 0x80,
591 0x01,
592 0x00,
593 0x02,
594 0x00,
595 0x00,
596 0x00,
597 0x04,
598 0x74,
599 0x65,
600 0x73,
601 0x74,
602 0x00,
603 0x00,
604 0x00,
605 0x0A,
606 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400607
Allen George0e22c362017-01-30 07:15:00 -0500608 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400609 }
610
611 #[test]
612 fn must_round_trip_strict_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500613 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400614
615 let sent_ident = TMessageIdentifier::new("test", TMessageType::Call, 1);
616 assert!(o_prot.write_message_begin(&sent_ident).is_ok());
617
Allen George0e22c362017-01-30 07:15:00 -0500618 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400619
620 let received_ident = assert_success!(i_prot.read_message_begin());
621 assert_eq!(&received_ident, &sent_ident);
622 }
623
624 #[test]
625 fn must_write_message_end() {
626 assert_no_write(|o| o.write_message_end());
627 }
628
629 #[test]
630 fn must_write_struct_begin() {
631 assert_no_write(|o| o.write_struct_begin(&TStructIdentifier::new("foo")));
632 }
633
634 #[test]
635 fn must_write_struct_end() {
636 assert_no_write(|o| o.write_struct_end());
637 }
638
639 #[test]
640 fn must_write_field_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500641 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400642
Allen George0e22c362017-01-30 07:15:00 -0500643 assert!(
644 o_prot
645 .write_field_begin(&TFieldIdentifier::new("some_field", TType::String, 22))
646 .is_ok()
647 );
Allen George8b96bfb2016-11-02 08:01:08 -0400648
649 let expected: [u8; 3] = [0x0B, 0x00, 0x16];
Allen George0e22c362017-01-30 07:15:00 -0500650 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400651 }
652
653 #[test]
654 fn must_round_trip_field_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500655 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400656
657 let sent_field_ident = TFieldIdentifier::new("foo", TType::I64, 20);
658 assert!(o_prot.write_field_begin(&sent_field_ident).is_ok());
659
Allen George0e22c362017-01-30 07:15:00 -0500660 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400661
662 let expected_ident = TFieldIdentifier {
663 name: None,
664 field_type: TType::I64,
665 id: Some(20),
666 }; // no name
667 let received_ident = assert_success!(i_prot.read_field_begin());
668 assert_eq!(&received_ident, &expected_ident);
669 }
670
671 #[test]
672 fn must_write_stop_field() {
Allen George0e22c362017-01-30 07:15:00 -0500673 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400674
675 assert!(o_prot.write_field_stop().is_ok());
676
677 let expected: [u8; 1] = [0x00];
Allen George0e22c362017-01-30 07:15:00 -0500678 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400679 }
680
681 #[test]
682 fn must_round_trip_field_stop() {
Allen George0e22c362017-01-30 07:15:00 -0500683 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400684
685 assert!(o_prot.write_field_stop().is_ok());
686
Allen George0e22c362017-01-30 07:15:00 -0500687 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400688
689 let expected_ident = TFieldIdentifier {
690 name: None,
691 field_type: TType::Stop,
692 id: Some(0),
693 }; // we get id 0
694
695 let received_ident = assert_success!(i_prot.read_field_begin());
696 assert_eq!(&received_ident, &expected_ident);
697 }
698
699 #[test]
700 fn must_write_field_end() {
701 assert_no_write(|o| o.write_field_end());
702 }
703
704 #[test]
705 fn must_write_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500706 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400707
Allen George0e22c362017-01-30 07:15:00 -0500708 assert!(
709 o_prot
710 .write_list_begin(&TListIdentifier::new(TType::Bool, 5))
711 .is_ok()
712 );
Allen George8b96bfb2016-11-02 08:01:08 -0400713
714 let expected: [u8; 5] = [0x02, 0x00, 0x00, 0x00, 0x05];
Allen George0e22c362017-01-30 07:15:00 -0500715 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400716 }
717
718 #[test]
719 fn must_round_trip_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500720 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400721
722 let ident = TListIdentifier::new(TType::List, 900);
723 assert!(o_prot.write_list_begin(&ident).is_ok());
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 received_ident = assert_success!(i_prot.read_list_begin());
728 assert_eq!(&received_ident, &ident);
729 }
730
731 #[test]
732 fn must_write_list_end() {
733 assert_no_write(|o| o.write_list_end());
734 }
735
736 #[test]
737 fn must_write_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500738 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400739
Allen George0e22c362017-01-30 07:15:00 -0500740 assert!(
741 o_prot
742 .write_set_begin(&TSetIdentifier::new(TType::I16, 7))
743 .is_ok()
744 );
Allen George8b96bfb2016-11-02 08:01:08 -0400745
746 let expected: [u8; 5] = [0x06, 0x00, 0x00, 0x00, 0x07];
Allen George0e22c362017-01-30 07:15:00 -0500747 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400748 }
749
750 #[test]
751 fn must_round_trip_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500752 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400753
754 let ident = TSetIdentifier::new(TType::I64, 2000);
755 assert!(o_prot.write_set_begin(&ident).is_ok());
756
Allen George0e22c362017-01-30 07:15:00 -0500757 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400758
759 let received_ident_result = i_prot.read_set_begin();
760 assert!(received_ident_result.is_ok());
761 assert_eq!(&received_ident_result.unwrap(), &ident);
762 }
763
764 #[test]
765 fn must_write_set_end() {
766 assert_no_write(|o| o.write_set_end());
767 }
768
769 #[test]
770 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500771 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400772
Allen George0e22c362017-01-30 07:15:00 -0500773 assert!(
774 o_prot
775 .write_map_begin(&TMapIdentifier::new(TType::I64, TType::Struct, 32))
776 .is_ok()
777 );
Allen George8b96bfb2016-11-02 08:01:08 -0400778
779 let expected: [u8; 6] = [0x0A, 0x0C, 0x00, 0x00, 0x00, 0x20];
Allen George0e22c362017-01-30 07:15:00 -0500780 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400781 }
782
783 #[test]
784 fn must_round_trip_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500785 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400786
787 let ident = TMapIdentifier::new(TType::Map, TType::Set, 100);
788 assert!(o_prot.write_map_begin(&ident).is_ok());
789
Allen George0e22c362017-01-30 07:15:00 -0500790 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400791
792 let received_ident = assert_success!(i_prot.read_map_begin());
793 assert_eq!(&received_ident, &ident);
794 }
795
796 #[test]
797 fn must_write_map_end() {
798 assert_no_write(|o| o.write_map_end());
799 }
800
801 #[test]
802 fn must_write_bool_true() {
Allen George0e22c362017-01-30 07:15:00 -0500803 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400804
805 assert!(o_prot.write_bool(true).is_ok());
806
807 let expected: [u8; 1] = [0x01];
Allen George0e22c362017-01-30 07:15:00 -0500808 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400809 }
810
811 #[test]
812 fn must_write_bool_false() {
Allen George0e22c362017-01-30 07:15:00 -0500813 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400814
815 assert!(o_prot.write_bool(false).is_ok());
816
817 let expected: [u8; 1] = [0x00];
Allen George0e22c362017-01-30 07:15:00 -0500818 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400819 }
820
821 #[test]
822 fn must_read_bool_true() {
Allen George0e22c362017-01-30 07:15:00 -0500823 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400824
Allen George0e22c362017-01-30 07:15:00 -0500825 set_readable_bytes!(i_prot, &[0x01]);
Allen George8b96bfb2016-11-02 08:01:08 -0400826
827 let read_bool = assert_success!(i_prot.read_bool());
828 assert_eq!(read_bool, true);
829 }
830
831 #[test]
832 fn must_read_bool_false() {
Allen George0e22c362017-01-30 07:15:00 -0500833 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400834
Allen George0e22c362017-01-30 07:15:00 -0500835 set_readable_bytes!(i_prot, &[0x00]);
Allen George8b96bfb2016-11-02 08:01:08 -0400836
837 let read_bool = assert_success!(i_prot.read_bool());
838 assert_eq!(read_bool, false);
839 }
840
841 #[test]
842 fn must_allow_any_non_zero_value_to_be_interpreted_as_bool_true() {
Allen George0e22c362017-01-30 07:15:00 -0500843 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400844
Allen George0e22c362017-01-30 07:15:00 -0500845 set_readable_bytes!(i_prot, &[0xAC]);
Allen George8b96bfb2016-11-02 08:01:08 -0400846
847 let read_bool = assert_success!(i_prot.read_bool());
848 assert_eq!(read_bool, true);
849 }
850
851 #[test]
852 fn must_write_bytes() {
Allen George0e22c362017-01-30 07:15:00 -0500853 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400854
855 let bytes: [u8; 10] = [0x0A, 0xCC, 0xD1, 0x84, 0x99, 0x12, 0xAB, 0xBB, 0x45, 0xDF];
856
857 assert!(o_prot.write_bytes(&bytes).is_ok());
858
Allen George0e22c362017-01-30 07:15:00 -0500859 let buf = o_prot.transport.write_bytes();
Allen George8b96bfb2016-11-02 08:01:08 -0400860 assert_eq!(&buf[0..4], [0x00, 0x00, 0x00, 0x0A]); // length
861 assert_eq!(&buf[4..], bytes); // actual bytes
862 }
863
864 #[test]
865 fn must_round_trip_bytes() {
Allen George0e22c362017-01-30 07:15:00 -0500866 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400867
Allen George0e22c362017-01-30 07:15:00 -0500868 let bytes: [u8; 25] = [
869 0x20,
870 0xFD,
871 0x18,
872 0x84,
873 0x99,
874 0x12,
875 0xAB,
876 0xBB,
877 0x45,
878 0xDF,
879 0x34,
880 0xDC,
881 0x98,
882 0xA4,
883 0x6D,
884 0xF3,
885 0x99,
886 0xB4,
887 0xB7,
888 0xD4,
889 0x9C,
890 0xA5,
891 0xB3,
892 0xC9,
893 0x88,
894 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400895
896 assert!(o_prot.write_bytes(&bytes).is_ok());
897
Allen George0e22c362017-01-30 07:15:00 -0500898 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400899
900 let received_bytes = assert_success!(i_prot.read_bytes());
901 assert_eq!(&received_bytes, &bytes);
902 }
903
Allen George0e22c362017-01-30 07:15:00 -0500904 fn test_objects()
905 -> (TBinaryInputProtocol<ReadHalf<TBufferChannel>>,
906 TBinaryOutputProtocol<WriteHalf<TBufferChannel>>)
Allen George8b96bfb2016-11-02 08:01:08 -0400907 {
Allen George0e22c362017-01-30 07:15:00 -0500908 let mem = TBufferChannel::with_capacity(40, 40);
Chao Sunc063b302017-03-12 12:21:05 -0700909
Allen George0e22c362017-01-30 07:15:00 -0500910 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400911
Allen George0e22c362017-01-30 07:15:00 -0500912 let i_prot = TBinaryInputProtocol::new(r_mem, true);
913 let o_prot = TBinaryOutputProtocol::new(w_mem, true);
Allen George8b96bfb2016-11-02 08:01:08 -0400914
Allen George0e22c362017-01-30 07:15:00 -0500915 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -0400916 }
917
Allen George0e22c362017-01-30 07:15:00 -0500918 fn assert_no_write<F>(mut write_fn: F)
919 where
920 F: FnMut(&mut TBinaryOutputProtocol<WriteHalf<TBufferChannel>>) -> ::Result<()>,
921 {
922 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400923 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -0500924 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -0400925 }
926}