blob: 596285fb9f154dd2537f2ef2425c571f70746362 [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};
Danny Browningddec4312019-03-08 14:20:41 -070019use std::convert::{From, TryFrom};
Allen George8b96bfb2016-11-02 08:01:08 -040020
Allen Georgeef7a1892018-12-16 18:01:37 -050021use super::{
22 TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier, TMapIdentifier,
23 TMessageIdentifier, TMessageType,
24};
Allen George8b96bfb2016-11-02 08:01:08 -040025use super::{TOutputProtocol, TOutputProtocolFactory, TSetIdentifier, TStructIdentifier, TType};
Allen Georgeb0d14132020-03-29 11:48:55 -040026use crate::transport::{TReadTransport, TWriteTransport};
Hasnain Lakhani42d0b712025-07-17 19:57:05 -070027use crate::{ProtocolError, ProtocolErrorKind, TConfiguration};
Allen George8b96bfb2016-11-02 08:01:08 -040028
Allen George7ddbcc02020-11-08 09:51:19 -050029const BINARY_PROTOCOL_VERSION_1: u32 = 0x8001_0000;
Allen George8b96bfb2016-11-02 08:01:08 -040030
31/// Read messages encoded in the Thrift simple binary encoding.
32///
33/// There are two available modes: `strict` and `non-strict`, where the
34/// `non-strict` version does not check for the protocol version in the
35/// received message header.
36///
37/// # Examples
38///
39/// Create and use a `TBinaryInputProtocol`.
40///
41/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -040042/// use thrift::protocol::{TBinaryInputProtocol, TInputProtocol};
Allen George0e22c362017-01-30 07:15:00 -050043/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -040044///
Allen George0e22c362017-01-30 07:15:00 -050045/// let mut channel = TTcpChannel::new();
46/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040047///
Allen George0e22c362017-01-30 07:15:00 -050048/// let mut protocol = TBinaryInputProtocol::new(channel, true);
Allen George8b96bfb2016-11-02 08:01:08 -040049///
Allen George0e22c362017-01-30 07:15:00 -050050/// let recvd_bool = protocol.read_bool().unwrap();
51/// let recvd_string = protocol.read_string().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -040052/// ```
Allen George0e22c362017-01-30 07:15:00 -050053#[derive(Debug)]
54pub struct TBinaryInputProtocol<T>
55where
56 T: TReadTransport,
57{
Allen George8b96bfb2016-11-02 08:01:08 -040058 strict: bool,
Allen Georgebc1344d2017-04-28 10:22:03 -040059 pub transport: T, // FIXME: shouldn't be public
Hasnain Lakhani42d0b712025-07-17 19:57:05 -070060 config: TConfiguration,
61 recursion_depth: usize,
Allen George8b96bfb2016-11-02 08:01:08 -040062}
63
Jiayu Liufbfa52c2023-11-07 13:47:24 +080064impl<T> TBinaryInputProtocol<T>
Allen George0e22c362017-01-30 07:15:00 -050065where
66 T: TReadTransport,
67{
Allen George8b96bfb2016-11-02 08:01:08 -040068 /// Create a `TBinaryInputProtocol` that reads bytes from `transport`.
69 ///
70 /// Set `strict` to `true` if all incoming messages contain the protocol
71 /// version number in the protocol header.
Hasnain Lakhani42d0b712025-07-17 19:57:05 -070072 pub fn new(transport: T, strict: bool) -> Self {
73 Self::with_config(transport, strict, TConfiguration::default())
74 }
75
76 pub fn with_config(transport: T, strict: bool, config: TConfiguration) -> Self {
77 TBinaryInputProtocol {
78 strict,
79 transport,
80 config,
81 recursion_depth: 0,
82 }
83 }
84
85 fn check_recursion_depth(&self) -> crate::Result<()> {
86 if let Some(limit) = self.config.max_recursion_depth() {
87 if self.recursion_depth >= limit {
88 return Err(crate::Error::Protocol(ProtocolError::new(
89 ProtocolErrorKind::DepthLimit,
90 format!("Maximum recursion depth {} exceeded", limit),
91 )));
92 }
93 }
94 Ok(())
Allen George8b96bfb2016-11-02 08:01:08 -040095 }
96}
97
Allen George0e22c362017-01-30 07:15:00 -050098impl<T> TInputProtocol for TBinaryInputProtocol<T>
99where
100 T: TReadTransport,
101{
Allen George7ddbcc02020-11-08 09:51:19 -0500102 #[allow(clippy::collapsible_if)]
Allen Georgeb0d14132020-03-29 11:48:55 -0400103 fn read_message_begin(&mut self) -> crate::Result<TMessageIdentifier> {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700104 // TODO: Once specialization is stable, call the message size tracking here
Allen George8b96bfb2016-11-02 08:01:08 -0400105 let mut first_bytes = vec![0; 4];
Allen George0e22c362017-01-30 07:15:00 -0500106 self.transport.read_exact(&mut first_bytes[..])?;
Allen George8b96bfb2016-11-02 08:01:08 -0400107
108 // the thrift version header is intentionally negative
109 // so the first check we'll do is see if the sign bit is set
110 // and if so - assume it's the protocol-version header
Yuxuan 'fishy' Wangeadbd9c2022-01-27 13:17:37 -0800111 if (first_bytes[0] & 0x80) != 0 {
Allen George8b96bfb2016-11-02 08:01:08 -0400112 // apparently we got a protocol-version header - check
113 // it, and if it matches, read the rest of the fields
114 if first_bytes[0..2] != [0x80, 0x01] {
Allen Georgeb0d14132020-03-29 11:48:55 -0400115 Err(crate::Error::Protocol(ProtocolError {
Allen Georgeef7a1892018-12-16 18:01:37 -0500116 kind: ProtocolErrorKind::BadVersion,
117 message: format!("received bad version: {:?}", &first_bytes[0..2]),
118 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400119 } else {
120 let message_type: TMessageType = TryFrom::try_from(first_bytes[3])?;
121 let name = self.read_string()?;
122 let sequence_number = self.read_i32()?;
123 Ok(TMessageIdentifier::new(name, message_type, sequence_number))
124 }
125 } else {
126 // apparently we didn't get a protocol-version header,
127 // which happens if the sender is not using the strict protocol
128 if self.strict {
129 // we're in strict mode however, and that always
130 // requires the protocol-version header to be written first
Allen Georgeb0d14132020-03-29 11:48:55 -0400131 Err(crate::Error::Protocol(ProtocolError {
Allen Georgeef7a1892018-12-16 18:01:37 -0500132 kind: ProtocolErrorKind::BadVersion,
133 message: format!("received bad version: {:?}", &first_bytes[0..2]),
134 }))
Allen George8b96bfb2016-11-02 08:01:08 -0400135 } else {
136 // in the non-strict version the first message field
137 // is the message name. strings (byte arrays) are length-prefixed,
138 // so we've just read the length in the first 4 bytes
139 let name_size = BigEndian::read_i32(&first_bytes) as usize;
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500140 let mut name_buf: Vec<u8> = vec![0; name_size];
Allen George0e22c362017-01-30 07:15:00 -0500141 self.transport.read_exact(&mut name_buf)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400142 let name = String::from_utf8(name_buf)?;
143
144 // read the rest of the fields
145 let message_type: TMessageType = self.read_byte().and_then(TryFrom::try_from)?;
146 let sequence_number = self.read_i32()?;
147 Ok(TMessageIdentifier::new(name, message_type, sequence_number))
148 }
149 }
150 }
151
Allen Georgeb0d14132020-03-29 11:48:55 -0400152 fn read_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400153 Ok(())
154 }
155
Allen Georgeb0d14132020-03-29 11:48:55 -0400156 fn read_struct_begin(&mut self) -> crate::Result<Option<TStructIdentifier>> {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700157 self.check_recursion_depth()?;
158 self.recursion_depth += 1;
Allen George8b96bfb2016-11-02 08:01:08 -0400159 Ok(None)
160 }
161
Allen Georgeb0d14132020-03-29 11:48:55 -0400162 fn read_struct_end(&mut self) -> crate::Result<()> {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700163 self.recursion_depth -= 1;
Allen George8b96bfb2016-11-02 08:01:08 -0400164 Ok(())
165 }
166
Allen Georgeb0d14132020-03-29 11:48:55 -0400167 fn read_field_begin(&mut self) -> crate::Result<TFieldIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400168 let field_type_byte = self.read_byte()?;
169 let field_type = field_type_from_u8(field_type_byte)?;
170 let id = match field_type {
171 TType::Stop => Ok(0),
172 _ => self.read_i16(),
173 }?;
Allen Georgeef7a1892018-12-16 18:01:37 -0500174 Ok(TFieldIdentifier::new::<Option<String>, String, i16>(
175 None, field_type, id,
176 ))
Allen George8b96bfb2016-11-02 08:01:08 -0400177 }
178
Allen Georgeb0d14132020-03-29 11:48:55 -0400179 fn read_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400180 Ok(())
181 }
182
Allen Georgeb0d14132020-03-29 11:48:55 -0400183 fn read_bytes(&mut self) -> crate::Result<Vec<u8>> {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700184 let num_bytes = self.transport.read_i32::<BigEndian>()?;
185
186 if num_bytes < 0 {
187 return Err(crate::Error::Protocol(ProtocolError::new(
188 ProtocolErrorKind::NegativeSize,
189 format!("Negative byte array size: {}", num_bytes),
190 )));
191 }
192
193 if let Some(max_size) = self.config.max_string_size() {
194 if num_bytes as usize > max_size {
195 return Err(crate::Error::Protocol(ProtocolError::new(
196 ProtocolErrorKind::SizeLimit,
197 format!(
198 "Byte array size {} exceeds maximum allowed size of {}",
199 num_bytes, max_size
200 ),
201 )));
202 }
203 }
204
205 let mut buf = vec![0u8; num_bytes as usize];
Allen George0e22c362017-01-30 07:15:00 -0500206 self.transport
207 .read_exact(&mut buf)
208 .map(|_| buf)
209 .map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400210 }
211
Allen Georgeb0d14132020-03-29 11:48:55 -0400212 fn read_bool(&mut self) -> crate::Result<bool> {
Allen George8b96bfb2016-11-02 08:01:08 -0400213 let b = self.read_i8()?;
214 match b {
215 0 => Ok(false),
216 _ => Ok(true),
217 }
218 }
219
Allen Georgeb0d14132020-03-29 11:48:55 -0400220 fn read_i8(&mut self) -> crate::Result<i8> {
Allen George0e22c362017-01-30 07:15:00 -0500221 self.transport.read_i8().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400222 }
223
Allen Georgeb0d14132020-03-29 11:48:55 -0400224 fn read_i16(&mut self) -> crate::Result<i16> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500225 self.transport.read_i16::<BigEndian>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400226 }
227
Allen Georgeb0d14132020-03-29 11:48:55 -0400228 fn read_i32(&mut self) -> crate::Result<i32> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500229 self.transport.read_i32::<BigEndian>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400230 }
231
Allen Georgeb0d14132020-03-29 11:48:55 -0400232 fn read_i64(&mut self) -> crate::Result<i64> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500233 self.transport.read_i64::<BigEndian>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400234 }
235
Allen Georgeb0d14132020-03-29 11:48:55 -0400236 fn read_double(&mut self) -> crate::Result<f64> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500237 self.transport.read_f64::<BigEndian>().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400238 }
239
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800240 fn read_uuid(&mut self) -> crate::Result<uuid::Uuid> {
241 let mut buf = [0u8; 16];
242 self.transport
243 .read_exact(&mut buf)
244 .map(|_| uuid::Uuid::from_bytes(buf))
245 .map_err(From::from)
246 }
247
Allen Georgeb0d14132020-03-29 11:48:55 -0400248 fn read_string(&mut self) -> crate::Result<String> {
Allen George8b96bfb2016-11-02 08:01:08 -0400249 let bytes = self.read_bytes()?;
250 String::from_utf8(bytes).map_err(From::from)
251 }
252
Allen Georgeb0d14132020-03-29 11:48:55 -0400253 fn read_list_begin(&mut self) -> crate::Result<TListIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400254 let element_type: TType = self.read_byte().and_then(field_type_from_u8)?;
255 let size = self.read_i32()?;
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700256 let min_element_size = self.min_serialized_size(element_type);
257 super::check_container_size(&self.config, size, min_element_size)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400258 Ok(TListIdentifier::new(element_type, size))
259 }
260
Allen Georgeb0d14132020-03-29 11:48:55 -0400261 fn read_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400262 Ok(())
263 }
264
Allen Georgeb0d14132020-03-29 11:48:55 -0400265 fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400266 let element_type: TType = self.read_byte().and_then(field_type_from_u8)?;
267 let size = self.read_i32()?;
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700268 let min_element_size = self.min_serialized_size(element_type);
269 super::check_container_size(&self.config, size, min_element_size)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400270 Ok(TSetIdentifier::new(element_type, size))
271 }
272
Allen Georgeb0d14132020-03-29 11:48:55 -0400273 fn read_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400274 Ok(())
275 }
276
Allen Georgeb0d14132020-03-29 11:48:55 -0400277 fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier> {
Allen George8b96bfb2016-11-02 08:01:08 -0400278 let key_type: TType = self.read_byte().and_then(field_type_from_u8)?;
279 let value_type: TType = self.read_byte().and_then(field_type_from_u8)?;
280 let size = self.read_i32()?;
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700281
282 let key_min_size = self.min_serialized_size(key_type);
283 let value_min_size = self.min_serialized_size(value_type);
284 let element_size = key_min_size + value_min_size;
285 super::check_container_size(&self.config, size, element_size)?;
286
Allen George8b96bfb2016-11-02 08:01:08 -0400287 Ok(TMapIdentifier::new(key_type, value_type, size))
288 }
289
Allen Georgeb0d14132020-03-29 11:48:55 -0400290 fn read_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400291 Ok(())
292 }
293
294 // utility
295 //
296
Allen Georgeb0d14132020-03-29 11:48:55 -0400297 fn read_byte(&mut self) -> crate::Result<u8> {
Allen George0e22c362017-01-30 07:15:00 -0500298 self.transport.read_u8().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400299 }
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700300
301 fn min_serialized_size(&self, field_type: TType) -> usize {
302 match field_type {
303 TType::Stop => 1, // 1 byte minimum
304 TType::Void => 1, // 1 byte minimum
305 TType::Bool => 1, // 1 byte
306 TType::I08 => 1, // 1 byte
307 TType::Double => 8, // 8 bytes
308 TType::I16 => 2, // 2 bytes
309 TType::I32 => 4, // 4 bytes
310 TType::I64 => 8, // 8 bytes
311 TType::String => 4, // 4 bytes for length prefix
312 TType::Struct => 1, // 1 byte minimum (stop field)
313 TType::Map => 4, // 4 bytes size
314 TType::Set => 4, // 4 bytes size
315 TType::List => 4, // 4 bytes size
316 TType::Uuid => 16, // 16 bytes
317 TType::Utf7 => 1, // 1 byte
318 }
319 }
Allen George8b96bfb2016-11-02 08:01:08 -0400320}
321
322/// Factory for creating instances of `TBinaryInputProtocol`.
323#[derive(Default)]
324pub struct TBinaryInputProtocolFactory;
325
326impl TBinaryInputProtocolFactory {
327 /// Create a `TBinaryInputProtocolFactory`.
328 pub fn new() -> TBinaryInputProtocolFactory {
329 TBinaryInputProtocolFactory {}
330 }
331}
332
333impl TInputProtocolFactory for TBinaryInputProtocolFactory {
Danny Browning77d96c12019-08-21 13:41:07 -0600334 fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500335 Box::new(TBinaryInputProtocol::new(transport, true))
Allen George8b96bfb2016-11-02 08:01:08 -0400336 }
337}
338
339/// Write messages using the Thrift simple binary encoding.
340///
341/// There are two available modes: `strict` and `non-strict`, where the
342/// `strict` version writes the protocol version number in the outgoing message
343/// header and the `non-strict` version does not.
344///
345/// # Examples
346///
347/// Create and use a `TBinaryOutputProtocol`.
348///
349/// ```no_run
Allen George8b96bfb2016-11-02 08:01:08 -0400350/// use thrift::protocol::{TBinaryOutputProtocol, TOutputProtocol};
Allen George0e22c362017-01-30 07:15:00 -0500351/// use thrift::transport::TTcpChannel;
Allen George8b96bfb2016-11-02 08:01:08 -0400352///
Allen George0e22c362017-01-30 07:15:00 -0500353/// let mut channel = TTcpChannel::new();
354/// channel.open("localhost:9090").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400355///
Allen George0e22c362017-01-30 07:15:00 -0500356/// let mut protocol = TBinaryOutputProtocol::new(channel, true);
Allen George8b96bfb2016-11-02 08:01:08 -0400357///
Allen George0e22c362017-01-30 07:15:00 -0500358/// protocol.write_bool(true).unwrap();
359/// protocol.write_string("test_string").unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -0400360/// ```
Allen George0e22c362017-01-30 07:15:00 -0500361#[derive(Debug)]
362pub struct TBinaryOutputProtocol<T>
363where
364 T: TWriteTransport,
365{
Allen George8b96bfb2016-11-02 08:01:08 -0400366 strict: bool,
Allen George0e22c362017-01-30 07:15:00 -0500367 pub transport: T, // FIXME: do not make public; only public for testing!
Allen George8b96bfb2016-11-02 08:01:08 -0400368}
369
Allen George0e22c362017-01-30 07:15:00 -0500370impl<T> TBinaryOutputProtocol<T>
371where
372 T: TWriteTransport,
373{
Allen George8b96bfb2016-11-02 08:01:08 -0400374 /// Create a `TBinaryOutputProtocol` that writes bytes to `transport`.
375 ///
376 /// Set `strict` to `true` if all outgoing messages should contain the
377 /// protocol version number in the protocol header.
Allen George0e22c362017-01-30 07:15:00 -0500378 pub fn new(transport: T, strict: bool) -> TBinaryOutputProtocol<T> {
Allen George55c3e4c2021-03-01 23:19:52 -0500379 TBinaryOutputProtocol { strict, transport }
Allen George8b96bfb2016-11-02 08:01:08 -0400380 }
Allen George8b96bfb2016-11-02 08:01:08 -0400381}
382
Allen George0e22c362017-01-30 07:15:00 -0500383impl<T> TOutputProtocol for TBinaryOutputProtocol<T>
384where
385 T: TWriteTransport,
386{
Allen Georgeb0d14132020-03-29 11:48:55 -0400387 fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400388 if self.strict {
389 let message_type: u8 = identifier.message_type.into();
390 let header = BINARY_PROTOCOL_VERSION_1 | (message_type as u32);
Allen George0e22c362017-01-30 07:15:00 -0500391 self.transport.write_u32::<BigEndian>(header)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400392 self.write_string(&identifier.name)?;
393 self.write_i32(identifier.sequence_number)
394 } else {
395 self.write_string(&identifier.name)?;
396 self.write_byte(identifier.message_type.into())?;
397 self.write_i32(identifier.sequence_number)
398 }
399 }
400
Allen Georgeb0d14132020-03-29 11:48:55 -0400401 fn write_message_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400402 Ok(())
403 }
404
Allen Georgeb0d14132020-03-29 11:48:55 -0400405 fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400406 Ok(())
407 }
408
Allen Georgeb0d14132020-03-29 11:48:55 -0400409 fn write_struct_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400410 Ok(())
411 }
412
Allen Georgeb0d14132020-03-29 11:48:55 -0400413 fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400414 if identifier.id.is_none() && identifier.field_type != TType::Stop {
Allen Georgeb0d14132020-03-29 11:48:55 -0400415 return Err(crate::Error::Protocol(ProtocolError {
Allen Georgeef7a1892018-12-16 18:01:37 -0500416 kind: ProtocolErrorKind::Unknown,
417 message: format!(
418 "cannot write identifier {:?} without sequence number",
419 &identifier
Allen George0e22c362017-01-30 07:15:00 -0500420 ),
Allen Georgeef7a1892018-12-16 18:01:37 -0500421 }));
Allen George8b96bfb2016-11-02 08:01:08 -0400422 }
423
424 self.write_byte(field_type_to_u8(identifier.field_type))?;
425 if let Some(id) = identifier.id {
426 self.write_i16(id)
427 } else {
428 Ok(())
429 }
430 }
431
Allen Georgeb0d14132020-03-29 11:48:55 -0400432 fn write_field_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400433 Ok(())
434 }
435
Allen Georgeb0d14132020-03-29 11:48:55 -0400436 fn write_field_stop(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400437 self.write_byte(field_type_to_u8(TType::Stop))
438 }
439
Allen Georgeb0d14132020-03-29 11:48:55 -0400440 fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400441 self.write_i32(b.len() as i32)?;
Allen Georgecf7ba4c2017-12-11 11:44:11 -0500442 self.transport.write_all(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400443 }
444
Allen Georgeb0d14132020-03-29 11:48:55 -0400445 fn write_bool(&mut self, b: bool) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400446 if b {
447 self.write_i8(1)
448 } else {
449 self.write_i8(0)
450 }
451 }
452
Allen Georgeb0d14132020-03-29 11:48:55 -0400453 fn write_i8(&mut self, i: i8) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500454 self.transport.write_i8(i).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400455 }
456
Allen Georgeb0d14132020-03-29 11:48:55 -0400457 fn write_i16(&mut self, i: i16) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500458 self.transport.write_i16::<BigEndian>(i).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400459 }
460
Allen Georgeb0d14132020-03-29 11:48:55 -0400461 fn write_i32(&mut self, i: i32) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500462 self.transport.write_i32::<BigEndian>(i).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400463 }
464
Allen Georgeb0d14132020-03-29 11:48:55 -0400465 fn write_i64(&mut self, i: i64) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500466 self.transport.write_i64::<BigEndian>(i).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400467 }
468
Allen Georgeb0d14132020-03-29 11:48:55 -0400469 fn write_double(&mut self, d: f64) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500470 self.transport.write_f64::<BigEndian>(d).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400471 }
472
Allen Georgeb0d14132020-03-29 11:48:55 -0400473 fn write_string(&mut self, s: &str) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400474 self.write_bytes(s.as_bytes())
475 }
476
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800477 fn write_uuid(&mut self, uuid: &uuid::Uuid) -> crate::Result<()> {
478 self.transport
479 .write_all(uuid.as_bytes())
480 .map_err(From::from)
481 }
482
Allen Georgeb0d14132020-03-29 11:48:55 -0400483 fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400484 self.write_byte(field_type_to_u8(identifier.element_type))?;
485 self.write_i32(identifier.size)
486 }
487
Allen Georgeb0d14132020-03-29 11:48:55 -0400488 fn write_list_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400489 Ok(())
490 }
491
Allen Georgeb0d14132020-03-29 11:48:55 -0400492 fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400493 self.write_byte(field_type_to_u8(identifier.element_type))?;
494 self.write_i32(identifier.size)
495 }
496
Allen Georgeb0d14132020-03-29 11:48:55 -0400497 fn write_set_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400498 Ok(())
499 }
500
Allen Georgeb0d14132020-03-29 11:48:55 -0400501 fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500502 let key_type = identifier
503 .key_type
Allen George8b96bfb2016-11-02 08:01:08 -0400504 .expect("map identifier to write should contain key type");
505 self.write_byte(field_type_to_u8(key_type))?;
Allen George0e22c362017-01-30 07:15:00 -0500506 let val_type = identifier
507 .value_type
Allen George8b96bfb2016-11-02 08:01:08 -0400508 .expect("map identifier to write should contain value type");
509 self.write_byte(field_type_to_u8(val_type))?;
510 self.write_i32(identifier.size)
511 }
512
Allen Georgeb0d14132020-03-29 11:48:55 -0400513 fn write_map_end(&mut self) -> crate::Result<()> {
Allen George8b96bfb2016-11-02 08:01:08 -0400514 Ok(())
515 }
516
Allen Georgeb0d14132020-03-29 11:48:55 -0400517 fn flush(&mut self) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500518 self.transport.flush().map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400519 }
520
521 // utility
522 //
523
Allen Georgeb0d14132020-03-29 11:48:55 -0400524 fn write_byte(&mut self, b: u8) -> crate::Result<()> {
Allen George0e22c362017-01-30 07:15:00 -0500525 self.transport.write_u8(b).map_err(From::from)
Allen George8b96bfb2016-11-02 08:01:08 -0400526 }
527}
528
529/// Factory for creating instances of `TBinaryOutputProtocol`.
530#[derive(Default)]
531pub struct TBinaryOutputProtocolFactory;
532
533impl TBinaryOutputProtocolFactory {
534 /// Create a `TBinaryOutputProtocolFactory`.
535 pub fn new() -> TBinaryOutputProtocolFactory {
536 TBinaryOutputProtocolFactory {}
537 }
538}
539
540impl TOutputProtocolFactory for TBinaryOutputProtocolFactory {
Allen George55c3e4c2021-03-01 23:19:52 -0500541 fn create(
542 &self,
543 transport: Box<dyn TWriteTransport + Send>,
544 ) -> Box<dyn TOutputProtocol + Send> {
Allen George0e22c362017-01-30 07:15:00 -0500545 Box::new(TBinaryOutputProtocol::new(transport, true))
Allen George8b96bfb2016-11-02 08:01:08 -0400546 }
547}
548
549fn field_type_to_u8(field_type: TType) -> u8 {
550 match field_type {
551 TType::Stop => 0x00,
552 TType::Void => 0x01,
553 TType::Bool => 0x02,
554 TType::I08 => 0x03, // equivalent to TType::Byte
555 TType::Double => 0x04,
556 TType::I16 => 0x06,
557 TType::I32 => 0x08,
558 TType::I64 => 0x0A,
559 TType::String | TType::Utf7 => 0x0B,
560 TType::Struct => 0x0C,
561 TType::Map => 0x0D,
562 TType::Set => 0x0E,
563 TType::List => 0x0F,
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800564 TType::Uuid => 0x10,
Allen George8b96bfb2016-11-02 08:01:08 -0400565 }
566}
567
Allen Georgeb0d14132020-03-29 11:48:55 -0400568fn field_type_from_u8(b: u8) -> crate::Result<TType> {
Allen George8b96bfb2016-11-02 08:01:08 -0400569 match b {
570 0x00 => Ok(TType::Stop),
571 0x01 => Ok(TType::Void),
572 0x02 => Ok(TType::Bool),
573 0x03 => Ok(TType::I08), // Equivalent to TType::Byte
574 0x04 => Ok(TType::Double),
575 0x06 => Ok(TType::I16),
576 0x08 => Ok(TType::I32),
577 0x0A => Ok(TType::I64),
578 0x0B => Ok(TType::String), // technically, also a UTF7, but we'll treat it as string
579 0x0C => Ok(TType::Struct),
580 0x0D => Ok(TType::Map),
581 0x0E => Ok(TType::Set),
582 0x0F => Ok(TType::List),
Jiayu Liub6b6dc72022-10-08 14:28:44 +0800583 0x10 => Ok(TType::Uuid),
Allen Georgeb0d14132020-03-29 11:48:55 -0400584 unkn => Err(crate::Error::Protocol(ProtocolError {
Allen Georgeef7a1892018-12-16 18:01:37 -0500585 kind: ProtocolErrorKind::InvalidData,
586 message: format!("cannot convert {} to TType", unkn),
587 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400588 }
589}
590
591#[cfg(test)]
592mod tests {
593
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700594 use super::*;
Allen Georgeb0d14132020-03-29 11:48:55 -0400595 use crate::protocol::{
Allen Georgeef7a1892018-12-16 18:01:37 -0500596 TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
597 TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
598 };
Allen Georgeb0d14132020-03-29 11:48:55 -0400599 use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
Allen George8b96bfb2016-11-02 08:01:08 -0400600
Allen George8b96bfb2016-11-02 08:01:08 -0400601 #[test]
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500602 fn must_write_strict_message_call_begin() {
603 let (_, mut o_prot) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -0400604
605 let ident = TMessageIdentifier::new("test", TMessageType::Call, 1);
606 assert!(o_prot.write_message_begin(&ident).is_ok());
607
Allen George7ddbcc02020-11-08 09:51:19 -0500608 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500609 let expected: [u8; 16] = [
610 0x80,
611 0x01,
612 0x00,
613 0x01,
614 0x00,
615 0x00,
616 0x00,
617 0x04,
618 0x74,
619 0x65,
620 0x73,
621 0x74,
622 0x00,
623 0x00,
624 0x00,
625 0x01,
626 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400627
Allen George0e22c362017-01-30 07:15:00 -0500628 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400629 }
630
Allen George8b96bfb2016-11-02 08:01:08 -0400631 #[test]
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500632 fn must_write_non_strict_message_call_begin() {
633 let (_, mut o_prot) = test_objects(false);
634
635 let ident = TMessageIdentifier::new("test", TMessageType::Call, 1);
636 assert!(o_prot.write_message_begin(&ident).is_ok());
637
Allen George7ddbcc02020-11-08 09:51:19 -0500638 #[rustfmt::skip]
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500639 let expected: [u8; 13] = [
640 0x00,
641 0x00,
642 0x00,
643 0x04,
644 0x74,
645 0x65,
646 0x73,
647 0x74,
648 0x01,
649 0x00,
650 0x00,
651 0x00,
652 0x01,
653 ];
654
655 assert_eq_written_bytes!(o_prot, expected);
656 }
657
658 #[test]
659 fn must_write_strict_message_reply_begin() {
660 let (_, mut o_prot) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -0400661
662 let ident = TMessageIdentifier::new("test", TMessageType::Reply, 10);
663 assert!(o_prot.write_message_begin(&ident).is_ok());
664
Allen George7ddbcc02020-11-08 09:51:19 -0500665 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -0500666 let expected: [u8; 16] = [
667 0x80,
668 0x01,
669 0x00,
670 0x02,
671 0x00,
672 0x00,
673 0x00,
674 0x04,
675 0x74,
676 0x65,
677 0x73,
678 0x74,
679 0x00,
680 0x00,
681 0x00,
682 0x0A,
683 ];
Allen George8b96bfb2016-11-02 08:01:08 -0400684
Allen George0e22c362017-01-30 07:15:00 -0500685 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400686 }
687
688 #[test]
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500689 fn must_write_non_strict_message_reply_begin() {
690 let (_, mut o_prot) = test_objects(false);
691
692 let ident = TMessageIdentifier::new("test", TMessageType::Reply, 10);
693 assert!(o_prot.write_message_begin(&ident).is_ok());
694
Allen George7ddbcc02020-11-08 09:51:19 -0500695 #[rustfmt::skip]
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500696 let expected: [u8; 13] = [
697 0x00,
698 0x00,
699 0x00,
700 0x04,
701 0x74,
702 0x65,
703 0x73,
704 0x74,
705 0x02,
706 0x00,
707 0x00,
708 0x00,
709 0x0A,
710 ];
711
712 assert_eq_written_bytes!(o_prot, expected);
713 }
714
715 #[test]
Allen George8b96bfb2016-11-02 08:01:08 -0400716 fn must_round_trip_strict_message_begin() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500717 let (mut i_prot, mut o_prot) = test_objects(true);
718
719 let sent_ident = TMessageIdentifier::new("test", TMessageType::Call, 1);
720 assert!(o_prot.write_message_begin(&sent_ident).is_ok());
721
722 copy_write_buffer_to_read_buffer!(o_prot);
723
724 let received_ident = assert_success!(i_prot.read_message_begin());
725 assert_eq!(&received_ident, &sent_ident);
726 }
727
728 #[test]
729 fn must_round_trip_non_strict_message_begin() {
730 let (mut i_prot, mut o_prot) = test_objects(false);
Allen George8b96bfb2016-11-02 08:01:08 -0400731
732 let sent_ident = TMessageIdentifier::new("test", TMessageType::Call, 1);
733 assert!(o_prot.write_message_begin(&sent_ident).is_ok());
734
Allen George0e22c362017-01-30 07:15:00 -0500735 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400736
737 let received_ident = assert_success!(i_prot.read_message_begin());
738 assert_eq!(&received_ident, &sent_ident);
739 }
740
741 #[test]
742 fn must_write_message_end() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500743 assert_no_write(|o| o.write_message_end(), true);
Allen George8b96bfb2016-11-02 08:01:08 -0400744 }
745
746 #[test]
747 fn must_write_struct_begin() {
Allen Georgeef7a1892018-12-16 18:01:37 -0500748 assert_no_write(
749 |o| o.write_struct_begin(&TStructIdentifier::new("foo")),
750 true,
751 );
Allen George8b96bfb2016-11-02 08:01:08 -0400752 }
753
754 #[test]
755 fn must_write_struct_end() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500756 assert_no_write(|o| o.write_struct_end(), true);
Allen George8b96bfb2016-11-02 08:01:08 -0400757 }
758
759 #[test]
760 fn must_write_field_begin() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500761 let (_, mut o_prot) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -0400762
Allen Georgeef7a1892018-12-16 18:01:37 -0500763 assert!(o_prot
764 .write_field_begin(&TFieldIdentifier::new("some_field", TType::String, 22))
765 .is_ok());
Allen George8b96bfb2016-11-02 08:01:08 -0400766
767 let expected: [u8; 3] = [0x0B, 0x00, 0x16];
Allen George0e22c362017-01-30 07:15:00 -0500768 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400769 }
770
771 #[test]
772 fn must_round_trip_field_begin() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500773 let (mut i_prot, mut o_prot) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -0400774
775 let sent_field_ident = TFieldIdentifier::new("foo", TType::I64, 20);
776 assert!(o_prot.write_field_begin(&sent_field_ident).is_ok());
777
Allen George0e22c362017-01-30 07:15:00 -0500778 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400779
780 let expected_ident = TFieldIdentifier {
781 name: None,
782 field_type: TType::I64,
783 id: Some(20),
784 }; // no name
785 let received_ident = assert_success!(i_prot.read_field_begin());
786 assert_eq!(&received_ident, &expected_ident);
787 }
788
789 #[test]
790 fn must_write_stop_field() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500791 let (_, mut o_prot) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -0400792
793 assert!(o_prot.write_field_stop().is_ok());
794
795 let expected: [u8; 1] = [0x00];
Allen George0e22c362017-01-30 07:15:00 -0500796 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400797 }
798
799 #[test]
800 fn must_round_trip_field_stop() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500801 let (mut i_prot, mut o_prot) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -0400802
803 assert!(o_prot.write_field_stop().is_ok());
804
Allen George0e22c362017-01-30 07:15:00 -0500805 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400806
807 let expected_ident = TFieldIdentifier {
808 name: None,
809 field_type: TType::Stop,
810 id: Some(0),
811 }; // we get id 0
812
813 let received_ident = assert_success!(i_prot.read_field_begin());
814 assert_eq!(&received_ident, &expected_ident);
815 }
816
817 #[test]
818 fn must_write_field_end() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500819 assert_no_write(|o| o.write_field_end(), true);
Allen George8b96bfb2016-11-02 08:01:08 -0400820 }
821
822 #[test]
823 fn must_write_list_begin() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500824 let (_, mut o_prot) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -0400825
Allen Georgeef7a1892018-12-16 18:01:37 -0500826 assert!(o_prot
827 .write_list_begin(&TListIdentifier::new(TType::Bool, 5))
828 .is_ok());
Allen George8b96bfb2016-11-02 08:01:08 -0400829
830 let expected: [u8; 5] = [0x02, 0x00, 0x00, 0x00, 0x05];
Allen George0e22c362017-01-30 07:15:00 -0500831 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400832 }
833
834 #[test]
835 fn must_round_trip_list_begin() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500836 let (mut i_prot, mut o_prot) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -0400837
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700838 let ident = TListIdentifier::new(TType::I32, 4);
Allen George8b96bfb2016-11-02 08:01:08 -0400839 assert!(o_prot.write_list_begin(&ident).is_ok());
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700840 assert!(o_prot.write_i32(10).is_ok());
841 assert!(o_prot.write_i32(20).is_ok());
842 assert!(o_prot.write_i32(30).is_ok());
843 assert!(o_prot.write_i32(40).is_ok());
844
845 assert!(o_prot.write_list_end().is_ok());
Allen George8b96bfb2016-11-02 08:01:08 -0400846
Allen George0e22c362017-01-30 07:15:00 -0500847 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400848
849 let received_ident = assert_success!(i_prot.read_list_begin());
850 assert_eq!(&received_ident, &ident);
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700851
852 assert_eq!(i_prot.read_i32().unwrap(), 10);
853 assert_eq!(i_prot.read_i32().unwrap(), 20);
854 assert_eq!(i_prot.read_i32().unwrap(), 30);
855 assert_eq!(i_prot.read_i32().unwrap(), 40);
856
857 assert!(i_prot.read_list_end().is_ok());
Allen George8b96bfb2016-11-02 08:01:08 -0400858 }
859
860 #[test]
861 fn must_write_list_end() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500862 assert_no_write(|o| o.write_list_end(), true);
Allen George8b96bfb2016-11-02 08:01:08 -0400863 }
864
865 #[test]
866 fn must_write_set_begin() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500867 let (_, mut o_prot) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -0400868
Allen Georgeef7a1892018-12-16 18:01:37 -0500869 assert!(o_prot
870 .write_set_begin(&TSetIdentifier::new(TType::I16, 7))
871 .is_ok());
Allen George8b96bfb2016-11-02 08:01:08 -0400872
873 let expected: [u8; 5] = [0x06, 0x00, 0x00, 0x00, 0x07];
Allen George0e22c362017-01-30 07:15:00 -0500874 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400875 }
876
877 #[test]
878 fn must_round_trip_set_begin() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500879 let (mut i_prot, mut o_prot) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -0400880
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700881 let ident = TSetIdentifier::new(TType::I64, 3);
Allen George8b96bfb2016-11-02 08:01:08 -0400882 assert!(o_prot.write_set_begin(&ident).is_ok());
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700883 assert!(o_prot.write_i64(123).is_ok());
884 assert!(o_prot.write_i64(456).is_ok());
885 assert!(o_prot.write_i64(789).is_ok());
886
887 assert!(o_prot.write_set_end().is_ok());
Allen George8b96bfb2016-11-02 08:01:08 -0400888
Allen George0e22c362017-01-30 07:15:00 -0500889 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400890
891 let received_ident_result = i_prot.read_set_begin();
892 assert!(received_ident_result.is_ok());
893 assert_eq!(&received_ident_result.unwrap(), &ident);
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700894
895 assert_eq!(i_prot.read_i64().unwrap(), 123);
896 assert_eq!(i_prot.read_i64().unwrap(), 456);
897 assert_eq!(i_prot.read_i64().unwrap(), 789);
898
899 assert!(i_prot.read_set_end().is_ok());
Allen George8b96bfb2016-11-02 08:01:08 -0400900 }
901
902 #[test]
903 fn must_write_set_end() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500904 assert_no_write(|o| o.write_set_end(), true);
Allen George8b96bfb2016-11-02 08:01:08 -0400905 }
906
907 #[test]
908 fn must_write_map_begin() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500909 let (_, mut o_prot) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -0400910
Allen Georgeef7a1892018-12-16 18:01:37 -0500911 assert!(o_prot
912 .write_map_begin(&TMapIdentifier::new(TType::I64, TType::Struct, 32))
913 .is_ok());
Allen George8b96bfb2016-11-02 08:01:08 -0400914
915 let expected: [u8; 6] = [0x0A, 0x0C, 0x00, 0x00, 0x00, 0x20];
Allen George0e22c362017-01-30 07:15:00 -0500916 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400917 }
918
919 #[test]
920 fn must_round_trip_map_begin() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500921 let (mut i_prot, mut o_prot) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -0400922
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700923 let ident = TMapIdentifier::new(TType::String, TType::I32, 2);
Allen George8b96bfb2016-11-02 08:01:08 -0400924 assert!(o_prot.write_map_begin(&ident).is_ok());
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700925 assert!(o_prot.write_string("key1").is_ok());
926 assert!(o_prot.write_i32(100).is_ok());
927 assert!(o_prot.write_string("key2").is_ok());
928 assert!(o_prot.write_i32(200).is_ok());
929
930 assert!(o_prot.write_map_end().is_ok());
Allen George8b96bfb2016-11-02 08:01:08 -0400931
Allen George0e22c362017-01-30 07:15:00 -0500932 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -0400933
934 let received_ident = assert_success!(i_prot.read_map_begin());
935 assert_eq!(&received_ident, &ident);
Hasnain Lakhani42d0b712025-07-17 19:57:05 -0700936
937 assert_eq!(i_prot.read_string().unwrap(), "key1");
938 assert_eq!(i_prot.read_i32().unwrap(), 100);
939 assert_eq!(i_prot.read_string().unwrap(), "key2");
940 assert_eq!(i_prot.read_i32().unwrap(), 200);
941
942 assert!(i_prot.read_map_end().is_ok());
Allen George8b96bfb2016-11-02 08:01:08 -0400943 }
944
945 #[test]
946 fn must_write_map_end() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500947 assert_no_write(|o| o.write_map_end(), true);
Allen George8b96bfb2016-11-02 08:01:08 -0400948 }
949
950 #[test]
951 fn must_write_bool_true() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500952 let (_, mut o_prot) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -0400953
954 assert!(o_prot.write_bool(true).is_ok());
955
956 let expected: [u8; 1] = [0x01];
Allen George0e22c362017-01-30 07:15:00 -0500957 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400958 }
959
960 #[test]
961 fn must_write_bool_false() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500962 let (_, mut o_prot) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -0400963
964 assert!(o_prot.write_bool(false).is_ok());
965
966 let expected: [u8; 1] = [0x00];
Allen George0e22c362017-01-30 07:15:00 -0500967 assert_eq_written_bytes!(o_prot, expected);
Allen George8b96bfb2016-11-02 08:01:08 -0400968 }
969
970 #[test]
971 fn must_read_bool_true() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500972 let (mut i_prot, _) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -0400973
Allen George0e22c362017-01-30 07:15:00 -0500974 set_readable_bytes!(i_prot, &[0x01]);
Allen George8b96bfb2016-11-02 08:01:08 -0400975
976 let read_bool = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +0800977 assert!(read_bool);
Allen George8b96bfb2016-11-02 08:01:08 -0400978 }
979
980 #[test]
981 fn must_read_bool_false() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500982 let (mut i_prot, _) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -0400983
Allen George0e22c362017-01-30 07:15:00 -0500984 set_readable_bytes!(i_prot, &[0x00]);
Allen George8b96bfb2016-11-02 08:01:08 -0400985
986 let read_bool = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +0800987 assert!(!read_bool);
Allen George8b96bfb2016-11-02 08:01:08 -0400988 }
989
990 #[test]
991 fn must_allow_any_non_zero_value_to_be_interpreted_as_bool_true() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -0500992 let (mut i_prot, _) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -0400993
Allen George0e22c362017-01-30 07:15:00 -0500994 set_readable_bytes!(i_prot, &[0xAC]);
Allen George8b96bfb2016-11-02 08:01:08 -0400995
996 let read_bool = assert_success!(i_prot.read_bool());
Jiayu Liufbfa52c2023-11-07 13:47:24 +0800997 assert!(read_bool);
Allen George8b96bfb2016-11-02 08:01:08 -0400998 }
999
1000 #[test]
1001 fn must_write_bytes() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -05001002 let (_, mut o_prot) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -04001003
1004 let bytes: [u8; 10] = [0x0A, 0xCC, 0xD1, 0x84, 0x99, 0x12, 0xAB, 0xBB, 0x45, 0xDF];
1005
1006 assert!(o_prot.write_bytes(&bytes).is_ok());
1007
Allen George0e22c362017-01-30 07:15:00 -05001008 let buf = o_prot.transport.write_bytes();
Allen George8b96bfb2016-11-02 08:01:08 -04001009 assert_eq!(&buf[0..4], [0x00, 0x00, 0x00, 0x0A]); // length
1010 assert_eq!(&buf[4..], bytes); // actual bytes
1011 }
1012
1013 #[test]
Jiayu Liub6b6dc72022-10-08 14:28:44 +08001014 fn must_write_uuid() {
1015 let (_, mut o_prot) = test_objects(true);
1016 let uuid = uuid::Uuid::new_v4();
1017 assert!(o_prot.write_uuid(&uuid).is_ok());
1018 let buf = o_prot.transport.write_bytes();
1019 assert_eq!(&buf, uuid.as_bytes());
1020 }
1021
1022 #[test]
1023 fn must_round_trip_uuid() {
1024 let (mut i_prot, mut o_prot) = test_objects(true);
1025 let uuid = uuid::uuid!("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4");
1026 assert!(o_prot.write_uuid(&uuid).is_ok());
1027 copy_write_buffer_to_read_buffer!(o_prot);
1028 let received_uuid = assert_success!(i_prot.read_uuid());
1029 assert_eq!(&received_uuid, &uuid);
1030 }
1031
1032 #[test]
Allen George8b96bfb2016-11-02 08:01:08 -04001033 fn must_round_trip_bytes() {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -05001034 let (mut i_prot, mut o_prot) = test_objects(true);
Allen George8b96bfb2016-11-02 08:01:08 -04001035
Allen George7ddbcc02020-11-08 09:51:19 -05001036 #[rustfmt::skip]
Allen George0e22c362017-01-30 07:15:00 -05001037 let bytes: [u8; 25] = [
1038 0x20,
1039 0xFD,
1040 0x18,
1041 0x84,
1042 0x99,
1043 0x12,
1044 0xAB,
1045 0xBB,
1046 0x45,
1047 0xDF,
1048 0x34,
1049 0xDC,
1050 0x98,
1051 0xA4,
1052 0x6D,
1053 0xF3,
1054 0x99,
1055 0xB4,
1056 0xB7,
1057 0xD4,
1058 0x9C,
1059 0xA5,
1060 0xB3,
1061 0xC9,
1062 0x88,
1063 ];
Allen George8b96bfb2016-11-02 08:01:08 -04001064
1065 assert!(o_prot.write_bytes(&bytes).is_ok());
1066
Allen George0e22c362017-01-30 07:15:00 -05001067 copy_write_buffer_to_read_buffer!(o_prot);
Allen George8b96bfb2016-11-02 08:01:08 -04001068
1069 let received_bytes = assert_success!(i_prot.read_bytes());
1070 assert_eq!(&received_bytes, &bytes);
1071 }
1072
Allen Georgeef7a1892018-12-16 18:01:37 -05001073 fn test_objects(
1074 strict: bool,
1075 ) -> (
1076 TBinaryInputProtocol<ReadHalf<TBufferChannel>>,
1077 TBinaryOutputProtocol<WriteHalf<TBufferChannel>>,
1078 ) {
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07001079 let mem = TBufferChannel::with_capacity(200, 200);
Chao Sunc063b302017-03-12 12:21:05 -07001080
Allen George0e22c362017-01-30 07:15:00 -05001081 let (r_mem, w_mem) = mem.split().unwrap();
Allen George8b96bfb2016-11-02 08:01:08 -04001082
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -05001083 let i_prot = TBinaryInputProtocol::new(r_mem, strict);
1084 let o_prot = TBinaryOutputProtocol::new(w_mem, strict);
Allen George8b96bfb2016-11-02 08:01:08 -04001085
Allen George0e22c362017-01-30 07:15:00 -05001086 (i_prot, o_prot)
Allen George8b96bfb2016-11-02 08:01:08 -04001087 }
1088
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -05001089 fn assert_no_write<F>(mut write_fn: F, strict: bool)
Allen George0e22c362017-01-30 07:15:00 -05001090 where
Allen Georgeb0d14132020-03-29 11:48:55 -04001091 F: FnMut(&mut TBinaryOutputProtocol<WriteHalf<TBufferChannel>>) -> crate::Result<()>,
Allen George0e22c362017-01-30 07:15:00 -05001092 {
GREATEST Wiggler EvaR!718a63c2018-11-04 20:28:57 -05001093 let (_, mut o_prot) = test_objects(strict);
Allen George8b96bfb2016-11-02 08:01:08 -04001094 assert!(write_fn(&mut o_prot).is_ok());
Allen George0e22c362017-01-30 07:15:00 -05001095 assert_eq!(o_prot.transport.write_bytes().len(), 0);
Allen George8b96bfb2016-11-02 08:01:08 -04001096 }
Hasnain Lakhani42d0b712025-07-17 19:57:05 -07001097
1098 #[test]
1099 fn must_enforce_recursion_depth_limit() {
1100 let mem = TBufferChannel::with_capacity(40, 40);
1101 let (r_mem, _) = mem.split().unwrap();
1102
1103 let config = TConfiguration::builder()
1104 .max_recursion_depth(Some(2))
1105 .build()
1106 .unwrap();
1107 let mut i_prot = TBinaryInputProtocol::with_config(r_mem, true, config);
1108
1109 assert!(i_prot.read_struct_begin().is_ok());
1110 assert_eq!(i_prot.recursion_depth, 1);
1111
1112 assert!(i_prot.read_struct_begin().is_ok());
1113 assert_eq!(i_prot.recursion_depth, 2);
1114
1115 let result = i_prot.read_struct_begin();
1116 assert!(result.is_err());
1117 match result {
1118 Err(crate::Error::Protocol(e)) => {
1119 assert_eq!(e.kind, ProtocolErrorKind::DepthLimit);
1120 }
1121 _ => panic!("Expected protocol error with DepthLimit"),
1122 }
1123
1124 assert!(i_prot.read_struct_end().is_ok());
1125 assert_eq!(i_prot.recursion_depth, 1);
1126 assert!(i_prot.read_struct_end().is_ok());
1127 assert_eq!(i_prot.recursion_depth, 0);
1128 }
1129
1130 #[test]
1131 fn must_reject_negative_container_sizes() {
1132 let mem = TBufferChannel::with_capacity(40, 40);
1133 let (r_mem, mut w_mem) = mem.split().unwrap();
1134
1135 let mut i_prot = TBinaryInputProtocol::new(r_mem, true);
1136
1137 w_mem.set_readable_bytes(&[0x0F, 0xFF, 0xFF, 0xFF, 0xFF]);
1138
1139 let result = i_prot.read_list_begin();
1140 assert!(result.is_err());
1141 match result {
1142 Err(crate::Error::Protocol(e)) => {
1143 assert_eq!(e.kind, ProtocolErrorKind::NegativeSize);
1144 }
1145 _ => panic!("Expected protocol error with NegativeSize"),
1146 }
1147 }
1148
1149 #[test]
1150 fn must_enforce_container_size_limit() {
1151 let mem = TBufferChannel::with_capacity(40, 40);
1152 let (r_mem, mut w_mem) = mem.split().unwrap();
1153
1154 let config = TConfiguration::builder()
1155 .max_container_size(Some(100))
1156 .build()
1157 .unwrap();
1158
1159 let mut i_prot = TBinaryInputProtocol::with_config(r_mem, true, config);
1160
1161 w_mem.set_readable_bytes(&[0x0F, 0x00, 0x00, 0x00, 0xC8]);
1162
1163 let result = i_prot.read_list_begin();
1164 assert!(result.is_err());
1165 match result {
1166 Err(crate::Error::Protocol(e)) => {
1167 assert_eq!(e.kind, ProtocolErrorKind::SizeLimit);
1168 assert!(e
1169 .message
1170 .contains("Container size 200 exceeds maximum allowed size of 100"));
1171 }
1172 _ => panic!("Expected protocol error with SizeLimit"),
1173 }
1174 }
1175
1176 #[test]
1177 fn must_allow_containers_within_limit() {
1178 let mem = TBufferChannel::with_capacity(200, 200);
1179 let (r_mem, mut w_mem) = mem.split().unwrap();
1180
1181 // Create protocol with container limit of 100
1182 let config = TConfiguration::builder()
1183 .max_container_size(Some(100))
1184 .build()
1185 .unwrap();
1186 let mut i_prot = TBinaryInputProtocol::with_config(r_mem, true, config);
1187
1188 let mut data = vec![0x08]; // TType::I32
1189 data.extend_from_slice(&5i32.to_be_bytes()); // size = 5
1190
1191 for i in 1i32..=5i32 {
1192 data.extend_from_slice(&(i * 10).to_be_bytes());
1193 }
1194
1195 w_mem.set_readable_bytes(&data);
1196
1197 let result = i_prot.read_list_begin();
1198 assert!(result.is_ok());
1199 let list_ident = result.unwrap();
1200 assert_eq!(list_ident.size, 5);
1201 assert_eq!(list_ident.element_type, TType::I32);
1202 }
1203
1204 #[test]
1205 fn must_enforce_string_size_limit() {
1206 let mem = TBufferChannel::with_capacity(100, 100);
1207 let (r_mem, mut w_mem) = mem.split().unwrap();
1208
1209 let config = TConfiguration::builder()
1210 .max_string_size(Some(1000))
1211 .build()
1212 .unwrap();
1213 let mut i_prot = TBinaryInputProtocol::with_config(r_mem, true, config);
1214
1215 w_mem.set_readable_bytes(&[0x00, 0x00, 0x07, 0xD0]);
1216
1217 let result = i_prot.read_string();
1218 assert!(result.is_err());
1219 match result {
1220 Err(crate::Error::Protocol(e)) => {
1221 assert_eq!(e.kind, ProtocolErrorKind::SizeLimit);
1222 assert!(e
1223 .message
1224 .contains("Byte array size 2000 exceeds maximum allowed size of 1000"));
1225 }
1226 _ => panic!("Expected protocol error with SizeLimit"),
1227 }
1228 }
1229
1230 #[test]
1231 fn must_allow_strings_within_limit() {
1232 let mem = TBufferChannel::with_capacity(100, 100);
1233 let (r_mem, mut w_mem) = mem.split().unwrap();
1234
1235 let config = TConfiguration::builder()
1236 .max_string_size(Some(1000))
1237 .build()
1238 .unwrap();
1239 let mut i_prot = TBinaryInputProtocol::with_config(r_mem, true, config);
1240
1241 w_mem.set_readable_bytes(&[0x00, 0x00, 0x00, 0x05, b'h', b'e', b'l', b'l', b'o']);
1242
1243 let result = i_prot.read_string();
1244 assert!(result.is_ok());
1245 assert_eq!(result.unwrap(), "hello");
1246 }
Allen George8b96bfb2016-11-02 08:01:08 -04001247}