blob: 8505b63344846b3c086e8d85722e42bc08410c7a [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 Georgebc1344d2017-04-28 10:22:03 -040058 pub transport: T, // FIXME: shouldn't be public
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 }
Allen George8b96bfb2016-11-02 08:01:08 -0400315}
316
Allen George0e22c362017-01-30 07:15:00 -0500317impl<T> TOutputProtocol for TBinaryOutputProtocol<T>
318where
319 T: TWriteTransport,
320{
Allen George8b96bfb2016-11-02 08:01:08 -0400321 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> ::Result<()> {
322 if self.strict {
323 let message_type: u8 = identifier.message_type.into();
324 let header = BINARY_PROTOCOL_VERSION_1 | (message_type as u32);
Allen George0e22c362017-01-30 07:15:00 -0500325 self.transport.write_u32::<BigEndian>(header)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400326 self.write_string(&identifier.name)?;
327 self.write_i32(identifier.sequence_number)
328 } else {
329 self.write_string(&identifier.name)?;
330 self.write_byte(identifier.message_type.into())?;
331 self.write_i32(identifier.sequence_number)
332 }
333 }
334
335 fn write_message_end(&mut self) -> ::Result<()> {
336 Ok(())
337 }
338
339 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> ::Result<()> {
340 Ok(())
341 }
342
343 fn write_struct_end(&mut self) -> ::Result<()> {
344 Ok(())
345 }
346
347 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> ::Result<()> {
348 if identifier.id.is_none() && identifier.field_type != TType::Stop {
Allen George0e22c362017-01-30 07:15:00 -0500349 return Err(
350 ::Error::Protocol(
351 ProtocolError {
352 kind: ProtocolErrorKind::Unknown,
353 message: format!(
354 "cannot write identifier {:?} without sequence number",
355 &identifier
356 ),
357 },
358 ),
359 );
Allen George8b96bfb2016-11-02 08:01:08 -0400360 }
361
362 self.write_byte(field_type_to_u8(identifier.field_type))?;
363 if let Some(id) = identifier.id {
364 self.write_i16(id)
365 } else {
366 Ok(())
367 }
368 }
369
370 fn write_field_end(&mut self) -> ::Result<()> {
371 Ok(())
372 }
373
374 fn write_field_stop(&mut self) -> ::Result<()> {
375 self.write_byte(field_type_to_u8(TType::Stop))
376 }
377
378 fn write_bytes(&mut self, b: &[u8]) -> ::Result<()> {
379 self.write_i32(b.len() as i32)?;
Allen Georgecf7ba4c2017-12-11 11:44:11 -0500380 self.transport.write_all(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400381 }
382
383 fn write_bool(&mut self, b: bool) -> ::Result<()> {
384 if b {
385 self.write_i8(1)
386 } else {
387 self.write_i8(0)
388 }
389 }
390
391 fn write_i8(&mut self, i: i8) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500392 self.transport.write_i8(i).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400393 }
394
395 fn write_i16(&mut self, i: i16) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500396 self.transport
397 .write_i16::<BigEndian>(i)
398 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400399 }
400
401 fn write_i32(&mut self, i: i32) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500402 self.transport
403 .write_i32::<BigEndian>(i)
404 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400405 }
406
407 fn write_i64(&mut self, i: i64) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500408 self.transport
409 .write_i64::<BigEndian>(i)
410 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400411 }
412
413 fn write_double(&mut self, d: f64) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500414 self.transport
415 .write_f64::<BigEndian>(d)
416 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400417 }
418
419 fn write_string(&mut self, s: &str) -> ::Result<()> {
420 self.write_bytes(s.as_bytes())
421 }
422
423 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> ::Result<()> {
424 self.write_byte(field_type_to_u8(identifier.element_type))?;
425 self.write_i32(identifier.size)
426 }
427
428 fn write_list_end(&mut self) -> ::Result<()> {
429 Ok(())
430 }
431
432 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> ::Result<()> {
433 self.write_byte(field_type_to_u8(identifier.element_type))?;
434 self.write_i32(identifier.size)
435 }
436
437 fn write_set_end(&mut self) -> ::Result<()> {
438 Ok(())
439 }
440
441 fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500442 let key_type = identifier
443 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400444 .expect("map identifier to write should contain key type");
445 self.write_byte(field_type_to_u8(key_type))?;
Allen George0e22c362017-01-30 07:15:00 -0500446 let val_type = identifier
447 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400448 .expect("map identifier to write should contain value type");
449 self.write_byte(field_type_to_u8(val_type))?;
450 self.write_i32(identifier.size)
451 }
452
453 fn write_map_end(&mut self) -> ::Result<()> {
454 Ok(())
455 }
456
457 fn flush(&mut self) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500458 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400459 }
460
461 // utility
462 //
463
464 fn write_byte(&mut self, b: u8) -> ::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500465 self.transport.write_u8(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400466 }
467}
468
469/// Factory for creating instances of `TBinaryOutputProtocol`.
470#[derive(Default)]
471pub struct TBinaryOutputProtocolFactory;
472
473impl TBinaryOutputProtocolFactory {
474 /// Create a `TBinaryOutputProtocolFactory`.
475 pub fn new() -> TBinaryOutputProtocolFactory {
476 TBinaryOutputProtocolFactory {}
477 }
478}
479
480impl TOutputProtocolFactory for TBinaryOutputProtocolFactory {
Allen George0e22c362017-01-30 07:15:00 -0500481 fn create(&self, transport: Box<TWriteTransport + Send>) -> Box<TOutputProtocol + Send> {
482 Box::new(TBinaryOutputProtocol::new(transport, true))
Allen George8b96bfb2016-11-02 08:01:08 -0400483 }
484}
485
486fn field_type_to_u8(field_type: TType) -> u8 {
487 match field_type {
488 TType::Stop => 0x00,
489 TType::Void => 0x01,
490 TType::Bool => 0x02,
491 TType::I08 => 0x03, // equivalent to TType::Byte
492 TType::Double => 0x04,
493 TType::I16 => 0x06,
494 TType::I32 => 0x08,
495 TType::I64 => 0x0A,
496 TType::String | TType::Utf7 => 0x0B,
497 TType::Struct => 0x0C,
498 TType::Map => 0x0D,
499 TType::Set => 0x0E,
500 TType::List => 0x0F,
501 TType::Utf8 => 0x10,
502 TType::Utf16 => 0x11,
503 }
504}
505
506fn field_type_from_u8(b: u8) -> ::Result<TType> {
507 match b {
508 0x00 => Ok(TType::Stop),
509 0x01 => Ok(TType::Void),
510 0x02 => Ok(TType::Bool),
511 0x03 => Ok(TType::I08), // Equivalent to TType::Byte
512 0x04 => Ok(TType::Double),
513 0x06 => Ok(TType::I16),
514 0x08 => Ok(TType::I32),
515 0x0A => Ok(TType::I64),
516 0x0B => Ok(TType::String), // technically, also a UTF7, but we'll treat it as string
517 0x0C => Ok(TType::Struct),
518 0x0D => Ok(TType::Map),
519 0x0E => Ok(TType::Set),
520 0x0F => Ok(TType::List),
521 0x10 => Ok(TType::Utf8),
522 0x11 => Ok(TType::Utf16),
523 unkn => {
Allen George0e22c362017-01-30 07:15:00 -0500524 Err(
525 ::Error::Protocol(
526 ProtocolError {
527 kind: ProtocolErrorKind::InvalidData,
528 message: format!("cannot convert {} to TType", unkn),
529 },
530 ),
531 )
Allen George8b96bfb2016-11-02 08:01:08 -0400532 }
533 }
534}
535
536#[cfg(test)]
537mod tests {
538
Allen George0e22c362017-01-30 07:15:00 -0500539 use protocol::{TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier,
540 TMessageIdentifier, TMessageType, TOutputProtocol, TSetIdentifier,
541 TStructIdentifier, TType};
542 use transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400543
544 use super::*;
545
546 #[test]
547 fn must_write_message_call_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500548 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400549
550 let ident = TMessageIdentifier::new("test", TMessageType::Call, 1);
551 assert!(o_prot.write_message_begin(&ident).is_ok());
552
Allen George0e22c362017-01-30 07:15:00 -0500553 let expected: [u8; 16] = [
554 0x80,
555 0x01,
556 0x00,
557 0x01,
558 0x00,
559 0x00,
560 0x00,
561 0x04,
562 0x74,
563 0x65,
564 0x73,
565 0x74,
566 0x00,
567 0x00,
568 0x00,
569 0x01,
570 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400571
Allen George0e22c362017-01-30 07:15:00 -0500572 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400573 }
574
Allen George8b96bfb2016-11-02 08:01:08 -0400575 #[test]
576 fn must_write_message_reply_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500577 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400578
579 let ident = TMessageIdentifier::new("test", TMessageType::Reply, 10);
580 assert!(o_prot.write_message_begin(&ident).is_ok());
581
Allen George0e22c362017-01-30 07:15:00 -0500582 let expected: [u8; 16] = [
583 0x80,
584 0x01,
585 0x00,
586 0x02,
587 0x00,
588 0x00,
589 0x00,
590 0x04,
591 0x74,
592 0x65,
593 0x73,
594 0x74,
595 0x00,
596 0x00,
597 0x00,
598 0x0A,
599 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400600
Allen George0e22c362017-01-30 07:15:00 -0500601 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400602 }
603
604 #[test]
605 fn must_round_trip_strict_message_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500606 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400607
608 let sent_ident = TMessageIdentifier::new("test", TMessageType::Call, 1);
609 assert!(o_prot.write_message_begin(&sent_ident).is_ok());
610
Allen George0e22c362017-01-30 07:15:00 -0500611 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400612
613 let received_ident = assert_success!(i_prot.read_message_begin());
614 assert_eq!(&received_ident, &sent_ident);
615 }
616
617 #[test]
618 fn must_write_message_end() {
619 assert_no_write(|o| o.write_message_end());
620 }
621
622 #[test]
623 fn must_write_struct_begin() {
624 assert_no_write(|o| o.write_struct_begin(&TStructIdentifier::new("foo")));
625 }
626
627 #[test]
628 fn must_write_struct_end() {
629 assert_no_write(|o| o.write_struct_end());
630 }
631
632 #[test]
633 fn must_write_field_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500634 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400635
Allen George0e22c362017-01-30 07:15:00 -0500636 assert!(
637 o_prot
638 .write_field_begin(&TFieldIdentifier::new("some_field", TType::String, 22))
639 .is_ok()
640 );
Allen George8b96bfb2016-11-02 08:01:08 -0400641
642 let expected: [u8; 3] = [0x0B, 0x00, 0x16];
Allen George0e22c362017-01-30 07:15:00 -0500643 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400644 }
645
646 #[test]
647 fn must_round_trip_field_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500648 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400649
650 let sent_field_ident = TFieldIdentifier::new("foo", TType::I64, 20);
651 assert!(o_prot.write_field_begin(&sent_field_ident).is_ok());
652
Allen George0e22c362017-01-30 07:15:00 -0500653 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400654
655 let expected_ident = TFieldIdentifier {
656 name: None,
657 field_type: TType::I64,
658 id: Some(20),
659 }; // no name
660 let received_ident = assert_success!(i_prot.read_field_begin());
661 assert_eq!(&received_ident, &expected_ident);
662 }
663
664 #[test]
665 fn must_write_stop_field() {
Allen George0e22c362017-01-30 07:15:00 -0500666 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400667
668 assert!(o_prot.write_field_stop().is_ok());
669
670 let expected: [u8; 1] = [0x00];
Allen George0e22c362017-01-30 07:15:00 -0500671 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400672 }
673
674 #[test]
675 fn must_round_trip_field_stop() {
Allen George0e22c362017-01-30 07:15:00 -0500676 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400677
678 assert!(o_prot.write_field_stop().is_ok());
679
Allen George0e22c362017-01-30 07:15:00 -0500680 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400681
682 let expected_ident = TFieldIdentifier {
683 name: None,
684 field_type: TType::Stop,
685 id: Some(0),
686 }; // we get id 0
687
688 let received_ident = assert_success!(i_prot.read_field_begin());
689 assert_eq!(&received_ident, &expected_ident);
690 }
691
692 #[test]
693 fn must_write_field_end() {
694 assert_no_write(|o| o.write_field_end());
695 }
696
697 #[test]
698 fn must_write_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500699 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400700
Allen George0e22c362017-01-30 07:15:00 -0500701 assert!(
702 o_prot
703 .write_list_begin(&TListIdentifier::new(TType::Bool, 5))
704 .is_ok()
705 );
Allen George8b96bfb2016-11-02 08:01:08 -0400706
707 let expected: [u8; 5] = [0x02, 0x00, 0x00, 0x00, 0x05];
Allen George0e22c362017-01-30 07:15:00 -0500708 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400709 }
710
711 #[test]
712 fn must_round_trip_list_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500713 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400714
715 let ident = TListIdentifier::new(TType::List, 900);
716 assert!(o_prot.write_list_begin(&ident).is_ok());
717
Allen George0e22c362017-01-30 07:15:00 -0500718 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400719
720 let received_ident = assert_success!(i_prot.read_list_begin());
721 assert_eq!(&received_ident, &ident);
722 }
723
724 #[test]
725 fn must_write_list_end() {
726 assert_no_write(|o| o.write_list_end());
727 }
728
729 #[test]
730 fn must_write_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500731 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400732
Allen George0e22c362017-01-30 07:15:00 -0500733 assert!(
734 o_prot
735 .write_set_begin(&TSetIdentifier::new(TType::I16, 7))
736 .is_ok()
737 );
Allen George8b96bfb2016-11-02 08:01:08 -0400738
739 let expected: [u8; 5] = [0x06, 0x00, 0x00, 0x00, 0x07];
Allen George0e22c362017-01-30 07:15:00 -0500740 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400741 }
742
743 #[test]
744 fn must_round_trip_set_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500745 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400746
747 let ident = TSetIdentifier::new(TType::I64, 2000);
748 assert!(o_prot.write_set_begin(&ident).is_ok());
749
Allen George0e22c362017-01-30 07:15:00 -0500750 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400751
752 let received_ident_result = i_prot.read_set_begin();
753 assert!(received_ident_result.is_ok());
754 assert_eq!(&received_ident_result.unwrap(), &ident);
755 }
756
757 #[test]
758 fn must_write_set_end() {
759 assert_no_write(|o| o.write_set_end());
760 }
761
762 #[test]
763 fn must_write_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500764 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400765
Allen George0e22c362017-01-30 07:15:00 -0500766 assert!(
767 o_prot
768 .write_map_begin(&TMapIdentifier::new(TType::I64, TType::Struct, 32))
769 .is_ok()
770 );
Allen George8b96bfb2016-11-02 08:01:08 -0400771
772 let expected: [u8; 6] = [0x0A, 0x0C, 0x00, 0x00, 0x00, 0x20];
Allen George0e22c362017-01-30 07:15:00 -0500773 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400774 }
775
776 #[test]
777 fn must_round_trip_map_begin() {
Allen George0e22c362017-01-30 07:15:00 -0500778 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400779
780 let ident = TMapIdentifier::new(TType::Map, TType::Set, 100);
781 assert!(o_prot.write_map_begin(&ident).is_ok());
782
Allen George0e22c362017-01-30 07:15:00 -0500783 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400784
785 let received_ident = assert_success!(i_prot.read_map_begin());
786 assert_eq!(&received_ident, &ident);
787 }
788
789 #[test]
790 fn must_write_map_end() {
791 assert_no_write(|o| o.write_map_end());
792 }
793
794 #[test]
795 fn must_write_bool_true() {
Allen George0e22c362017-01-30 07:15:00 -0500796 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400797
798 assert!(o_prot.write_bool(true).is_ok());
799
800 let expected: [u8; 1] = [0x01];
Allen George0e22c362017-01-30 07:15:00 -0500801 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400802 }
803
804 #[test]
805 fn must_write_bool_false() {
Allen George0e22c362017-01-30 07:15:00 -0500806 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400807
808 assert!(o_prot.write_bool(false).is_ok());
809
810 let expected: [u8; 1] = [0x00];
Allen George0e22c362017-01-30 07:15:00 -0500811 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400812 }
813
814 #[test]
815 fn must_read_bool_true() {
Allen George0e22c362017-01-30 07:15:00 -0500816 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400817
Allen George0e22c362017-01-30 07:15:00 -0500818 set_readable_bytes!(i_prot, &[0x01]);
Allen George8b96bfb2016-11-02 08:01:08 -0400819
820 let read_bool = assert_success!(i_prot.read_bool());
821 assert_eq!(read_bool, true);
822 }
823
824 #[test]
825 fn must_read_bool_false() {
Allen George0e22c362017-01-30 07:15:00 -0500826 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400827
Allen George0e22c362017-01-30 07:15:00 -0500828 set_readable_bytes!(i_prot, &[0x00]);
Allen George8b96bfb2016-11-02 08:01:08 -0400829
830 let read_bool = assert_success!(i_prot.read_bool());
831 assert_eq!(read_bool, false);
832 }
833
834 #[test]
835 fn must_allow_any_non_zero_value_to_be_interpreted_as_bool_true() {
Allen George0e22c362017-01-30 07:15:00 -0500836 let (mut i_prot, _) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400837
Allen George0e22c362017-01-30 07:15:00 -0500838 set_readable_bytes!(i_prot, &[0xAC]);
Allen George8b96bfb2016-11-02 08:01:08 -0400839
840 let read_bool = assert_success!(i_prot.read_bool());
841 assert_eq!(read_bool, true);
842 }
843
844 #[test]
845 fn must_write_bytes() {
Allen George0e22c362017-01-30 07:15:00 -0500846 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400847
848 let bytes: [u8; 10] = [0x0A, 0xCC, 0xD1, 0x84, 0x99, 0x12, 0xAB, 0xBB, 0x45, 0xDF];
849
850 assert!(o_prot.write_bytes(&bytes).is_ok());
851
Allen George0e22c362017-01-30 07:15:00 -0500852 let buf = o_prot.transport.write_bytes();
Allen George8b96bfb2016-11-02 08:01:08 -0400853 assert_eq!(&buf[0..4], [0x00, 0x00, 0x00, 0x0A]); // length
854 assert_eq!(&buf[4..], bytes); // actual bytes
855 }
856
857 #[test]
858 fn must_round_trip_bytes() {
Allen George0e22c362017-01-30 07:15:00 -0500859 let (mut i_prot, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400860
Allen George0e22c362017-01-30 07:15:00 -0500861 let bytes: [u8; 25] = [
862 0x20,
863 0xFD,
864 0x18,
865 0x84,
866 0x99,
867 0x12,
868 0xAB,
869 0xBB,
870 0x45,
871 0xDF,
872 0x34,
873 0xDC,
874 0x98,
875 0xA4,
876 0x6D,
877 0xF3,
878 0x99,
879 0xB4,
880 0xB7,
881 0xD4,
882 0x9C,
883 0xA5,
884 0xB3,
885 0xC9,
886 0x88,
887 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400888
889 assert!(o_prot.write_bytes(&bytes).is_ok());
890
Allen George0e22c362017-01-30 07:15:00 -0500891 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400892
893 let received_bytes = assert_success!(i_prot.read_bytes());
894 assert_eq!(&received_bytes, &bytes);
895 }
896
Allen George0e22c362017-01-30 07:15:00 -0500897 fn test_objects()
898 -> (TBinaryInputProtocol<ReadHalf<TBufferChannel>>,
899 TBinaryOutputProtocol<WriteHalf<TBufferChannel>>)
Allen George8b96bfb2016-11-02 08:01:08 -0400900 {
Allen George0e22c362017-01-30 07:15:00 -0500901 let mem = TBufferChannel::with_capacity(40, 40);
Chao Sunc063b302017-03-12 12:21:05 -0700902
Allen George0e22c362017-01-30 07:15:00 -0500903 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400904
Allen George0e22c362017-01-30 07:15:00 -0500905 let i_prot = TBinaryInputProtocol::new(r_mem, true);
906 let o_prot = TBinaryOutputProtocol::new(w_mem, true);
Allen George8b96bfb2016-11-02 08:01:08 -0400907
Allen George0e22c362017-01-30 07:15:00 -0500908 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -0400909 }
910
Allen George0e22c362017-01-30 07:15:00 -0500911 fn assert_no_write<F>(mut write_fn: F)
912 where
913 F: FnMut(&mut TBinaryOutputProtocol<WriteHalf<TBufferChannel>>) -> ::Result<()>,
914 {
915 let (_, mut o_prot) = test_objects();
Allen George8b96bfb2016-11-02 08:01:08 -0400916 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -0500917 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -0400918 }
919}