Coverage Report

Created: 2026-05-30 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/thrift/lib/rs/src/protocol/mod.rs
Line
Count
Source
1
// 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
18
//! Types used to send and receive primitives between a Thrift client and server.
19
//!
20
//! # Examples
21
//!
22
//! Create and use a `TInputProtocol`.
23
//!
24
//! ```no_run
25
//! use thrift::protocol::{TBinaryInputProtocol, TInputProtocol};
26
//! use thrift::transport::TTcpChannel;
27
//!
28
//! // create the I/O channel
29
//! let mut channel = TTcpChannel::new();
30
//! channel.open("127.0.0.1:9090").unwrap();
31
//!
32
//! // create the protocol to decode bytes into types
33
//! let mut protocol = TBinaryInputProtocol::new(channel, true);
34
//!
35
//! // read types from the wire
36
//! let field_identifier = protocol.read_field_begin().unwrap();
37
//! let field_contents = protocol.read_string().unwrap();
38
//! let field_end = protocol.read_field_end().unwrap();
39
//! ```
40
//!
41
//! Create and use a `TOutputProtocol`.
42
//!
43
//! ```no_run
44
//! use thrift::protocol::{TBinaryOutputProtocol, TFieldIdentifier, TOutputProtocol, TType};
45
//! use thrift::transport::TTcpChannel;
46
//!
47
//! // create the I/O channel
48
//! let mut channel = TTcpChannel::new();
49
//! channel.open("127.0.0.1:9090").unwrap();
50
//!
51
//! // create the protocol to encode types into bytes
52
//! let mut protocol = TBinaryOutputProtocol::new(channel, true);
53
//!
54
//! // write types
55
//! protocol.write_field_begin(&TFieldIdentifier::new("string_thing", TType::String, 1)).unwrap();
56
//! protocol.write_string("foo").unwrap();
57
//! protocol.write_field_end().unwrap();
58
//! ```
59
60
use std::convert::{From, TryFrom};
61
use std::fmt;
62
use std::fmt::{Display, Formatter};
63
64
use crate::transport::{TReadTransport, TWriteTransport};
65
use crate::{ProtocolError, ProtocolErrorKind, TConfiguration};
66
67
#[cfg(test)]
68
macro_rules! assert_eq_written_bytes {
69
    ($o_prot:ident, $expected_bytes:ident) => {{
70
        assert_eq!($o_prot.transport.write_bytes(), &$expected_bytes);
71
    }};
72
}
73
74
// FIXME: should take both read and write
75
#[cfg(test)]
76
macro_rules! copy_write_buffer_to_read_buffer {
77
    ($o_prot:ident) => {{
78
        $o_prot.transport.copy_write_buffer_to_read_buffer();
79
    }};
80
}
81
82
#[cfg(test)]
83
macro_rules! set_readable_bytes {
84
    ($i_prot:ident, $bytes:expr) => {
85
        $i_prot.transport.set_readable_bytes($bytes);
86
    };
87
}
88
89
mod binary;
90
mod compact;
91
mod multiplexed;
92
mod stored;
93
94
pub use self::binary::{
95
    TBinaryInputProtocol, TBinaryInputProtocolFactory, TBinaryOutputProtocol,
96
    TBinaryOutputProtocolFactory,
97
};
98
pub use self::compact::{
99
    TCompactInputProtocol, TCompactInputProtocolFactory, TCompactOutputProtocol,
100
    TCompactOutputProtocolFactory,
101
};
102
pub use self::multiplexed::TMultiplexedOutputProtocol;
103
pub use self::stored::TStoredInputProtocol;
104
105
/// Reads and writes the struct to Thrift protocols.
106
///
107
/// It is implemented in generated code for Thrift `struct`, `union`, and `enum` types.
108
pub trait TSerializable: Sized {
109
    fn read_from_in_protocol(i_prot: &mut dyn TInputProtocol) -> crate::Result<Self>;
110
    fn write_to_out_protocol(&self, o_prot: &mut dyn TOutputProtocol) -> crate::Result<()>;
111
}
112
113
// Default maximum depth to which `TInputProtocol::skip` will skip a Thrift
114
// field. A default is necessary because Thrift structs or collections may
115
// contain nested structs and collections, which could result in indefinite
116
// recursion.
117
const MAXIMUM_SKIP_DEPTH: i8 = 64;
118
119
/// Converts a stream of bytes into Thrift identifiers, primitives,
120
/// containers, or structs.
121
///
122
/// This trait does not deal with higher-level Thrift concepts like structs or
123
/// exceptions - only with primitives and message or container boundaries. Once
124
/// bytes are read they are deserialized and an identifier (for example
125
/// `TMessageIdentifier`) or a primitive is returned.
126
///
127
/// All methods return a `thrift::Result`. If an `Err` is returned the protocol
128
/// instance and its underlying transport should be terminated.
129
///
130
/// # Examples
131
///
132
/// Create and use a `TInputProtocol`
133
///
134
/// ```no_run
135
/// use thrift::protocol::{TBinaryInputProtocol, TInputProtocol};
136
/// use thrift::transport::TTcpChannel;
137
///
138
/// let mut channel = TTcpChannel::new();
139
/// channel.open("127.0.0.1:9090").unwrap();
140
///
141
/// let mut protocol = TBinaryInputProtocol::new(channel, true);
142
///
143
/// let field_identifier = protocol.read_field_begin().unwrap();
144
/// let field_contents = protocol.read_string().unwrap();
145
/// let field_end = protocol.read_field_end().unwrap();
146
/// ```
147
pub trait TInputProtocol {
148
    /// Read the beginning of a Thrift message.
149
    fn read_message_begin(&mut self) -> crate::Result<TMessageIdentifier>;
150
    /// Read the end of a Thrift message.
151
    fn read_message_end(&mut self) -> crate::Result<()>;
152
    /// Read the beginning of a Thrift struct.
153
    fn read_struct_begin(&mut self) -> crate::Result<Option<TStructIdentifier>>;
154
    /// Read the end of a Thrift struct.
155
    fn read_struct_end(&mut self) -> crate::Result<()>;
156
    /// Read the beginning of a Thrift struct field.
157
    fn read_field_begin(&mut self) -> crate::Result<TFieldIdentifier>;
158
    /// Read the end of a Thrift struct field.
159
    fn read_field_end(&mut self) -> crate::Result<()>;
160
    /// Read a bool.
161
    fn read_bool(&mut self) -> crate::Result<bool>;
162
    /// Read a fixed-length byte array.
163
    fn read_bytes(&mut self) -> crate::Result<Vec<u8>>;
164
    /// Read a word.
165
    fn read_i8(&mut self) -> crate::Result<i8>;
166
    /// Read a 16-bit signed integer.
167
    fn read_i16(&mut self) -> crate::Result<i16>;
168
    /// Read a 32-bit signed integer.
169
    fn read_i32(&mut self) -> crate::Result<i32>;
170
    /// Read a 64-bit signed integer.
171
    fn read_i64(&mut self) -> crate::Result<i64>;
172
    /// Read a 64-bit float.
173
    fn read_double(&mut self) -> crate::Result<f64>;
174
    /// Read a UUID.
175
    fn read_uuid(&mut self) -> crate::Result<uuid::Uuid>;
176
    /// Read a fixed-length string (not null terminated).
177
    fn read_string(&mut self) -> crate::Result<String>;
178
    /// Read the beginning of a list.
179
    fn read_list_begin(&mut self) -> crate::Result<TListIdentifier>;
180
    /// Read the end of a list.
181
    fn read_list_end(&mut self) -> crate::Result<()>;
182
    /// Read the beginning of a set.
183
    fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier>;
184
    /// Read the end of a set.
185
    fn read_set_end(&mut self) -> crate::Result<()>;
186
    /// Read the beginning of a map.
187
    fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier>;
188
    /// Read the end of a map.
189
    fn read_map_end(&mut self) -> crate::Result<()>;
190
    /// Skip a field with type `field_type` recursively until the default
191
    /// maximum skip depth is reached.
192
1.02M
    fn skip(&mut self, field_type: TType) -> crate::Result<()> {
193
1.02M
        self.skip_till_depth(field_type, MAXIMUM_SKIP_DEPTH)
194
1.02M
    }
<thrift::protocol::binary::TBinaryInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::skip
Line
Count
Source
192
107k
    fn skip(&mut self, field_type: TType) -> crate::Result<()> {
193
107k
        self.skip_till_depth(field_type, MAXIMUM_SKIP_DEPTH)
194
107k
    }
Unexecuted instantiation: <thrift::protocol::binary::TBinaryInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::skip
Unexecuted instantiation: <thrift::protocol::stored::TStoredInputProtocol as thrift::protocol::TInputProtocol>::skip
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::skip
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::skip
Line
Count
Source
192
370k
    fn skip(&mut self, field_type: TType) -> crate::Result<()> {
193
370k
        self.skip_till_depth(field_type, MAXIMUM_SKIP_DEPTH)
194
370k
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::skip
Line
Count
Source
192
469k
    fn skip(&mut self, field_type: TType) -> crate::Result<()> {
193
469k
        self.skip_till_depth(field_type, MAXIMUM_SKIP_DEPTH)
194
469k
    }
<thrift::protocol::binary::TBinaryInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::skip
Line
Count
Source
192
78.2k
    fn skip(&mut self, field_type: TType) -> crate::Result<()> {
193
78.2k
        self.skip_till_depth(field_type, MAXIMUM_SKIP_DEPTH)
194
78.2k
    }
195
    /// Skip a field with type `field_type` recursively up to `depth` levels.
196
1.82M
    fn skip_till_depth(&mut self, field_type: TType, depth: i8) -> crate::Result<()> {
197
1.82M
        if depth == 0 {
198
4
            return Err(crate::Error::Protocol(ProtocolError {
199
4
                kind: ProtocolErrorKind::DepthLimit,
200
4
                message: format!("cannot parse past {:?}", field_type),
201
4
            }));
202
1.82M
        }
203
204
1.82M
        match field_type {
205
402k
            TType::Bool => self.read_bool().map(|_| ()),
206
213k
            TType::I08 => self.read_i8().map(|_| ()),
207
54.3k
            TType::I16 => self.read_i16().map(|_| ()),
208
81.8k
            TType::I32 => self.read_i32().map(|_| ()),
209
81.7k
            TType::I64 => self.read_i64().map(|_| ()),
210
16.7k
            TType::Double => self.read_double().map(|_| ()),
211
28.1k
            TType::String => self.read_bytes().map(|_| ()),
212
276k
            TType::Uuid => self.read_uuid().map(|_| ()),
213
            TType::Struct => {
214
34.8k
                self.read_struct_begin()?;
215
                loop {
216
679k
                    let field_ident = self.read_field_begin()?;
217
679k
                    if field_ident.field_type == TType::Stop {
218
32.7k
                        break;
219
646k
                    }
220
646k
                    self.skip_till_depth(field_ident.field_type, depth - 1)?;
221
                }
222
32.7k
                self.read_struct_end()
223
            }
224
            TType::List => {
225
603k
                let list_ident = self.read_list_begin()?;
226
603k
                for _ in 0..list_ident.size {
227
107k
                    self.skip_till_depth(list_ident.element_type, depth - 1)?;
228
                }
229
601k
                self.read_list_end()
230
            }
231
            TType::Set => {
232
23.7k
                let set_ident = self.read_set_begin()?;
233
23.4k
                for _ in 0..set_ident.size {
234
25.8k
                    self.skip_till_depth(set_ident.element_type, depth - 1)?;
235
                }
236
22.0k
                self.read_set_end()
237
            }
238
            TType::Map => {
239
6.48k
                let map_ident = self.read_map_begin()?;
240
6.17k
                for _ in 0..map_ident.size {
241
9.00k
                    let key_type = map_ident
242
9.00k
                        .key_type
243
9.00k
                        .expect("non-zero sized map should contain key type");
244
9.00k
                    let val_type = map_ident
245
9.00k
                        .value_type
246
9.00k
                        .expect("non-zero sized map should contain value type");
247
9.00k
                    self.skip_till_depth(key_type, depth - 1)?;
248
8.20k
                    self.skip_till_depth(val_type, depth - 1)?;
249
                }
250
5.00k
                self.read_map_end()
251
            }
252
181
            u => Err(crate::Error::Protocol(ProtocolError {
253
181
                kind: ProtocolErrorKind::Unknown,
254
181
                message: format!("cannot skip field type {:?}", &u),
255
181
            })),
256
        }
257
1.82M
    }
<thrift::protocol::binary::TBinaryInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::skip_till_depth
Line
Count
Source
196
226k
    fn skip_till_depth(&mut self, field_type: TType, depth: i8) -> crate::Result<()> {
197
226k
        if depth == 0 {
198
1
            return Err(crate::Error::Protocol(ProtocolError {
199
1
                kind: ProtocolErrorKind::DepthLimit,
200
1
                message: format!("cannot parse past {:?}", field_type),
201
1
            }));
202
226k
        }
203
204
226k
        match field_type {
205
78.9k
            TType::Bool => self.read_bool().map(|_| ()),
206
120k
            TType::I08 => self.read_i8().map(|_| ()),
207
593
            TType::I16 => self.read_i16().map(|_| ()),
208
3.27k
            TType::I32 => self.read_i32().map(|_| ()),
209
2.24k
            TType::I64 => self.read_i64().map(|_| ()),
210
3.35k
            TType::Double => self.read_double().map(|_| ()),
211
2.63k
            TType::String => self.read_bytes().map(|_| ()),
212
1.14k
            TType::Uuid => self.read_uuid().map(|_| ()),
213
            TType::Struct => {
214
7.29k
                self.read_struct_begin()?;
215
                loop {
216
114k
                    let field_ident = self.read_field_begin()?;
217
114k
                    if field_ident.field_type == TType::Stop {
218
6.79k
                        break;
219
107k
                    }
220
107k
                    self.skip_till_depth(field_ident.field_type, depth - 1)?;
221
                }
222
6.79k
                self.read_struct_end()
223
            }
224
            TType::List => {
225
2.08k
                let list_ident = self.read_list_begin()?;
226
1.99k
                for _ in 0..list_ident.size {
227
3.01k
                    self.skip_till_depth(list_ident.element_type, depth - 1)?;
228
                }
229
1.83k
                self.read_list_end()
230
            }
231
            TType::Set => {
232
2.84k
                let set_ident = self.read_set_begin()?;
233
2.73k
                for _ in 0..set_ident.size {
234
4.57k
                    self.skip_till_depth(set_ident.element_type, depth - 1)?;
235
                }
236
2.38k
                self.read_set_end()
237
            }
238
            TType::Map => {
239
1.27k
                let map_ident = self.read_map_begin()?;
240
1.22k
                for _ in 0..map_ident.size {
241
2.08k
                    let key_type = map_ident
242
2.08k
                        .key_type
243
2.08k
                        .expect("non-zero sized map should contain key type");
244
2.08k
                    let val_type = map_ident
245
2.08k
                        .value_type
246
2.08k
                        .expect("non-zero sized map should contain value type");
247
2.08k
                    self.skip_till_depth(key_type, depth - 1)?;
248
1.90k
                    self.skip_till_depth(val_type, depth - 1)?;
249
                }
250
970
                self.read_map_end()
251
            }
252
70
            u => Err(crate::Error::Protocol(ProtocolError {
253
70
                kind: ProtocolErrorKind::Unknown,
254
70
                message: format!("cannot skip field type {:?}", &u),
255
70
            })),
256
        }
257
226k
    }
Unexecuted instantiation: <thrift::protocol::binary::TBinaryInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::skip_till_depth
Unexecuted instantiation: <thrift::protocol::stored::TStoredInputProtocol as thrift::protocol::TInputProtocol>::skip_till_depth
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::skip_till_depth
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::skip_till_depth
Line
Count
Source
196
857k
    fn skip_till_depth(&mut self, field_type: TType, depth: i8) -> crate::Result<()> {
197
857k
        if depth == 0 {
198
1
            return Err(crate::Error::Protocol(ProtocolError {
199
1
                kind: ProtocolErrorKind::DepthLimit,
200
1
                message: format!("cannot parse past {:?}", field_type),
201
1
            }));
202
857k
        }
203
204
857k
        match field_type {
205
82.0k
            TType::Bool => self.read_bool().map(|_| ()),
206
15.0k
            TType::I08 => self.read_i8().map(|_| ()),
207
42.7k
            TType::I16 => self.read_i16().map(|_| ()),
208
59.3k
            TType::I32 => self.read_i32().map(|_| ()),
209
48.4k
            TType::I64 => self.read_i64().map(|_| ()),
210
4.63k
            TType::Double => self.read_double().map(|_| ()),
211
7.48k
            TType::String => self.read_bytes().map(|_| ()),
212
2.54k
            TType::Uuid => self.read_uuid().map(|_| ()),
213
            TType::Struct => {
214
7.46k
                self.read_struct_begin()?;
215
                loop {
216
413k
                    let field_ident = self.read_field_begin()?;
217
413k
                    if field_ident.field_type == TType::Stop {
218
6.97k
                        break;
219
406k
                    }
220
406k
                    self.skip_till_depth(field_ident.field_type, depth - 1)?;
221
                }
222
6.97k
                self.read_struct_end()
223
            }
224
            TType::List => {
225
582k
                let list_ident = self.read_list_begin()?;
226
582k
                for _ in 0..list_ident.size {
227
73.3k
                    self.skip_till_depth(list_ident.element_type, depth - 1)?;
228
                }
229
581k
                self.read_list_end()
230
            }
231
            TType::Set => {
232
3.20k
                let set_ident = self.read_set_begin()?;
233
3.16k
                for _ in 0..set_ident.size {
234
4.06k
                    self.skip_till_depth(set_ident.element_type, depth - 1)?;
235
                }
236
2.80k
                self.read_set_end()
237
            }
238
            TType::Map => {
239
2.62k
                let map_ident = self.read_map_begin()?;
240
2.51k
                for _ in 0..map_ident.size {
241
1.69k
                    let key_type = map_ident
242
1.69k
                        .key_type
243
1.69k
                        .expect("non-zero sized map should contain key type");
244
1.69k
                    let val_type = map_ident
245
1.69k
                        .value_type
246
1.69k
                        .expect("non-zero sized map should contain value type");
247
1.69k
                    self.skip_till_depth(key_type, depth - 1)?;
248
1.51k
                    self.skip_till_depth(val_type, depth - 1)?;
249
                }
250
2.20k
                self.read_map_end()
251
            }
252
19
            u => Err(crate::Error::Protocol(ProtocolError {
253
19
                kind: ProtocolErrorKind::Unknown,
254
19
                message: format!("cannot skip field type {:?}", &u),
255
19
            })),
256
        }
257
857k
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::skip_till_depth
Line
Count
Source
196
643k
    fn skip_till_depth(&mut self, field_type: TType, depth: i8) -> crate::Result<()> {
197
643k
        if depth == 0 {
198
1
            return Err(crate::Error::Protocol(ProtocolError {
199
1
                kind: ProtocolErrorKind::DepthLimit,
200
1
                message: format!("cannot parse past {:?}", field_type),
201
1
            }));
202
643k
        }
203
204
643k
        match field_type {
205
228k
            TType::Bool => self.read_bool().map(|_| ()),
206
29.3k
            TType::I08 => self.read_i8().map(|_| ()),
207
8.83k
            TType::I16 => self.read_i16().map(|_| ()),
208
15.6k
            TType::I32 => self.read_i32().map(|_| ()),
209
27.9k
            TType::I64 => self.read_i64().map(|_| ()),
210
4.60k
            TType::Double => self.read_double().map(|_| ()),
211
12.5k
            TType::String => self.read_bytes().map(|_| ()),
212
270k
            TType::Uuid => self.read_uuid().map(|_| ()),
213
            TType::Struct => {
214
10.8k
                self.read_struct_begin()?;
215
                loop {
216
135k
                    let field_ident = self.read_field_begin()?;
217
135k
                    if field_ident.field_type == TType::Stop {
218
10.2k
                        break;
219
124k
                    }
220
124k
                    self.skip_till_depth(field_ident.field_type, depth - 1)?;
221
                }
222
10.2k
                self.read_struct_end()
223
            }
224
            TType::List => {
225
17.9k
                let list_ident = self.read_list_begin()?;
226
17.8k
                for _ in 0..list_ident.size {
227
28.2k
                    self.skip_till_depth(list_ident.element_type, depth - 1)?;
228
                }
229
17.4k
                self.read_list_end()
230
            }
231
            TType::Set => {
232
16.6k
                let set_ident = self.read_set_begin()?;
233
16.5k
                for _ in 0..set_ident.size {
234
13.7k
                    self.skip_till_depth(set_ident.element_type, depth - 1)?;
235
                }
236
15.9k
                self.read_set_end()
237
            }
238
            TType::Map => {
239
1.16k
                let map_ident = self.read_map_begin()?;
240
1.06k
                for _ in 0..map_ident.size {
241
3.74k
                    let key_type = map_ident
242
3.74k
                        .key_type
243
3.74k
                        .expect("non-zero sized map should contain key type");
244
3.74k
                    let val_type = map_ident
245
3.74k
                        .value_type
246
3.74k
                        .expect("non-zero sized map should contain value type");
247
3.74k
                    self.skip_till_depth(key_type, depth - 1)?;
248
3.65k
                    self.skip_till_depth(val_type, depth - 1)?;
249
                }
250
885
                self.read_map_end()
251
            }
252
20
            u => Err(crate::Error::Protocol(ProtocolError {
253
20
                kind: ProtocolErrorKind::Unknown,
254
20
                message: format!("cannot skip field type {:?}", &u),
255
20
            })),
256
        }
257
643k
    }
<thrift::protocol::binary::TBinaryInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::skip_till_depth
Line
Count
Source
196
94.8k
    fn skip_till_depth(&mut self, field_type: TType, depth: i8) -> crate::Result<()> {
197
94.8k
        if depth == 0 {
198
1
            return Err(crate::Error::Protocol(ProtocolError {
199
1
                kind: ProtocolErrorKind::DepthLimit,
200
1
                message: format!("cannot parse past {:?}", field_type),
201
1
            }));
202
94.8k
        }
203
204
94.8k
        match field_type {
205
13.0k
            TType::Bool => self.read_bool().map(|_| ()),
206
48.1k
            TType::I08 => self.read_i8().map(|_| ()),
207
2.22k
            TType::I16 => self.read_i16().map(|_| ()),
208
3.60k
            TType::I32 => self.read_i32().map(|_| ()),
209
3.09k
            TType::I64 => self.read_i64().map(|_| ()),
210
4.13k
            TType::Double => self.read_double().map(|_| ()),
211
5.49k
            TType::String => self.read_bytes().map(|_| ()),
212
2.22k
            TType::Uuid => self.read_uuid().map(|_| ()),
213
            TType::Struct => {
214
9.18k
                self.read_struct_begin()?;
215
                loop {
216
16.6k
                    let field_ident = self.read_field_begin()?;
217
16.5k
                    if field_ident.field_type == TType::Stop {
218
8.78k
                        break;
219
7.74k
                    }
220
7.74k
                    self.skip_till_depth(field_ident.field_type, depth - 1)?;
221
                }
222
8.78k
                self.read_struct_end()
223
            }
224
            TType::List => {
225
1.13k
                let list_ident = self.read_list_begin()?;
226
1.05k
                for _ in 0..list_ident.size {
227
2.86k
                    self.skip_till_depth(list_ident.element_type, depth - 1)?;
228
                }
229
938
                self.read_list_end()
230
            }
231
            TType::Set => {
232
1.09k
                let set_ident = self.read_set_begin()?;
233
1.02k
                for _ in 0..set_ident.size {
234
3.43k
                    self.skip_till_depth(set_ident.element_type, depth - 1)?;
235
                }
236
886
                self.read_set_end()
237
            }
238
            TType::Map => {
239
1.42k
                let map_ident = self.read_map_begin()?;
240
1.37k
                for _ in 0..map_ident.size {
241
1.47k
                    let key_type = map_ident
242
1.47k
                        .key_type
243
1.47k
                        .expect("non-zero sized map should contain key type");
244
1.47k
                    let val_type = map_ident
245
1.47k
                        .value_type
246
1.47k
                        .expect("non-zero sized map should contain value type");
247
1.47k
                    self.skip_till_depth(key_type, depth - 1)?;
248
1.13k
                    self.skip_till_depth(val_type, depth - 1)?;
249
                }
250
951
                self.read_map_end()
251
            }
252
72
            u => Err(crate::Error::Protocol(ProtocolError {
253
72
                kind: ProtocolErrorKind::Unknown,
254
72
                message: format!("cannot skip field type {:?}", &u),
255
72
            })),
256
        }
257
94.8k
    }
258
259
    // utility (DO NOT USE IN GENERATED CODE!!!!)
260
    //
261
262
    /// Read an unsigned byte.
263
    ///
264
    /// This method should **never** be used in generated code.
265
    fn read_byte(&mut self) -> crate::Result<u8>;
266
267
    /// Get the minimum number of bytes a type will consume on the wire.
268
    /// This picks the minimum possible across all protocols (so currently matches the compact protocol).
269
    ///
270
    /// This is used for pre-allocation size checks.
271
    /// The actual data may be larger (e.g., for strings, lists, etc.).
272
0
    fn min_serialized_size(&self, field_type: TType) -> usize {
273
0
        self::compact::compact_protocol_min_serialized_size(field_type)
274
0
    }
275
}
276
277
/// Converts Thrift identifiers, primitives, containers or structs into a
278
/// stream of bytes.
279
///
280
/// This trait does not deal with higher-level Thrift concepts like structs or
281
/// exceptions - only with primitives and message or container boundaries.
282
/// Write methods take an identifier (for example, `TMessageIdentifier`) or a
283
/// primitive. Any or all of the fields in an identifier may be omitted when
284
/// writing to the transport. Write methods may even be noops. All of this is
285
/// transparent to the caller; as long as a matching `TInputProtocol`
286
/// implementation is used, received messages will be decoded correctly.
287
///
288
/// All methods return a `thrift::Result`. If an `Err` is returned the protocol
289
/// instance and its underlying transport should be terminated.
290
///
291
/// # Examples
292
///
293
/// Create and use a `TOutputProtocol`
294
///
295
/// ```no_run
296
/// use thrift::protocol::{TBinaryOutputProtocol, TFieldIdentifier, TOutputProtocol, TType};
297
/// use thrift::transport::TTcpChannel;
298
///
299
/// let mut channel = TTcpChannel::new();
300
/// channel.open("127.0.0.1:9090").unwrap();
301
///
302
/// let mut protocol = TBinaryOutputProtocol::new(channel, true);
303
///
304
/// protocol.write_field_begin(&TFieldIdentifier::new("string_thing", TType::String, 1)).unwrap();
305
/// protocol.write_string("foo").unwrap();
306
/// protocol.write_field_end().unwrap();
307
/// ```
308
pub trait TOutputProtocol {
309
    /// Write the beginning of a Thrift message.
310
    fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()>;
311
    /// Write the end of a Thrift message.
312
    fn write_message_end(&mut self) -> crate::Result<()>;
313
    /// Write the beginning of a Thrift struct.
314
    fn write_struct_begin(&mut self, identifier: &TStructIdentifier) -> crate::Result<()>;
315
    /// Write the end of a Thrift struct.
316
    fn write_struct_end(&mut self) -> crate::Result<()>;
317
    /// Write the beginning of a Thrift field.
318
    fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()>;
319
    /// Write the end of a Thrift field.
320
    fn write_field_end(&mut self) -> crate::Result<()>;
321
    /// Write a STOP field indicating that all the fields in a struct have been
322
    /// written.
323
    fn write_field_stop(&mut self) -> crate::Result<()>;
324
    /// Write a bool.
325
    fn write_bool(&mut self, b: bool) -> crate::Result<()>;
326
    /// Write a fixed-length byte array.
327
    fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()>;
328
    /// Write an 8-bit signed integer.
329
    fn write_i8(&mut self, i: i8) -> crate::Result<()>;
330
    /// Write a 16-bit signed integer.
331
    fn write_i16(&mut self, i: i16) -> crate::Result<()>;
332
    /// Write a 32-bit signed integer.
333
    fn write_i32(&mut self, i: i32) -> crate::Result<()>;
334
    /// Write a 64-bit signed integer.
335
    fn write_i64(&mut self, i: i64) -> crate::Result<()>;
336
    /// Write a 64-bit float.
337
    fn write_double(&mut self, d: f64) -> crate::Result<()>;
338
    /// Write a UUID
339
    fn write_uuid(&mut self, uuid: &uuid::Uuid) -> crate::Result<()>;
340
    /// Write a fixed-length string.
341
    fn write_string(&mut self, s: &str) -> crate::Result<()>;
342
    /// Write the beginning of a list.
343
    fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()>;
344
    /// Write the end of a list.
345
    fn write_list_end(&mut self) -> crate::Result<()>;
346
    /// Write the beginning of a set.
347
    fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()>;
348
    /// Write the end of a set.
349
    fn write_set_end(&mut self) -> crate::Result<()>;
350
    /// Write the beginning of a map.
351
    fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()>;
352
    /// Write the end of a map.
353
    fn write_map_end(&mut self) -> crate::Result<()>;
354
    /// Flush buffered bytes to the underlying transport.
355
    fn flush(&mut self) -> crate::Result<()>;
356
357
    // utility (DO NOT USE IN GENERATED CODE!!!!)
358
    //
359
360
    /// Write an unsigned byte.
361
    ///
362
    /// This method should **never** be used in generated code.
363
    fn write_byte(&mut self, b: u8) -> crate::Result<()>; // FIXME: REMOVE
364
}
365
366
impl<P> TInputProtocol for Box<P>
367
where
368
    P: TInputProtocol + ?Sized,
369
{
370
    fn read_message_begin(&mut self) -> crate::Result<TMessageIdentifier> {
371
        (**self).read_message_begin()
372
    }
373
374
    fn read_message_end(&mut self) -> crate::Result<()> {
375
        (**self).read_message_end()
376
    }
377
378
    fn read_struct_begin(&mut self) -> crate::Result<Option<TStructIdentifier>> {
379
        (**self).read_struct_begin()
380
    }
381
382
    fn read_struct_end(&mut self) -> crate::Result<()> {
383
        (**self).read_struct_end()
384
    }
385
386
    fn read_field_begin(&mut self) -> crate::Result<TFieldIdentifier> {
387
        (**self).read_field_begin()
388
    }
389
390
    fn read_field_end(&mut self) -> crate::Result<()> {
391
        (**self).read_field_end()
392
    }
393
394
    fn read_bool(&mut self) -> crate::Result<bool> {
395
        (**self).read_bool()
396
    }
397
398
    fn read_bytes(&mut self) -> crate::Result<Vec<u8>> {
399
        (**self).read_bytes()
400
    }
401
402
    fn read_i8(&mut self) -> crate::Result<i8> {
403
        (**self).read_i8()
404
    }
405
406
    fn read_i16(&mut self) -> crate::Result<i16> {
407
        (**self).read_i16()
408
    }
409
410
    fn read_i32(&mut self) -> crate::Result<i32> {
411
        (**self).read_i32()
412
    }
413
414
    fn read_i64(&mut self) -> crate::Result<i64> {
415
        (**self).read_i64()
416
    }
417
418
    fn read_double(&mut self) -> crate::Result<f64> {
419
        (**self).read_double()
420
    }
421
422
    fn read_uuid(&mut self) -> crate::Result<uuid::Uuid> {
423
        (**self).read_uuid()
424
    }
425
426
    fn read_string(&mut self) -> crate::Result<String> {
427
        (**self).read_string()
428
    }
429
430
    fn read_list_begin(&mut self) -> crate::Result<TListIdentifier> {
431
        (**self).read_list_begin()
432
    }
433
434
    fn read_list_end(&mut self) -> crate::Result<()> {
435
        (**self).read_list_end()
436
    }
437
438
    fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier> {
439
        (**self).read_set_begin()
440
    }
441
442
    fn read_set_end(&mut self) -> crate::Result<()> {
443
        (**self).read_set_end()
444
    }
445
446
    fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier> {
447
        (**self).read_map_begin()
448
    }
449
450
    fn read_map_end(&mut self) -> crate::Result<()> {
451
        (**self).read_map_end()
452
    }
453
454
    fn read_byte(&mut self) -> crate::Result<u8> {
455
        (**self).read_byte()
456
    }
457
458
    fn min_serialized_size(&self, field_type: TType) -> usize {
459
        (**self).min_serialized_size(field_type)
460
    }
461
}
462
463
impl<P> TOutputProtocol for Box<P>
464
where
465
    P: TOutputProtocol + ?Sized,
466
{
467
    fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> {
468
        (**self).write_message_begin(identifier)
469
    }
470
471
    fn write_message_end(&mut self) -> crate::Result<()> {
472
        (**self).write_message_end()
473
    }
474
475
    fn write_struct_begin(&mut self, identifier: &TStructIdentifier) -> crate::Result<()> {
476
        (**self).write_struct_begin(identifier)
477
    }
478
479
    fn write_struct_end(&mut self) -> crate::Result<()> {
480
        (**self).write_struct_end()
481
    }
482
483
    fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> {
484
        (**self).write_field_begin(identifier)
485
    }
486
487
    fn write_field_end(&mut self) -> crate::Result<()> {
488
        (**self).write_field_end()
489
    }
490
491
    fn write_field_stop(&mut self) -> crate::Result<()> {
492
        (**self).write_field_stop()
493
    }
494
495
    fn write_bool(&mut self, b: bool) -> crate::Result<()> {
496
        (**self).write_bool(b)
497
    }
498
499
    fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> {
500
        (**self).write_bytes(b)
501
    }
502
503
    fn write_i8(&mut self, i: i8) -> crate::Result<()> {
504
        (**self).write_i8(i)
505
    }
506
507
    fn write_i16(&mut self, i: i16) -> crate::Result<()> {
508
        (**self).write_i16(i)
509
    }
510
511
    fn write_i32(&mut self, i: i32) -> crate::Result<()> {
512
        (**self).write_i32(i)
513
    }
514
515
    fn write_i64(&mut self, i: i64) -> crate::Result<()> {
516
        (**self).write_i64(i)
517
    }
518
519
    fn write_double(&mut self, d: f64) -> crate::Result<()> {
520
        (**self).write_double(d)
521
    }
522
523
    fn write_uuid(&mut self, uuid: &uuid::Uuid) -> crate::Result<()> {
524
        (**self).write_uuid(uuid)
525
    }
526
527
    fn write_string(&mut self, s: &str) -> crate::Result<()> {
528
        (**self).write_string(s)
529
    }
530
531
    fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> {
532
        (**self).write_list_begin(identifier)
533
    }
534
535
    fn write_list_end(&mut self) -> crate::Result<()> {
536
        (**self).write_list_end()
537
    }
538
539
    fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> {
540
        (**self).write_set_begin(identifier)
541
    }
542
543
    fn write_set_end(&mut self) -> crate::Result<()> {
544
        (**self).write_set_end()
545
    }
546
547
    fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> {
548
        (**self).write_map_begin(identifier)
549
    }
550
551
    fn write_map_end(&mut self) -> crate::Result<()> {
552
        (**self).write_map_end()
553
    }
554
555
    fn flush(&mut self) -> crate::Result<()> {
556
        (**self).flush()
557
    }
558
559
    fn write_byte(&mut self, b: u8) -> crate::Result<()> {
560
        (**self).write_byte(b)
561
    }
562
}
563
564
/// Helper type used by servers to create `TInputProtocol` instances for
565
/// accepted client connections.
566
///
567
/// # Examples
568
///
569
/// Create a `TInputProtocolFactory` and use it to create a `TInputProtocol`.
570
///
571
/// ```no_run
572
/// use thrift::protocol::{TBinaryInputProtocolFactory, TInputProtocolFactory};
573
/// use thrift::transport::TTcpChannel;
574
///
575
/// let mut channel = TTcpChannel::new();
576
/// channel.open("127.0.0.1:9090").unwrap();
577
///
578
/// let factory = TBinaryInputProtocolFactory::new();
579
/// let protocol = factory.create(Box::new(channel));
580
/// ```
581
pub trait TInputProtocolFactory {
582
    /// Create a `TInputProtocol` that reads bytes from `transport`.
583
    fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send>;
584
}
585
586
impl<T> TInputProtocolFactory for Box<T>
587
where
588
    T: TInputProtocolFactory + ?Sized,
589
{
590
    fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send> {
591
        (**self).create(transport)
592
    }
593
}
594
595
/// Helper type used by servers to create `TOutputProtocol` instances for
596
/// accepted client connections.
597
///
598
/// # Examples
599
///
600
/// Create a `TOutputProtocolFactory` and use it to create a `TOutputProtocol`.
601
///
602
/// ```no_run
603
/// use thrift::protocol::{TBinaryOutputProtocolFactory, TOutputProtocolFactory};
604
/// use thrift::transport::TTcpChannel;
605
///
606
/// let mut channel = TTcpChannel::new();
607
/// channel.open("127.0.0.1:9090").unwrap();
608
///
609
/// let factory = TBinaryOutputProtocolFactory::new();
610
/// let protocol = factory.create(Box::new(channel));
611
/// ```
612
pub trait TOutputProtocolFactory {
613
    /// Create a `TOutputProtocol` that writes bytes to `transport`.
614
    fn create(&self, transport: Box<dyn TWriteTransport + Send>)
615
        -> Box<dyn TOutputProtocol + Send>;
616
}
617
618
impl<T> TOutputProtocolFactory for Box<T>
619
where
620
    T: TOutputProtocolFactory + ?Sized,
621
{
622
    fn create(
623
        &self,
624
        transport: Box<dyn TWriteTransport + Send>,
625
    ) -> Box<dyn TOutputProtocol + Send> {
626
        (**self).create(transport)
627
    }
628
}
629
630
/// Thrift message identifier.
631
#[derive(Clone, Debug, Eq, PartialEq)]
632
pub struct TMessageIdentifier {
633
    /// Service call the message is associated with.
634
    pub name: String,
635
    /// Message type.
636
    pub message_type: TMessageType,
637
    /// Ordered sequence number identifying the message.
638
    pub sequence_number: i32,
639
}
640
641
impl TMessageIdentifier {
642
    /// Create a `TMessageIdentifier` for a Thrift service-call named `name`
643
    /// with message type `message_type` and sequence number `sequence_number`.
644
0
    pub fn new<S: Into<String>>(
645
0
        name: S,
646
0
        message_type: TMessageType,
647
0
        sequence_number: i32,
648
0
    ) -> TMessageIdentifier {
649
0
        TMessageIdentifier {
650
0
            name: name.into(),
651
0
            message_type,
652
0
            sequence_number,
653
0
        }
654
0
    }
Unexecuted instantiation: <thrift::protocol::TMessageIdentifier>::new::<alloc::string::String>
Unexecuted instantiation: <thrift::protocol::TMessageIdentifier>::new::<&str>
655
}
656
657
/// Thrift struct identifier.
658
#[derive(Clone, Debug, Eq, PartialEq)]
659
pub struct TStructIdentifier {
660
    /// Name of the encoded Thrift struct.
661
    pub name: String,
662
}
663
664
impl TStructIdentifier {
665
    /// Create a `TStructIdentifier` for a struct named `name`.
666
724k
    pub fn new<S: Into<String>>(name: S) -> TStructIdentifier {
667
724k
        TStructIdentifier { name: name.into() }
668
724k
    }
669
}
670
671
/// Thrift field identifier.
672
#[derive(Clone, Debug, Eq, PartialEq)]
673
pub struct TFieldIdentifier {
674
    /// Name of the Thrift field.
675
    ///
676
    /// `None` if it's not sent over the wire.
677
    pub name: Option<String>,
678
    /// Field type.
679
    ///
680
    /// This may be a primitive, container, or a struct.
681
    pub field_type: TType,
682
    /// Thrift field id.
683
    ///
684
    /// `None` only if `field_type` is `TType::Stop`.
685
    pub id: Option<i16>,
686
}
687
688
impl TFieldIdentifier {
689
    /// Create a `TFieldIdentifier` for a field named `name` with type
690
    /// `field_type` and field id `id`.
691
    ///
692
    /// `id` should be `None` if `field_type` is `TType::Stop`.
693
3.59M
    pub fn new<N, S, I>(name: N, field_type: TType, id: I) -> TFieldIdentifier
694
3.59M
    where
695
3.59M
        N: Into<Option<S>>,
696
3.59M
        S: Into<String>,
697
3.59M
        I: Into<Option<i16>>,
698
    {
699
        TFieldIdentifier {
700
3.59M
            name: name.into().map(|n| n.into()),
Unexecuted instantiation: <thrift::protocol::TFieldIdentifier>::new::<core::option::Option<alloc::string::String>, alloc::string::String, core::option::Option<i16>>::{closure#0}
Unexecuted instantiation: <thrift::protocol::TFieldIdentifier>::new::<core::option::Option<alloc::string::String>, alloc::string::String, i16>::{closure#0}
<thrift::protocol::TFieldIdentifier>::new::<&str, &str, i16>::{closure#0}
Line
Count
Source
700
1.08M
            name: name.into().map(|n| n.into()),
701
3.59M
            field_type,
702
3.59M
            id: id.into(),
703
        }
704
3.59M
    }
<thrift::protocol::TFieldIdentifier>::new::<core::option::Option<alloc::string::String>, alloc::string::String, core::option::Option<i16>>
Line
Count
Source
693
968k
    pub fn new<N, S, I>(name: N, field_type: TType, id: I) -> TFieldIdentifier
694
968k
    where
695
968k
        N: Into<Option<S>>,
696
968k
        S: Into<String>,
697
968k
        I: Into<Option<i16>>,
698
    {
699
        TFieldIdentifier {
700
968k
            name: name.into().map(|n| n.into()),
701
968k
            field_type,
702
968k
            id: id.into(),
703
        }
704
968k
    }
<thrift::protocol::TFieldIdentifier>::new::<core::option::Option<alloc::string::String>, alloc::string::String, i16>
Line
Count
Source
693
1.53M
    pub fn new<N, S, I>(name: N, field_type: TType, id: I) -> TFieldIdentifier
694
1.53M
    where
695
1.53M
        N: Into<Option<S>>,
696
1.53M
        S: Into<String>,
697
1.53M
        I: Into<Option<i16>>,
698
    {
699
        TFieldIdentifier {
700
1.53M
            name: name.into().map(|n| n.into()),
701
1.53M
            field_type,
702
1.53M
            id: id.into(),
703
        }
704
1.53M
    }
<thrift::protocol::TFieldIdentifier>::new::<&str, &str, i16>
Line
Count
Source
693
1.08M
    pub fn new<N, S, I>(name: N, field_type: TType, id: I) -> TFieldIdentifier
694
1.08M
    where
695
1.08M
        N: Into<Option<S>>,
696
1.08M
        S: Into<String>,
697
1.08M
        I: Into<Option<i16>>,
698
    {
699
        TFieldIdentifier {
700
1.08M
            name: name.into().map(|n| n.into()),
701
1.08M
            field_type,
702
1.08M
            id: id.into(),
703
        }
704
1.08M
    }
705
}
706
707
/// Thrift list identifier.
708
#[derive(Clone, Debug, Eq, PartialEq)]
709
pub struct TListIdentifier {
710
    /// Type of the elements in the list.
711
    pub element_type: TType,
712
    /// Number of elements in the list.
713
    pub size: i32,
714
}
715
716
impl TListIdentifier {
717
    /// Create a `TListIdentifier` for a list with `size` elements of type
718
    /// `element_type`.
719
2.94M
    pub fn new(element_type: TType, size: i32) -> TListIdentifier {
720
2.94M
        TListIdentifier { element_type, size }
721
2.94M
    }
722
}
723
724
/// Thrift set identifier.
725
#[derive(Clone, Debug, Eq, PartialEq)]
726
pub struct TSetIdentifier {
727
    /// Type of the elements in the set.
728
    pub element_type: TType,
729
    /// Number of elements in the set.
730
    pub size: i32,
731
}
732
733
impl TSetIdentifier {
734
    /// Create a `TSetIdentifier` for a set with `size` elements of type
735
    /// `element_type`.
736
214k
    pub fn new(element_type: TType, size: i32) -> TSetIdentifier {
737
214k
        TSetIdentifier { element_type, size }
738
214k
    }
739
}
740
741
/// Thrift map identifier.
742
#[derive(Clone, Debug, Eq, PartialEq)]
743
pub struct TMapIdentifier {
744
    /// Map key type.
745
    pub key_type: Option<TType>,
746
    /// Map value type.
747
    pub value_type: Option<TType>,
748
    /// Number of entries in the map.
749
    pub size: i32,
750
}
751
752
impl TMapIdentifier {
753
    /// Create a `TMapIdentifier` for a map with `size` entries of type
754
    /// `key_type -> value_type`.
755
169k
    pub fn new<K, V>(key_type: K, value_type: V, size: i32) -> TMapIdentifier
756
169k
    where
757
169k
        K: Into<Option<TType>>,
758
169k
        V: Into<Option<TType>>,
759
    {
760
169k
        TMapIdentifier {
761
169k
            key_type: key_type.into(),
762
169k
            value_type: value_type.into(),
763
169k
            size,
764
169k
        }
765
169k
    }
<thrift::protocol::TMapIdentifier>::new::<core::option::Option<thrift::protocol::TType>, core::option::Option<thrift::protocol::TType>>
Line
Count
Source
755
12.0k
    pub fn new<K, V>(key_type: K, value_type: V, size: i32) -> TMapIdentifier
756
12.0k
    where
757
12.0k
        K: Into<Option<TType>>,
758
12.0k
        V: Into<Option<TType>>,
759
    {
760
12.0k
        TMapIdentifier {
761
12.0k
            key_type: key_type.into(),
762
12.0k
            value_type: value_type.into(),
763
12.0k
            size,
764
12.0k
        }
765
12.0k
    }
<thrift::protocol::TMapIdentifier>::new::<thrift::protocol::TType, thrift::protocol::TType>
Line
Count
Source
755
157k
    pub fn new<K, V>(key_type: K, value_type: V, size: i32) -> TMapIdentifier
756
157k
    where
757
157k
        K: Into<Option<TType>>,
758
157k
        V: Into<Option<TType>>,
759
    {
760
157k
        TMapIdentifier {
761
157k
            key_type: key_type.into(),
762
157k
            value_type: value_type.into(),
763
157k
            size,
764
157k
        }
765
157k
    }
766
}
767
768
/// Thrift message types.
769
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
770
pub enum TMessageType {
771
    /// Service-call request.
772
    Call,
773
    /// Service-call response.
774
    Reply,
775
    /// Unexpected error in the remote service.
776
    Exception,
777
    /// One-way service-call request (no response is expected).
778
    OneWay,
779
}
780
781
impl Display for TMessageType {
782
0
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
783
0
        match *self {
784
0
            TMessageType::Call => write!(f, "Call"),
785
0
            TMessageType::Reply => write!(f, "Reply"),
786
0
            TMessageType::Exception => write!(f, "Exception"),
787
0
            TMessageType::OneWay => write!(f, "OneWay"),
788
        }
789
0
    }
790
}
791
792
impl From<TMessageType> for u8 {
793
0
    fn from(message_type: TMessageType) -> Self {
794
0
        match message_type {
795
0
            TMessageType::Call => 0x01,
796
0
            TMessageType::Reply => 0x02,
797
0
            TMessageType::Exception => 0x03,
798
0
            TMessageType::OneWay => 0x04,
799
        }
800
0
    }
801
}
802
803
impl TryFrom<u8> for TMessageType {
804
    type Error = crate::Error;
805
0
    fn try_from(b: u8) -> Result<Self, Self::Error> {
806
0
        match b {
807
0
            0x01 => Ok(TMessageType::Call),
808
0
            0x02 => Ok(TMessageType::Reply),
809
0
            0x03 => Ok(TMessageType::Exception),
810
0
            0x04 => Ok(TMessageType::OneWay),
811
0
            unkn => Err(crate::Error::Protocol(ProtocolError {
812
0
                kind: ProtocolErrorKind::InvalidData,
813
0
                message: format!("cannot convert {} to TMessageType", unkn),
814
0
            })),
815
        }
816
0
    }
817
}
818
819
/// Thrift struct-field types.
820
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
821
pub enum TType {
822
    /// Indicates that there are no more serialized fields in this Thrift struct.
823
    Stop,
824
    /// Void (`()`) field.
825
    Void,
826
    /// Boolean.
827
    Bool,
828
    /// Signed 8-bit int.
829
    I08,
830
    /// Double-precision number.
831
    Double,
832
    /// Signed 16-bit int.
833
    I16,
834
    /// Signed 32-bit int.
835
    I32,
836
    /// Signed 64-bit int.
837
    I64,
838
    /// UTF-8 string.
839
    String,
840
    /// UTF-7 string. *Unsupported*.
841
    Utf7,
842
    /// Thrift struct.
843
    Struct,
844
    /// Map.
845
    Map,
846
    /// Set.
847
    Set,
848
    /// List.
849
    List,
850
    /// Uuid.
851
    Uuid,
852
}
853
854
impl Display for TType {
855
0
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
856
0
        match *self {
857
0
            TType::Stop => write!(f, "STOP"),
858
0
            TType::Void => write!(f, "void"),
859
0
            TType::Bool => write!(f, "bool"),
860
0
            TType::I08 => write!(f, "i08"),
861
0
            TType::Double => write!(f, "double"),
862
0
            TType::I16 => write!(f, "i16"),
863
0
            TType::I32 => write!(f, "i32"),
864
0
            TType::I64 => write!(f, "i64"),
865
0
            TType::String => write!(f, "string"),
866
0
            TType::Utf7 => write!(f, "UTF7"),
867
0
            TType::Struct => write!(f, "struct"),
868
0
            TType::Map => write!(f, "map"),
869
0
            TType::Set => write!(f, "set"),
870
0
            TType::List => write!(f, "list"),
871
0
            TType::Uuid => write!(f, "UUID"),
872
        }
873
0
    }
874
}
875
876
/// Compare the expected message sequence number `expected` with the received
877
/// message sequence number `actual`.
878
///
879
/// Return `()` if `actual == expected`, `Err` otherwise.
880
0
pub fn verify_expected_sequence_number(expected: i32, actual: i32) -> crate::Result<()> {
881
0
    if expected == actual {
882
0
        Ok(())
883
    } else {
884
0
        Err(crate::Error::Application(crate::ApplicationError {
885
0
            kind: crate::ApplicationErrorKind::BadSequenceId,
886
0
            message: format!("expected {} got {}", expected, actual),
887
0
        }))
888
    }
889
0
}
890
891
/// Compare the expected service-call name `expected` with the received
892
/// service-call name `actual`.
893
///
894
/// Return `()` if `actual == expected`, `Err` otherwise.
895
0
pub fn verify_expected_service_call(expected: &str, actual: &str) -> crate::Result<()> {
896
0
    if expected == actual {
897
0
        Ok(())
898
    } else {
899
0
        Err(crate::Error::Application(crate::ApplicationError {
900
0
            kind: crate::ApplicationErrorKind::WrongMethodName,
901
0
            message: format!("expected {} got {}", expected, actual),
902
0
        }))
903
    }
904
0
}
905
906
/// Compare the expected message type `expected` with the received message type
907
/// `actual`.
908
///
909
/// Return `()` if `actual == expected`, `Err` otherwise.
910
0
pub fn verify_expected_message_type(
911
0
    expected: TMessageType,
912
0
    actual: TMessageType,
913
0
) -> crate::Result<()> {
914
0
    if expected == actual {
915
0
        Ok(())
916
    } else {
917
0
        Err(crate::Error::Application(crate::ApplicationError {
918
0
            kind: crate::ApplicationErrorKind::InvalidMessageType,
919
0
            message: format!("expected {} got {}", expected, actual),
920
0
        }))
921
    }
922
0
}
923
924
/// Check if a required Thrift struct field exists.
925
///
926
/// Return `()` if it does, `Err` otherwise.
927
101k
pub fn verify_required_field_exists<T>(field_name: &str, field: &Option<T>) -> crate::Result<()> {
928
101k
    match *field {
929
100k
        Some(_) => Ok(()),
930
740
        None => Err(crate::Error::Protocol(crate::ProtocolError {
931
740
            kind: crate::ProtocolErrorKind::Unknown,
932
740
            message: format!("missing required field {}", field_name),
933
740
        })),
934
    }
935
101k
}
thrift::protocol::verify_required_field_exists::<thrift_fuzz::fuzz_test::BasicTypes>
Line
Count
Source
927
7.44k
pub fn verify_required_field_exists<T>(field_name: &str, field: &Option<T>) -> crate::Result<()> {
928
7.44k
    match *field {
929
7.15k
        Some(_) => Ok(()),
930
286
        None => Err(crate::Error::Protocol(crate::ProtocolError {
931
286
            kind: crate::ProtocolErrorKind::Unknown,
932
286
            message: format!("missing required field {}", field_name),
933
286
        })),
934
    }
935
7.44k
}
thrift::protocol::verify_required_field_exists::<thrift_fuzz::fuzz_test::Containers>
Line
Count
Source
927
6.99k
pub fn verify_required_field_exists<T>(field_name: &str, field: &Option<T>) -> crate::Result<()> {
928
6.99k
    match *field {
929
6.91k
        Some(_) => Ok(()),
930
80
        None => Err(crate::Error::Protocol(crate::ProtocolError {
931
80
            kind: crate::ProtocolErrorKind::Unknown,
932
80
            message: format!("missing required field {}", field_name),
933
80
        })),
934
    }
935
6.99k
}
thrift::protocol::verify_required_field_exists::<thrift_fuzz::fuzz_test::Requiredness>
Line
Count
Source
927
7.15k
pub fn verify_required_field_exists<T>(field_name: &str, field: &Option<T>) -> crate::Result<()> {
928
7.15k
    match *field {
929
6.99k
        Some(_) => Ok(()),
930
165
        None => Err(crate::Error::Protocol(crate::ProtocolError {
931
165
            kind: crate::ProtocolErrorKind::Unknown,
932
165
            message: format!("missing required field {}", field_name),
933
165
        })),
934
    }
935
7.15k
}
thrift::protocol::verify_required_field_exists::<thrift_fuzz::fuzz_test::TestEnum>
Line
Count
Source
927
6.85k
pub fn verify_required_field_exists<T>(field_name: &str, field: &Option<T>) -> crate::Result<()> {
928
6.85k
    match *field {
929
6.80k
        Some(_) => Ok(()),
930
54
        None => Err(crate::Error::Protocol(crate::ProtocolError {
931
54
            kind: crate::ProtocolErrorKind::Unknown,
932
54
            message: format!("missing required field {}", field_name),
933
54
        })),
934
    }
935
6.85k
}
thrift::protocol::verify_required_field_exists::<thrift_fuzz::fuzz_test::TestUnion>
Line
Count
Source
927
6.91k
pub fn verify_required_field_exists<T>(field_name: &str, field: &Option<T>) -> crate::Result<()> {
928
6.91k
    match *field {
929
6.85k
        Some(_) => Ok(()),
930
57
        None => Err(crate::Error::Protocol(crate::ProtocolError {
931
57
            kind: crate::ProtocolErrorKind::Unknown,
932
57
            message: format!("missing required field {}", field_name),
933
57
        })),
934
    }
935
6.91k
}
thrift::protocol::verify_required_field_exists::<bool>
Line
Count
Source
927
33.1k
pub fn verify_required_field_exists<T>(field_name: &str, field: &Option<T>) -> crate::Result<()> {
928
33.1k
    match *field {
929
33.0k
        Some(_) => Ok(()),
930
32
        None => Err(crate::Error::Protocol(crate::ProtocolError {
931
32
            kind: crate::ProtocolErrorKind::Unknown,
932
32
            message: format!("missing required field {}", field_name),
933
32
        })),
934
    }
935
33.1k
}
thrift::protocol::verify_required_field_exists::<i32>
Line
Count
Source
927
33.1k
pub fn verify_required_field_exists<T>(field_name: &str, field: &Option<T>) -> crate::Result<()> {
928
33.1k
    match *field {
929
33.1k
        Some(_) => Ok(()),
930
66
        None => Err(crate::Error::Protocol(crate::ProtocolError {
931
66
            kind: crate::ProtocolErrorKind::Unknown,
932
66
            message: format!("missing required field {}", field_name),
933
66
        })),
934
    }
935
33.1k
}
936
937
/// Common container size validation used by all protocols.
938
///
939
/// Checks that:
940
/// - Container size is not negative
941
/// - Container size doesn't exceed configured maximum
942
/// - Container size * element size doesn't overflow
943
/// - Container memory requirements don't exceed message size limit
944
3.26M
pub(crate) fn check_container_size(
945
3.26M
    config: &TConfiguration,
946
3.26M
    container_size: i32,
947
3.26M
    element_size: usize,
948
3.26M
) -> crate::Result<()> {
949
    // Check for negative size
950
3.26M
    if container_size < 0 {
951
132
        return Err(crate::Error::Protocol(ProtocolError::new(
952
132
            ProtocolErrorKind::NegativeSize,
953
132
            format!("Negative container size: {}", container_size),
954
132
        )));
955
3.26M
    }
956
957
3.26M
    let size_as_usize = container_size as usize;
958
959
    // Check against configured max container size
960
3.26M
    if let Some(max_size) = config.max_container_size() {
961
3.26M
        if size_as_usize > max_size {
962
168
            return Err(crate::Error::Protocol(ProtocolError::new(
963
168
                ProtocolErrorKind::SizeLimit,
964
168
                format!(
965
168
                    "Container size {} exceeds maximum allowed size of {}",
966
168
                    container_size, max_size
967
168
                ),
968
168
            )));
969
3.26M
        }
970
0
    }
971
972
    // Check for potential overflow
973
3.26M
    if let Some(min_bytes_needed) = size_as_usize.checked_mul(element_size) {
974
        // TODO: When Rust trait specialization stabilizes, we can add more precise checks
975
        // for transports that track exact remaining bytes. For now, we use the message
976
        // size limit as a best-effort check.
977
3.26M
        if let Some(max_message_size) = config.max_message_size() {
978
3.26M
            if min_bytes_needed > max_message_size {
979
134
                return Err(crate::Error::Protocol(ProtocolError::new(
980
134
                    ProtocolErrorKind::SizeLimit,
981
134
                    format!(
982
134
                        "Container would require {} bytes, exceeding message size limit of {}",
983
134
                        min_bytes_needed, max_message_size
984
134
                    ),
985
134
                )));
986
3.26M
            }
987
0
        }
988
3.26M
        Ok(())
989
    } else {
990
0
        Err(crate::Error::Protocol(ProtocolError::new(
991
0
            ProtocolErrorKind::SizeLimit,
992
0
            format!(
993
0
                "Container size {} with element size {} bytes would result in overflow",
994
0
                container_size, element_size
995
0
            ),
996
0
        )))
997
    }
998
3.26M
}
999
1000
/// Extract the field id from a Thrift field identifier.
1001
///
1002
/// `field_ident` must *not* have `TFieldIdentifier.field_type` of type `TType::Stop`.
1003
///
1004
/// Return `TFieldIdentifier.id` if an id exists, `Err` otherwise.
1005
3.16M
pub fn field_id(field_ident: &TFieldIdentifier) -> crate::Result<i16> {
1006
3.16M
    field_ident.id.ok_or_else(|| {
1007
0
        crate::Error::Protocol(crate::ProtocolError {
1008
0
            kind: crate::ProtocolErrorKind::Unknown,
1009
0
            message: format!("missing field id in {:?}", field_ident),
1010
0
        })
1011
0
    })
1012
3.16M
}
1013
1014
#[cfg(test)]
1015
mod tests {
1016
1017
    use std::io::Cursor;
1018
1019
    use super::*;
1020
    use crate::transport::{TReadTransport, TWriteTransport};
1021
1022
    #[test]
1023
    fn must_create_usable_input_protocol_from_concrete_input_protocol() {
1024
        let r: Box<dyn TReadTransport> = Box::new(Cursor::new([0, 1, 2]));
1025
        let mut t = TCompactInputProtocol::new(r);
1026
        takes_input_protocol(&mut t)
1027
    }
1028
1029
    #[test]
1030
    fn must_create_usable_input_protocol_from_boxed_input() {
1031
        let r: Box<dyn TReadTransport> = Box::new(Cursor::new([0, 1, 2]));
1032
        let mut t: Box<dyn TInputProtocol> = Box::new(TCompactInputProtocol::new(r));
1033
        takes_input_protocol(&mut t)
1034
    }
1035
1036
    #[test]
1037
    fn must_create_usable_output_protocol_from_concrete_output_protocol() {
1038
        let w: Box<dyn TWriteTransport> = Box::new(vec![0u8; 10]);
1039
        let mut t = TCompactOutputProtocol::new(w);
1040
        takes_output_protocol(&mut t)
1041
    }
1042
1043
    #[test]
1044
    fn must_create_usable_output_protocol_from_boxed_output() {
1045
        let w: Box<dyn TWriteTransport> = Box::new(vec![0u8; 10]);
1046
        let mut t: Box<dyn TOutputProtocol> = Box::new(TCompactOutputProtocol::new(w));
1047
        takes_output_protocol(&mut t)
1048
    }
1049
1050
    fn takes_input_protocol<R>(t: &mut R)
1051
    where
1052
        R: TInputProtocol,
1053
    {
1054
        t.read_byte().unwrap();
1055
    }
1056
1057
    fn takes_output_protocol<W>(t: &mut W)
1058
    where
1059
        W: TOutputProtocol,
1060
    {
1061
        t.flush().unwrap();
1062
    }
1063
1064
    // Test unknown binary fields are skipped without error (THRIFT-5928)
1065
1066
    fn build_struct_with_unknown_binary_field(payload: &[u8]) -> Vec<u8> {
1067
        let mut buf = Vec::new();
1068
        buf.push(0x0A); // field 1: TType::I64
1069
        buf.extend_from_slice(&1_i16.to_be_bytes());
1070
        buf.extend_from_slice(&42_i64.to_be_bytes());
1071
        buf.push(0x0B); // field 99: TType::String (same wire type for binary)
1072
        buf.extend_from_slice(&99_i16.to_be_bytes());
1073
        buf.extend_from_slice(&(payload.len() as i32).to_be_bytes());
1074
        buf.extend_from_slice(payload);
1075
        buf.push(0x00); // stop
1076
        buf
1077
    }
1078
1079
    fn read_struct_skipping_unknown(data: &[u8]) -> crate::Result<i64> {
1080
        let cursor = Cursor::new(data.to_vec());
1081
        let mut proto = TBinaryInputProtocol::new(cursor, true);
1082
        proto.read_struct_begin()?;
1083
        let mut known_value: Option<i64> = None;
1084
        loop {
1085
            let field = proto.read_field_begin()?;
1086
            if field.field_type == TType::Stop {
1087
                break;
1088
            }
1089
            match field.id {
1090
                Some(1) if field.field_type == TType::I64 => {
1091
                    known_value = Some(proto.read_i64()?);
1092
                }
1093
                _ => {
1094
                    proto.skip(field.field_type)?;
1095
                }
1096
            }
1097
            proto.read_field_end()?;
1098
        }
1099
        proto.read_struct_end()?;
1100
        known_value.ok_or_else(|| {
1101
            crate::Error::Protocol(crate::ProtocolError {
1102
                kind: crate::ProtocolErrorKind::InvalidData,
1103
                message: "missing known field".to_string(),
1104
            })
1105
        })
1106
    }
1107
1108
    #[test]
1109
    fn must_skip_binary_field_with_non_utf8_bytes() {
1110
        let non_utf8: Vec<u8> = vec![
1111
            0x04, 0xFF, 0xFE, 0x80, 0x90, 0xAB, 0xCD, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE,
1112
            0xBA, 0xBE,
1113
        ];
1114
        assert!(String::from_utf8(non_utf8.clone()).is_err());
1115
        let data = build_struct_with_unknown_binary_field(&non_utf8);
1116
        let result = read_struct_skipping_unknown(&data);
1117
        assert!(
1118
            result.is_ok(),
1119
            "skip() failed on non-UTF-8 binary: {:?}",
1120
            result.err()
1121
        );
1122
        assert_eq!(result.unwrap(), 42);
1123
    }
1124
1125
    #[test]
1126
    fn must_skip_valid_utf8_string_field() {
1127
        let data = build_struct_with_unknown_binary_field(b"hello world");
1128
        assert_eq!(read_struct_skipping_unknown(&data).unwrap(), 42);
1129
    }
1130
1131
    #[test]
1132
    fn must_skip_empty_binary_field() {
1133
        let data = build_struct_with_unknown_binary_field(&[]);
1134
        assert_eq!(read_struct_skipping_unknown(&data).unwrap(), 42);
1135
    }
1136
}