Coverage Report

Created: 2026-06-15 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/thrift/lib/rs/src/protocol/compact.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
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
19
use integer_encoding::VarIntWriter;
20
use std::convert::{From, TryFrom};
21
use std::io;
22
23
use super::{
24
    TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier, TMapIdentifier,
25
    TMessageIdentifier, TMessageType,
26
};
27
use super::{TOutputProtocol, TOutputProtocolFactory, TSetIdentifier, TStructIdentifier, TType};
28
use crate::transport::{TReadTransport, TWriteTransport};
29
use crate::{ProtocolError, ProtocolErrorKind, TConfiguration};
30
31
const COMPACT_PROTOCOL_ID: u8 = 0x82;
32
const COMPACT_VERSION: u8 = 0x01;
33
const COMPACT_VERSION_MASK: u8 = 0x1F;
34
const MAX_VARINT32_BYTES: usize = 5; // ceil(32/7); matches protobuf wire format
35
const MAX_VARINT64_BYTES: usize = 10; // ceil(64/7); matches protobuf wire format
36
37
/// Read messages encoded in the Thrift compact protocol.
38
///
39
/// # Examples
40
///
41
/// Create and use a `TCompactInputProtocol`.
42
///
43
/// ```no_run
44
/// use thrift::protocol::{TCompactInputProtocol, TInputProtocol};
45
/// use thrift::transport::TTcpChannel;
46
///
47
/// let mut channel = TTcpChannel::new();
48
/// channel.open("localhost:9090").unwrap();
49
///
50
/// let mut protocol = TCompactInputProtocol::new(channel);
51
///
52
/// let recvd_bool = protocol.read_bool().unwrap();
53
/// let recvd_string = protocol.read_string().unwrap();
54
/// ```
55
#[derive(Debug)]
56
pub struct TCompactInputProtocol<T>
57
where
58
    T: TReadTransport,
59
{
60
    // Identifier of the last field deserialized for a struct.
61
    last_read_field_id: i16,
62
    // Stack of the last read field ids (a new entry is added each time a nested struct is read).
63
    read_field_id_stack: Vec<i16>,
64
    // Boolean value for a field.
65
    // Saved because boolean fields and their value are encoded in a single byte,
66
    // and reading the field only occurs after the field id is read.
67
    pending_read_bool_value: Option<bool>,
68
    // Underlying transport used for byte-level operations.
69
    transport: T,
70
    // Configuration
71
    config: TConfiguration,
72
    // Current recursion depth
73
    recursion_depth: usize,
74
}
75
76
impl<T> TCompactInputProtocol<T>
77
where
78
    T: TReadTransport,
79
{
80
    /// Create a `TCompactInputProtocol` that reads bytes from `transport`.
81
0
    pub fn new(transport: T) -> TCompactInputProtocol<T> {
82
0
        Self::with_config(transport, TConfiguration::default())
83
0
    }
84
85
    /// Create a `TCompactInputProtocol` with custom configuration.
86
14.7k
    pub fn with_config(transport: T, config: TConfiguration) -> TCompactInputProtocol<T> {
87
14.7k
        TCompactInputProtocol {
88
14.7k
            last_read_field_id: 0,
89
14.7k
            read_field_id_stack: Vec::new(),
90
14.7k
            pending_read_bool_value: None,
91
14.7k
            transport,
92
14.7k
            config,
93
14.7k
            recursion_depth: 0,
94
14.7k
        }
95
14.7k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>>>::with_config
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel>>::with_config
Line
Count
Source
86
6.42k
    pub fn with_config(transport: T, config: TConfiguration) -> TCompactInputProtocol<T> {
87
6.42k
        TCompactInputProtocol {
88
6.42k
            last_read_field_id: 0,
89
6.42k
            read_field_id_stack: Vec::new(),
90
6.42k
            pending_read_bool_value: None,
91
6.42k
            transport,
92
6.42k
            config,
93
6.42k
            recursion_depth: 0,
94
6.42k
        }
95
6.42k
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel>>::with_config
Line
Count
Source
86
8.30k
    pub fn with_config(transport: T, config: TConfiguration) -> TCompactInputProtocol<T> {
87
8.30k
        TCompactInputProtocol {
88
8.30k
            last_read_field_id: 0,
89
8.30k
            read_field_id_stack: Vec::new(),
90
8.30k
            pending_read_bool_value: None,
91
8.30k
            transport,
92
8.30k
            config,
93
8.30k
            recursion_depth: 0,
94
8.30k
        }
95
8.30k
    }
96
97
2.59M
    fn read_list_set_begin(&mut self) -> crate::Result<(TType, i32)> {
98
2.59M
        let header = self.read_byte()?;
99
2.59M
        let element_type = collection_u8_to_type(header & 0x0F)?;
100
101
2.59M
        let possible_element_count = (header & 0xF0) >> 4;
102
2.59M
        let element_count = if possible_element_count != 15 {
103
            // high bits set high if count and type encoded separately
104
2.57M
            possible_element_count as i32
105
        } else {
106
18.2k
            self.read_varint32()? as i32
107
        };
108
109
2.59M
        let min_element_size = self.min_serialized_size(element_type);
110
2.59M
        super::check_container_size(&self.config, element_count, min_element_size)?;
111
112
2.59M
        Ok((element_type, element_count))
113
2.59M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>>>::read_list_set_begin
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel>>::read_list_set_begin
Line
Count
Source
97
1.18M
    fn read_list_set_begin(&mut self) -> crate::Result<(TType, i32)> {
98
1.18M
        let header = self.read_byte()?;
99
1.18M
        let element_type = collection_u8_to_type(header & 0x0F)?;
100
101
1.18M
        let possible_element_count = (header & 0xF0) >> 4;
102
1.18M
        let element_count = if possible_element_count != 15 {
103
            // high bits set high if count and type encoded separately
104
1.17M
            possible_element_count as i32
105
        } else {
106
7.06k
            self.read_varint32()? as i32
107
        };
108
109
1.18M
        let min_element_size = self.min_serialized_size(element_type);
110
1.18M
        super::check_container_size(&self.config, element_count, min_element_size)?;
111
112
1.18M
        Ok((element_type, element_count))
113
1.18M
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel>>::read_list_set_begin
Line
Count
Source
97
1.41M
    fn read_list_set_begin(&mut self) -> crate::Result<(TType, i32)> {
98
1.41M
        let header = self.read_byte()?;
99
1.41M
        let element_type = collection_u8_to_type(header & 0x0F)?;
100
101
1.41M
        let possible_element_count = (header & 0xF0) >> 4;
102
1.41M
        let element_count = if possible_element_count != 15 {
103
            // high bits set high if count and type encoded separately
104
1.39M
            possible_element_count as i32
105
        } else {
106
11.2k
            self.read_varint32()? as i32
107
        };
108
109
1.41M
        let min_element_size = self.min_serialized_size(element_type);
110
1.41M
        super::check_container_size(&self.config, element_count, min_element_size)?;
111
112
1.41M
        Ok((element_type, element_count))
113
1.41M
    }
114
115
1.00M
    fn check_recursion_depth(&self) -> crate::Result<()> {
116
1.00M
        if let Some(limit) = self.config.max_recursion_depth() {
117
1.00M
            if self.recursion_depth >= limit {
118
15
                return Err(crate::Error::Protocol(ProtocolError::new(
119
15
                    ProtocolErrorKind::DepthLimit,
120
15
                    format!("Maximum recursion depth {} exceeded", limit),
121
15
                )));
122
1.00M
            }
123
0
        }
124
1.00M
        Ok(())
125
1.00M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>>>::check_recursion_depth
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel>>::check_recursion_depth
Line
Count
Source
115
136k
    fn check_recursion_depth(&self) -> crate::Result<()> {
116
136k
        if let Some(limit) = self.config.max_recursion_depth() {
117
136k
            if self.recursion_depth >= limit {
118
9
                return Err(crate::Error::Protocol(ProtocolError::new(
119
9
                    ProtocolErrorKind::DepthLimit,
120
9
                    format!("Maximum recursion depth {} exceeded", limit),
121
9
                )));
122
136k
            }
123
0
        }
124
136k
        Ok(())
125
136k
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel>>::check_recursion_depth
Line
Count
Source
115
869k
    fn check_recursion_depth(&self) -> crate::Result<()> {
116
869k
        if let Some(limit) = self.config.max_recursion_depth() {
117
869k
            if self.recursion_depth >= limit {
118
6
                return Err(crate::Error::Protocol(ProtocolError::new(
119
6
                    ProtocolErrorKind::DepthLimit,
120
6
                    format!("Maximum recursion depth {} exceeded", limit),
121
6
                )));
122
869k
            }
123
0
        }
124
869k
        Ok(())
125
869k
    }
126
127
12.9M
    fn read_varint32(&mut self) -> crate::Result<u32> {
128
12.9M
        let mut result = 0u32;
129
12.9M
        let mut shift = 0u32;
130
13.6M
        for _ in 0..MAX_VARINT32_BYTES {
131
13.6M
            let b = self.read_byte()?;
132
13.6M
            result |= ((b & 0x7F) as u32) << shift;
133
13.6M
            if b & 0x80 == 0 {
134
12.9M
                return Ok(result);
135
659k
            }
136
659k
            shift += 7;
137
        }
138
77
        Err(crate::Error::Protocol(ProtocolError::new(
139
77
            ProtocolErrorKind::InvalidData,
140
77
            "Variable-length int over 5 bytes.",
141
77
        )))
142
12.9M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>>>::read_varint32
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel>>::read_varint32
Line
Count
Source
127
4.96M
    fn read_varint32(&mut self) -> crate::Result<u32> {
128
4.96M
        let mut result = 0u32;
129
4.96M
        let mut shift = 0u32;
130
5.04M
        for _ in 0..MAX_VARINT32_BYTES {
131
5.04M
            let b = self.read_byte()?;
132
5.04M
            result |= ((b & 0x7F) as u32) << shift;
133
5.04M
            if b & 0x80 == 0 {
134
4.96M
                return Ok(result);
135
79.7k
            }
136
79.7k
            shift += 7;
137
        }
138
50
        Err(crate::Error::Protocol(ProtocolError::new(
139
50
            ProtocolErrorKind::InvalidData,
140
50
            "Variable-length int over 5 bytes.",
141
50
        )))
142
4.96M
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel>>::read_varint32
Line
Count
Source
127
8.02M
    fn read_varint32(&mut self) -> crate::Result<u32> {
128
8.02M
        let mut result = 0u32;
129
8.02M
        let mut shift = 0u32;
130
8.60M
        for _ in 0..MAX_VARINT32_BYTES {
131
8.60M
            let b = self.read_byte()?;
132
8.60M
            result |= ((b & 0x7F) as u32) << shift;
133
8.60M
            if b & 0x80 == 0 {
134
8.02M
                return Ok(result);
135
579k
            }
136
579k
            shift += 7;
137
        }
138
27
        Err(crate::Error::Protocol(ProtocolError::new(
139
27
            ProtocolErrorKind::InvalidData,
140
27
            "Variable-length int over 5 bytes.",
141
27
        )))
142
8.02M
    }
143
144
2.94M
    fn read_varint64(&mut self) -> crate::Result<u64> {
145
2.94M
        let mut result = 0u64;
146
2.94M
        let mut shift = 0u32;
147
4.45M
        for _ in 0..MAX_VARINT64_BYTES {
148
4.45M
            let b = self.read_byte()?;
149
4.45M
            result |= ((b & 0x7F) as u64) << shift;
150
4.45M
            if b & 0x80 == 0 {
151
2.94M
                return Ok(result);
152
1.51M
            }
153
1.51M
            shift += 7;
154
        }
155
23
        Err(crate::Error::Protocol(ProtocolError::new(
156
23
            ProtocolErrorKind::InvalidData,
157
23
            "Variable-length int over 10 bytes.",
158
23
        )))
159
2.94M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>>>::read_varint64
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel>>::read_varint64
Line
Count
Source
144
1.31M
    fn read_varint64(&mut self) -> crate::Result<u64> {
145
1.31M
        let mut result = 0u64;
146
1.31M
        let mut shift = 0u32;
147
2.16M
        for _ in 0..MAX_VARINT64_BYTES {
148
2.16M
            let b = self.read_byte()?;
149
2.16M
            result |= ((b & 0x7F) as u64) << shift;
150
2.16M
            if b & 0x80 == 0 {
151
1.31M
                return Ok(result);
152
845k
            }
153
845k
            shift += 7;
154
        }
155
13
        Err(crate::Error::Protocol(ProtocolError::new(
156
13
            ProtocolErrorKind::InvalidData,
157
13
            "Variable-length int over 10 bytes.",
158
13
        )))
159
1.31M
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel>>::read_varint64
Line
Count
Source
144
1.62M
    fn read_varint64(&mut self) -> crate::Result<u64> {
145
1.62M
        let mut result = 0u64;
146
1.62M
        let mut shift = 0u32;
147
2.29M
        for _ in 0..MAX_VARINT64_BYTES {
148
2.29M
            let b = self.read_byte()?;
149
2.29M
            result |= ((b & 0x7F) as u64) << shift;
150
2.29M
            if b & 0x80 == 0 {
151
1.62M
                return Ok(result);
152
670k
            }
153
670k
            shift += 7;
154
        }
155
10
        Err(crate::Error::Protocol(ProtocolError::new(
156
10
            ProtocolErrorKind::InvalidData,
157
10
            "Variable-length int over 10 bytes.",
158
10
        )))
159
1.62M
    }
160
}
161
162
impl<T> TInputProtocol for TCompactInputProtocol<T>
163
where
164
    T: TReadTransport,
165
{
166
0
    fn read_message_begin(&mut self) -> crate::Result<TMessageIdentifier> {
167
        // TODO: Once specialization is stable, call the message size tracking here
168
0
        let compact_id = self.read_byte()?;
169
0
        if compact_id != COMPACT_PROTOCOL_ID {
170
0
            Err(crate::Error::Protocol(crate::ProtocolError {
171
0
                kind: crate::ProtocolErrorKind::BadVersion,
172
0
                message: format!("invalid compact protocol header {:?}", compact_id),
173
0
            }))
174
        } else {
175
0
            Ok(())
176
0
        }?;
177
178
0
        let type_and_byte = self.read_byte()?;
179
0
        let received_version = type_and_byte & COMPACT_VERSION_MASK;
180
0
        if received_version != COMPACT_VERSION {
181
0
            Err(crate::Error::Protocol(crate::ProtocolError {
182
0
                kind: crate::ProtocolErrorKind::BadVersion,
183
0
                message: format!(
184
0
                    "cannot process compact protocol version {:?}",
185
0
                    received_version
186
0
                ),
187
0
            }))
188
        } else {
189
0
            Ok(())
190
0
        }?;
191
192
        // NOTE: unsigned right shift will pad with 0s
193
0
        let message_type: TMessageType = TMessageType::try_from(type_and_byte >> 5)?;
194
        // writing side wrote signed sequence number as u32 to avoid zigzag encoding
195
0
        let sequence_number = self.read_varint32()? as i32;
196
0
        let service_call_name = self.read_string()?;
197
198
0
        self.last_read_field_id = 0;
199
200
0
        Ok(TMessageIdentifier::new(
201
0
            service_call_name,
202
0
            message_type,
203
0
            sequence_number,
204
0
        ))
205
0
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_message_begin
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_message_begin
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_message_begin
206
207
0
    fn read_message_end(&mut self) -> crate::Result<()> {
208
0
        Ok(())
209
0
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_message_end
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_message_end
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_message_end
210
211
1.00M
    fn read_struct_begin(&mut self) -> crate::Result<Option<TStructIdentifier>> {
212
1.00M
        self.check_recursion_depth()?;
213
1.00M
        self.recursion_depth += 1;
214
1.00M
        self.read_field_id_stack.push(self.last_read_field_id);
215
1.00M
        self.last_read_field_id = 0;
216
1.00M
        Ok(None)
217
1.00M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_struct_begin
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_struct_begin
Line
Count
Source
211
136k
    fn read_struct_begin(&mut self) -> crate::Result<Option<TStructIdentifier>> {
212
136k
        self.check_recursion_depth()?;
213
136k
        self.recursion_depth += 1;
214
136k
        self.read_field_id_stack.push(self.last_read_field_id);
215
136k
        self.last_read_field_id = 0;
216
136k
        Ok(None)
217
136k
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_struct_begin
Line
Count
Source
211
869k
    fn read_struct_begin(&mut self) -> crate::Result<Option<TStructIdentifier>> {
212
869k
        self.check_recursion_depth()?;
213
869k
        self.recursion_depth += 1;
214
869k
        self.read_field_id_stack.push(self.last_read_field_id);
215
869k
        self.last_read_field_id = 0;
216
869k
        Ok(None)
217
869k
    }
218
219
981k
    fn read_struct_end(&mut self) -> crate::Result<()> {
220
981k
        self.recursion_depth -= 1;
221
981k
        self.last_read_field_id = self
222
981k
            .read_field_id_stack
223
981k
            .pop()
224
981k
            .expect("should have previous field ids");
225
981k
        Ok(())
226
981k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_struct_end
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_struct_end
Line
Count
Source
219
123k
    fn read_struct_end(&mut self) -> crate::Result<()> {
220
123k
        self.recursion_depth -= 1;
221
123k
        self.last_read_field_id = self
222
123k
            .read_field_id_stack
223
123k
            .pop()
224
123k
            .expect("should have previous field ids");
225
123k
        Ok(())
226
123k
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_struct_end
Line
Count
Source
219
857k
    fn read_struct_end(&mut self) -> crate::Result<()> {
220
857k
        self.recursion_depth -= 1;
221
857k
        self.last_read_field_id = self
222
857k
            .read_field_id_stack
223
857k
            .pop()
224
857k
            .expect("should have previous field ids");
225
857k
        Ok(())
226
857k
    }
227
228
3.50M
    fn read_field_begin(&mut self) -> crate::Result<TFieldIdentifier> {
229
        // we can read at least one byte, which is:
230
        // - the type
231
        // - the field delta and the type
232
3.50M
        let field_type = self.read_byte()?;
233
3.49M
        let field_delta = (field_type & 0xF0) >> 4;
234
3.49M
        let field_type = match field_type & 0x0F {
235
            0x01 => {
236
185k
                self.pending_read_bool_value = Some(true);
237
185k
                Ok(TType::Bool)
238
            }
239
            0x02 => {
240
638k
                self.pending_read_bool_value = Some(false);
241
638k
                Ok(TType::Bool)
242
            }
243
2.67M
            ttu8 => u8_to_type(ttu8),
244
166
        }?;
245
246
3.49M
        match field_type {
247
981k
            TType::Stop => Ok(
248
981k
                TFieldIdentifier::new::<Option<String>, String, Option<i16>>(
249
981k
                    None,
250
981k
                    TType::Stop,
251
981k
                    None,
252
981k
                ),
253
981k
            ),
254
            _ => {
255
2.51M
                if field_delta != 0 {
256
932k
                    self.last_read_field_id = self
257
932k
                        .last_read_field_id
258
932k
                        .checked_add(field_delta as i16)
259
932k
                        .ok_or_else(|| {
260
3
                            crate::Error::Protocol(ProtocolError::new(
261
3
                                ProtocolErrorKind::InvalidData,
262
3
                                "field id overflow",
263
3
                            ))
264
3
                        })?;
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_field_begin::{closure#0}
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_field_begin::{closure#0}
Line
Count
Source
259
1
                        .ok_or_else(|| {
260
1
                            crate::Error::Protocol(ProtocolError::new(
261
1
                                ProtocolErrorKind::InvalidData,
262
1
                                "field id overflow",
263
1
                            ))
264
1
                        })?;
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_field_begin::{closure#0}
Line
Count
Source
259
2
                        .ok_or_else(|| {
260
2
                            crate::Error::Protocol(ProtocolError::new(
261
2
                                ProtocolErrorKind::InvalidData,
262
2
                                "field id overflow",
263
2
                            ))
264
2
                        })?;
265
                } else {
266
1.58M
                    self.last_read_field_id = self.read_i16()?;
267
                };
268
269
2.51M
                Ok(TFieldIdentifier {
270
2.51M
                    name: None,
271
2.51M
                    field_type,
272
2.51M
                    id: Some(self.last_read_field_id),
273
2.51M
                })
274
            }
275
        }
276
3.50M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_field_begin
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_field_begin
Line
Count
Source
228
1.03M
    fn read_field_begin(&mut self) -> crate::Result<TFieldIdentifier> {
229
        // we can read at least one byte, which is:
230
        // - the type
231
        // - the field delta and the type
232
1.03M
        let field_type = self.read_byte()?;
233
1.03M
        let field_delta = (field_type & 0xF0) >> 4;
234
1.03M
        let field_type = match field_type & 0x0F {
235
            0x01 => {
236
79.1k
                self.pending_read_bool_value = Some(true);
237
79.1k
                Ok(TType::Bool)
238
            }
239
            0x02 => {
240
116k
                self.pending_read_bool_value = Some(false);
241
116k
                Ok(TType::Bool)
242
            }
243
835k
            ttu8 => u8_to_type(ttu8),
244
87
        }?;
245
246
1.03M
        match field_type {
247
123k
            TType::Stop => Ok(
248
123k
                TFieldIdentifier::new::<Option<String>, String, Option<i16>>(
249
123k
                    None,
250
123k
                    TType::Stop,
251
123k
                    None,
252
123k
                ),
253
123k
            ),
254
            _ => {
255
907k
                if field_delta != 0 {
256
255k
                    self.last_read_field_id = self
257
255k
                        .last_read_field_id
258
255k
                        .checked_add(field_delta as i16)
259
255k
                        .ok_or_else(|| {
260
                            crate::Error::Protocol(ProtocolError::new(
261
                                ProtocolErrorKind::InvalidData,
262
                                "field id overflow",
263
                            ))
264
1
                        })?;
265
                } else {
266
652k
                    self.last_read_field_id = self.read_i16()?;
267
                };
268
269
907k
                Ok(TFieldIdentifier {
270
907k
                    name: None,
271
907k
                    field_type,
272
907k
                    id: Some(self.last_read_field_id),
273
907k
                })
274
            }
275
        }
276
1.03M
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_field_begin
Line
Count
Source
228
2.47M
    fn read_field_begin(&mut self) -> crate::Result<TFieldIdentifier> {
229
        // we can read at least one byte, which is:
230
        // - the type
231
        // - the field delta and the type
232
2.47M
        let field_type = self.read_byte()?;
233
2.46M
        let field_delta = (field_type & 0xF0) >> 4;
234
2.46M
        let field_type = match field_type & 0x0F {
235
            0x01 => {
236
106k
                self.pending_read_bool_value = Some(true);
237
106k
                Ok(TType::Bool)
238
            }
239
            0x02 => {
240
522k
                self.pending_read_bool_value = Some(false);
241
522k
                Ok(TType::Bool)
242
            }
243
1.83M
            ttu8 => u8_to_type(ttu8),
244
79
        }?;
245
246
2.46M
        match field_type {
247
857k
            TType::Stop => Ok(
248
857k
                TFieldIdentifier::new::<Option<String>, String, Option<i16>>(
249
857k
                    None,
250
857k
                    TType::Stop,
251
857k
                    None,
252
857k
                ),
253
857k
            ),
254
            _ => {
255
1.61M
                if field_delta != 0 {
256
677k
                    self.last_read_field_id = self
257
677k
                        .last_read_field_id
258
677k
                        .checked_add(field_delta as i16)
259
677k
                        .ok_or_else(|| {
260
                            crate::Error::Protocol(ProtocolError::new(
261
                                ProtocolErrorKind::InvalidData,
262
                                "field id overflow",
263
                            ))
264
2
                        })?;
265
                } else {
266
933k
                    self.last_read_field_id = self.read_i16()?;
267
                };
268
269
1.61M
                Ok(TFieldIdentifier {
270
1.61M
                    name: None,
271
1.61M
                    field_type,
272
1.61M
                    id: Some(self.last_read_field_id),
273
1.61M
                })
274
            }
275
        }
276
2.47M
    }
277
278
2.11M
    fn read_field_end(&mut self) -> crate::Result<()> {
279
2.11M
        Ok(())
280
2.11M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_field_end
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_field_end
Line
Count
Source
278
640k
    fn read_field_end(&mut self) -> crate::Result<()> {
279
640k
        Ok(())
280
640k
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_field_end
Line
Count
Source
278
1.47M
    fn read_field_end(&mut self) -> crate::Result<()> {
279
1.47M
        Ok(())
280
1.47M
    }
281
282
581k
    fn read_bool(&mut self) -> crate::Result<bool> {
283
581k
        match self.pending_read_bool_value.take() {
284
578k
            Some(b) => Ok(b),
285
            None => {
286
3.91k
                let b = self.read_byte()?;
287
3.85k
                match b {
288
                    // Previous versions of the thrift compact protocol specification said to use 0
289
                    // and 1 inside collections, but that differed from existing implementations.
290
                    // The specification was updated in https://github.com/apache/thrift/commit/2c29c5665bc442e703480bb0ee60fe925ffe02e8.
291
871
                    0x00 => Ok(false),
292
466
                    0x01 => Ok(true),
293
2.45k
                    0x02 => Ok(false),
294
60
                    unkn => Err(crate::Error::Protocol(crate::ProtocolError {
295
60
                        kind: crate::ProtocolErrorKind::InvalidData,
296
60
                        message: format!("cannot convert {} into bool", unkn),
297
60
                    })),
298
                }
299
            }
300
        }
301
581k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_bool
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_bool
Line
Count
Source
282
104k
    fn read_bool(&mut self) -> crate::Result<bool> {
283
104k
        match self.pending_read_bool_value.take() {
284
103k
            Some(b) => Ok(b),
285
            None => {
286
1.15k
                let b = self.read_byte()?;
287
1.12k
                match b {
288
                    // Previous versions of the thrift compact protocol specification said to use 0
289
                    // and 1 inside collections, but that differed from existing implementations.
290
                    // The specification was updated in https://github.com/apache/thrift/commit/2c29c5665bc442e703480bb0ee60fe925ffe02e8.
291
410
                    0x00 => Ok(false),
292
218
                    0x01 => Ok(true),
293
468
                    0x02 => Ok(false),
294
27
                    unkn => Err(crate::Error::Protocol(crate::ProtocolError {
295
27
                        kind: crate::ProtocolErrorKind::InvalidData,
296
27
                        message: format!("cannot convert {} into bool", unkn),
297
27
                    })),
298
                }
299
            }
300
        }
301
104k
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_bool
Line
Count
Source
282
477k
    fn read_bool(&mut self) -> crate::Result<bool> {
283
477k
        match self.pending_read_bool_value.take() {
284
474k
            Some(b) => Ok(b),
285
            None => {
286
2.75k
                let b = self.read_byte()?;
287
2.73k
                match b {
288
                    // Previous versions of the thrift compact protocol specification said to use 0
289
                    // and 1 inside collections, but that differed from existing implementations.
290
                    // The specification was updated in https://github.com/apache/thrift/commit/2c29c5665bc442e703480bb0ee60fe925ffe02e8.
291
461
                    0x00 => Ok(false),
292
248
                    0x01 => Ok(true),
293
1.99k
                    0x02 => Ok(false),
294
33
                    unkn => Err(crate::Error::Protocol(crate::ProtocolError {
295
33
                        kind: crate::ProtocolErrorKind::InvalidData,
296
33
                        message: format!("cannot convert {} into bool", unkn),
297
33
                    })),
298
                }
299
            }
300
        }
301
477k
    }
302
303
7.34M
    fn read_bytes(&mut self) -> crate::Result<Vec<u8>> {
304
7.34M
        let len = self.read_varint32()?;
305
306
7.34M
        if let Some(max_size) = self.config.max_string_size() {
307
7.34M
            if len as usize > max_size {
308
143
                return Err(crate::Error::Protocol(ProtocolError::new(
309
143
                    ProtocolErrorKind::SizeLimit,
310
143
                    format!(
311
143
                        "Byte array size {} exceeds maximum allowed size of {}",
312
143
                        len, max_size
313
143
                    ),
314
143
                )));
315
7.34M
            }
316
0
        }
317
318
7.34M
        let mut buf = vec![0u8; len as usize];
319
7.34M
        self.transport
320
7.34M
            .read_exact(&mut buf)
321
7.34M
            .map_err(From::from)
322
7.34M
            .map(|_| buf)
323
7.34M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_bytes
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_bytes
Line
Count
Source
303
2.93M
    fn read_bytes(&mut self) -> crate::Result<Vec<u8>> {
304
2.93M
        let len = self.read_varint32()?;
305
306
2.93M
        if let Some(max_size) = self.config.max_string_size() {
307
2.93M
            if len as usize > max_size {
308
65
                return Err(crate::Error::Protocol(ProtocolError::new(
309
65
                    ProtocolErrorKind::SizeLimit,
310
65
                    format!(
311
65
                        "Byte array size {} exceeds maximum allowed size of {}",
312
65
                        len, max_size
313
65
                    ),
314
65
                )));
315
2.93M
            }
316
0
        }
317
318
2.93M
        let mut buf = vec![0u8; len as usize];
319
2.93M
        self.transport
320
2.93M
            .read_exact(&mut buf)
321
2.93M
            .map_err(From::from)
322
2.93M
            .map(|_| buf)
323
2.93M
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_bytes
Line
Count
Source
303
4.41M
    fn read_bytes(&mut self) -> crate::Result<Vec<u8>> {
304
4.41M
        let len = self.read_varint32()?;
305
306
4.41M
        if let Some(max_size) = self.config.max_string_size() {
307
4.41M
            if len as usize > max_size {
308
78
                return Err(crate::Error::Protocol(ProtocolError::new(
309
78
                    ProtocolErrorKind::SizeLimit,
310
78
                    format!(
311
78
                        "Byte array size {} exceeds maximum allowed size of {}",
312
78
                        len, max_size
313
78
                    ),
314
78
                )));
315
4.41M
            }
316
0
        }
317
318
4.41M
        let mut buf = vec![0u8; len as usize];
319
4.41M
        self.transport
320
4.41M
            .read_exact(&mut buf)
321
4.41M
            .map_err(From::from)
322
4.41M
            .map(|_| buf)
323
4.41M
    }
324
325
83.1k
    fn read_i8(&mut self) -> crate::Result<i8> {
326
83.1k
        self.read_byte().map(|i| i as i8)
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_i8::{closure#0}
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_i8::{closure#0}
Line
Count
Source
326
38.4k
        self.read_byte().map(|i| i as i8)
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_i8::{closure#0}
Line
Count
Source
326
44.6k
        self.read_byte().map(|i| i as i8)
327
83.1k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_i8
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_i8
Line
Count
Source
325
38.5k
    fn read_i8(&mut self) -> crate::Result<i8> {
326
38.5k
        self.read_byte().map(|i| i as i8)
327
38.5k
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_i8
Line
Count
Source
325
44.6k
    fn read_i8(&mut self) -> crate::Result<i8> {
326
44.6k
        self.read_byte().map(|i| i as i8)
327
44.6k
    }
328
329
1.69M
    fn read_i16(&mut self) -> crate::Result<i16> {
330
1.69M
        Ok(zigzag_to_i32(self.read_varint32()?) as i16)
331
1.69M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_i16
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_i16
Line
Count
Source
329
720k
    fn read_i16(&mut self) -> crate::Result<i16> {
330
720k
        Ok(zigzag_to_i32(self.read_varint32()?) as i16)
331
720k
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_i16
Line
Count
Source
329
979k
    fn read_i16(&mut self) -> crate::Result<i16> {
330
979k
        Ok(zigzag_to_i32(self.read_varint32()?) as i16)
331
979k
    }
332
333
3.82M
    fn read_i32(&mut self) -> crate::Result<i32> {
334
3.82M
        Ok(zigzag_to_i32(self.read_varint32()?))
335
3.82M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_i32
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_i32
Line
Count
Source
333
1.26M
    fn read_i32(&mut self) -> crate::Result<i32> {
334
1.26M
        Ok(zigzag_to_i32(self.read_varint32()?))
335
1.26M
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_i32
Line
Count
Source
333
2.56M
    fn read_i32(&mut self) -> crate::Result<i32> {
334
2.56M
        Ok(zigzag_to_i32(self.read_varint32()?))
335
2.56M
    }
336
337
2.94M
    fn read_i64(&mut self) -> crate::Result<i64> {
338
2.94M
        Ok(zigzag_to_i64(self.read_varint64()?))
339
2.94M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_i64
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_i64
Line
Count
Source
337
1.31M
    fn read_i64(&mut self) -> crate::Result<i64> {
338
1.31M
        Ok(zigzag_to_i64(self.read_varint64()?))
339
1.31M
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_i64
Line
Count
Source
337
1.62M
    fn read_i64(&mut self) -> crate::Result<i64> {
338
1.62M
        Ok(zigzag_to_i64(self.read_varint64()?))
339
1.62M
    }
340
341
27.0k
    fn read_double(&mut self) -> crate::Result<f64> {
342
27.0k
        self.transport
343
27.0k
            .read_f64::<LittleEndian>()
344
27.0k
            .map_err(From::from)
345
27.0k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_double
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_double
Line
Count
Source
341
9.55k
    fn read_double(&mut self) -> crate::Result<f64> {
342
9.55k
        self.transport
343
9.55k
            .read_f64::<LittleEndian>()
344
9.55k
            .map_err(From::from)
345
9.55k
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_double
Line
Count
Source
341
17.4k
    fn read_double(&mut self) -> crate::Result<f64> {
342
17.4k
        self.transport
343
17.4k
            .read_f64::<LittleEndian>()
344
17.4k
            .map_err(From::from)
345
17.4k
    }
346
347
283k
    fn read_uuid(&mut self) -> crate::Result<uuid::Uuid> {
348
283k
        let mut buf = [0u8; 16];
349
283k
        self.transport
350
283k
            .read_exact(&mut buf)
351
283k
            .map(|_| uuid::Uuid::from_bytes(buf))
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_uuid::{closure#0}
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_uuid::{closure#0}
Line
Count
Source
351
4.32k
            .map(|_| uuid::Uuid::from_bytes(buf))
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_uuid::{closure#0}
Line
Count
Source
351
279k
            .map(|_| uuid::Uuid::from_bytes(buf))
352
283k
            .map_err(From::from)
353
283k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_uuid
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_uuid
Line
Count
Source
347
4.36k
    fn read_uuid(&mut self) -> crate::Result<uuid::Uuid> {
348
4.36k
        let mut buf = [0u8; 16];
349
4.36k
        self.transport
350
4.36k
            .read_exact(&mut buf)
351
4.36k
            .map(|_| uuid::Uuid::from_bytes(buf))
352
4.36k
            .map_err(From::from)
353
4.36k
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_uuid
Line
Count
Source
347
279k
    fn read_uuid(&mut self) -> crate::Result<uuid::Uuid> {
348
279k
        let mut buf = [0u8; 16];
349
279k
        self.transport
350
279k
            .read_exact(&mut buf)
351
279k
            .map(|_| uuid::Uuid::from_bytes(buf))
352
279k
            .map_err(From::from)
353
279k
    }
354
355
7.28M
    fn read_string(&mut self) -> crate::Result<String> {
356
7.28M
        let bytes = self.read_bytes()?;
357
7.28M
        String::from_utf8(bytes).map_err(From::from)
358
7.28M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_string
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_string
Line
Count
Source
355
2.91M
    fn read_string(&mut self) -> crate::Result<String> {
356
2.91M
        let bytes = self.read_bytes()?;
357
2.91M
        String::from_utf8(bytes).map_err(From::from)
358
2.91M
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_string
Line
Count
Source
355
4.37M
    fn read_string(&mut self) -> crate::Result<String> {
356
4.37M
        let bytes = self.read_bytes()?;
357
4.37M
        String::from_utf8(bytes).map_err(From::from)
358
4.37M
    }
359
360
2.43M
    fn read_list_begin(&mut self) -> crate::Result<TListIdentifier> {
361
2.43M
        let (element_type, element_count) = self.read_list_set_begin()?;
362
2.43M
        Ok(TListIdentifier::new(element_type, element_count))
363
2.43M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_list_begin
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_list_begin
Line
Count
Source
360
1.12M
    fn read_list_begin(&mut self) -> crate::Result<TListIdentifier> {
361
1.12M
        let (element_type, element_count) = self.read_list_set_begin()?;
362
1.12M
        Ok(TListIdentifier::new(element_type, element_count))
363
1.12M
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_list_begin
Line
Count
Source
360
1.30M
    fn read_list_begin(&mut self) -> crate::Result<TListIdentifier> {
361
1.30M
        let (element_type, element_count) = self.read_list_set_begin()?;
362
1.30M
        Ok(TListIdentifier::new(element_type, element_count))
363
1.30M
    }
364
365
2.42M
    fn read_list_end(&mut self) -> crate::Result<()> {
366
2.42M
        Ok(())
367
2.42M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_list_end
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_list_end
Line
Count
Source
365
1.12M
    fn read_list_end(&mut self) -> crate::Result<()> {
366
1.12M
        Ok(())
367
1.12M
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_list_end
Line
Count
Source
365
1.30M
    fn read_list_end(&mut self) -> crate::Result<()> {
366
1.30M
        Ok(())
367
1.30M
    }
368
369
160k
    fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier> {
370
160k
        let (element_type, element_count) = self.read_list_set_begin()?;
371
160k
        Ok(TSetIdentifier::new(element_type, element_count))
372
160k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_set_begin
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_set_begin
Line
Count
Source
369
54.1k
    fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier> {
370
54.1k
        let (element_type, element_count) = self.read_list_set_begin()?;
371
54.1k
        Ok(TSetIdentifier::new(element_type, element_count))
372
54.1k
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_set_begin
Line
Count
Source
369
106k
    fn read_set_begin(&mut self) -> crate::Result<TSetIdentifier> {
370
106k
        let (element_type, element_count) = self.read_list_set_begin()?;
371
106k
        Ok(TSetIdentifier::new(element_type, element_count))
372
106k
    }
373
374
158k
    fn read_set_end(&mut self) -> crate::Result<()> {
375
158k
        Ok(())
376
158k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_set_end
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_set_end
Line
Count
Source
374
53.0k
    fn read_set_end(&mut self) -> crate::Result<()> {
375
53.0k
        Ok(())
376
53.0k
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_set_end
Line
Count
Source
374
105k
    fn read_set_end(&mut self) -> crate::Result<()> {
375
105k
        Ok(())
376
105k
    }
377
378
101k
    fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier> {
379
101k
        let element_count = self.read_varint32()? as i32;
380
101k
        if element_count == 0 {
381
11.4k
            Ok(TMapIdentifier::new(None, None, 0))
382
        } else {
383
90.2k
            let type_header = self.read_byte()?;
384
90.0k
            let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
385
90.0k
            let val_type = collection_u8_to_type(type_header & 0x0F)?;
386
387
90.0k
            let key_min_size = self.min_serialized_size(key_type);
388
90.0k
            let value_min_size = self.min_serialized_size(val_type);
389
90.0k
            let element_size = key_min_size + value_min_size;
390
90.0k
            super::check_container_size(&self.config, element_count, element_size)?;
391
392
89.9k
            Ok(TMapIdentifier::new(key_type, val_type, element_count))
393
        }
394
101k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_map_begin
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_map_begin
Line
Count
Source
378
43.0k
    fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier> {
379
43.0k
        let element_count = self.read_varint32()? as i32;
380
42.9k
        if element_count == 0 {
381
4.37k
            Ok(TMapIdentifier::new(None, None, 0))
382
        } else {
383
38.5k
            let type_header = self.read_byte()?;
384
38.4k
            let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
385
38.4k
            let val_type = collection_u8_to_type(type_header & 0x0F)?;
386
387
38.4k
            let key_min_size = self.min_serialized_size(key_type);
388
38.4k
            let value_min_size = self.min_serialized_size(val_type);
389
38.4k
            let element_size = key_min_size + value_min_size;
390
38.4k
            super::check_container_size(&self.config, element_count, element_size)?;
391
392
38.3k
            Ok(TMapIdentifier::new(key_type, val_type, element_count))
393
        }
394
43.0k
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_map_begin
Line
Count
Source
378
58.8k
    fn read_map_begin(&mut self) -> crate::Result<TMapIdentifier> {
379
58.8k
        let element_count = self.read_varint32()? as i32;
380
58.7k
        if element_count == 0 {
381
7.05k
            Ok(TMapIdentifier::new(None, None, 0))
382
        } else {
383
51.6k
            let type_header = self.read_byte()?;
384
51.6k
            let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?;
385
51.6k
            let val_type = collection_u8_to_type(type_header & 0x0F)?;
386
387
51.6k
            let key_min_size = self.min_serialized_size(key_type);
388
51.6k
            let value_min_size = self.min_serialized_size(val_type);
389
51.6k
            let element_size = key_min_size + value_min_size;
390
51.6k
            super::check_container_size(&self.config, element_count, element_size)?;
391
392
51.5k
            Ok(TMapIdentifier::new(key_type, val_type, element_count))
393
        }
394
58.8k
    }
395
396
98.9k
    fn read_map_end(&mut self) -> crate::Result<()> {
397
98.9k
        Ok(())
398
98.9k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_map_end
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_map_end
Line
Count
Source
396
41.4k
    fn read_map_end(&mut self) -> crate::Result<()> {
397
41.4k
        Ok(())
398
41.4k
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_map_end
Line
Count
Source
396
57.5k
    fn read_map_end(&mut self) -> crate::Result<()> {
397
57.5k
        Ok(())
398
57.5k
    }
399
400
    // utility
401
    //
402
403
24.3M
    fn read_byte(&mut self) -> crate::Result<u8> {
404
24.3M
        let mut buf = [0u8; 1];
405
24.3M
        self.transport
406
24.3M
            .read_exact(&mut buf)
407
24.3M
            .map_err(From::from)
408
24.3M
            .map(|_| buf[0])
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_byte::{closure#0}
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_byte::{closure#0}
Line
Count
Source
408
9.50M
            .map(|_| buf[0])
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_byte::{closure#0}
Line
Count
Source
408
14.8M
            .map(|_| buf[0])
409
24.3M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::read_byte
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_byte
Line
Count
Source
403
9.50M
    fn read_byte(&mut self) -> crate::Result<u8> {
404
9.50M
        let mut buf = [0u8; 1];
405
9.50M
        self.transport
406
9.50M
            .read_exact(&mut buf)
407
9.50M
            .map_err(From::from)
408
9.50M
            .map(|_| buf[0])
409
9.50M
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::read_byte
Line
Count
Source
403
14.8M
    fn read_byte(&mut self) -> crate::Result<u8> {
404
14.8M
        let mut buf = [0u8; 1];
405
14.8M
        self.transport
406
14.8M
            .read_exact(&mut buf)
407
14.8M
            .map_err(From::from)
408
14.8M
            .map(|_| buf[0])
409
14.8M
    }
410
411
2.77M
    fn min_serialized_size(&self, field_type: TType) -> usize {
412
2.77M
        compact_protocol_min_serialized_size(field_type)
413
2.77M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactInputProtocol<alloc::boxed::Box<dyn thrift::transport::TReadTransport + core::marker::Send>> as thrift::protocol::TInputProtocol>::min_serialized_size
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::min_serialized_size
Line
Count
Source
411
1.25M
    fn min_serialized_size(&self, field_type: TType) -> usize {
412
1.25M
        compact_protocol_min_serialized_size(field_type)
413
1.25M
    }
<thrift::protocol::compact::TCompactInputProtocol<thrift::transport::mem::TBufferChannel> as thrift::protocol::TInputProtocol>::min_serialized_size
Line
Count
Source
411
1.51M
    fn min_serialized_size(&self, field_type: TType) -> usize {
412
1.51M
        compact_protocol_min_serialized_size(field_type)
413
1.51M
    }
414
}
415
416
2.77M
pub(crate) fn compact_protocol_min_serialized_size(field_type: TType) -> usize {
417
2.77M
    match field_type {
418
513k
        TType::Stop => 1,   // 1 byte
419
0
        TType::Void => 1,   // 1 byte
420
494k
        TType::Bool => 1,   // 1 byte
421
51.4k
        TType::I08 => 1,    // 1 byte
422
38.5k
        TType::Double => 8, // 8 bytes (not varint encoded)
423
264k
        TType::I16 => 1,    // 1 byte minimum (varint)
424
78.7k
        TType::I32 => 1,    // 1 byte minimum (varint)
425
423k
        TType::I64 => 1,    // 1 byte minimum (varint)
426
128k
        TType::String => 1, // 1 byte minimum for length (varint)
427
60.5k
        TType::Struct => 1, // 1 byte minimum (stop field)
428
13.4k
        TType::Map => 1,    // 1 byte minimum
429
234k
        TType::Set => 1,    // 1 byte minimum
430
375k
        TType::List => 1,   // 1 byte minimum
431
95.1k
        TType::Uuid => 16,  // 16 bytes
432
0
        TType::Utf7 => 1,   // 1 byte
433
    }
434
2.77M
}
435
436
#[inline]
437
5.52M
fn zigzag_to_i32(n: u32) -> i32 {
438
5.52M
    ((n >> 1) as i32) ^ (0i32.wrapping_sub((n & 1) as i32))
439
5.52M
}
Unexecuted instantiation: thrift::protocol::compact::zigzag_to_i32
thrift::protocol::compact::zigzag_to_i32
Line
Count
Source
437
1.98M
fn zigzag_to_i32(n: u32) -> i32 {
438
1.98M
    ((n >> 1) as i32) ^ (0i32.wrapping_sub((n & 1) as i32))
439
1.98M
}
thrift::protocol::compact::zigzag_to_i32
Line
Count
Source
437
3.54M
fn zigzag_to_i32(n: u32) -> i32 {
438
3.54M
    ((n >> 1) as i32) ^ (0i32.wrapping_sub((n & 1) as i32))
439
3.54M
}
440
441
#[inline]
442
2.94M
fn zigzag_to_i64(n: u64) -> i64 {
443
2.94M
    ((n >> 1) as i64) ^ (0i64.wrapping_sub((n & 1) as i64))
444
2.94M
}
Unexecuted instantiation: thrift::protocol::compact::zigzag_to_i64
thrift::protocol::compact::zigzag_to_i64
Line
Count
Source
442
1.31M
fn zigzag_to_i64(n: u64) -> i64 {
443
1.31M
    ((n >> 1) as i64) ^ (0i64.wrapping_sub((n & 1) as i64))
444
1.31M
}
thrift::protocol::compact::zigzag_to_i64
Line
Count
Source
442
1.62M
fn zigzag_to_i64(n: u64) -> i64 {
443
1.62M
    ((n >> 1) as i64) ^ (0i64.wrapping_sub((n & 1) as i64))
444
1.62M
}
445
446
impl<T> io::Seek for TCompactInputProtocol<T>
447
where
448
    T: io::Seek + TReadTransport,
449
{
450
    fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
451
        self.transport.seek(pos)
452
    }
453
}
454
455
/// Factory for creating instances of `TCompactInputProtocol`.
456
#[derive(Default)]
457
pub struct TCompactInputProtocolFactory;
458
459
impl TCompactInputProtocolFactory {
460
    /// Create a `TCompactInputProtocolFactory`.
461
0
    pub fn new() -> TCompactInputProtocolFactory {
462
0
        TCompactInputProtocolFactory {}
463
0
    }
464
}
465
466
impl TInputProtocolFactory for TCompactInputProtocolFactory {
467
0
    fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send> {
468
0
        Box::new(TCompactInputProtocol::new(transport))
469
0
    }
470
}
471
472
/// Write messages using the Thrift compact protocol.
473
///
474
/// # Examples
475
///
476
/// Create and use a `TCompactOutputProtocol`.
477
///
478
/// ```no_run
479
/// use thrift::protocol::{TCompactOutputProtocol, TOutputProtocol};
480
/// use thrift::transport::TTcpChannel;
481
///
482
/// let mut channel = TTcpChannel::new();
483
/// channel.open("localhost:9090").unwrap();
484
///
485
/// let mut protocol = TCompactOutputProtocol::new(channel);
486
///
487
/// protocol.write_bool(true).unwrap();
488
/// protocol.write_string("test_string").unwrap();
489
/// ```
490
#[derive(Debug)]
491
pub struct TCompactOutputProtocol<T>
492
where
493
    T: TWriteTransport,
494
{
495
    // Identifier of the last field serialized for a struct.
496
    last_write_field_id: i16,
497
    // Stack of the last written field ids (new entry added each time a nested struct is written).
498
    write_field_id_stack: Vec<i16>,
499
    // Field identifier of the boolean field to be written.
500
    // Saved because boolean fields and their value are encoded in a single byte
501
    pending_write_bool_field_identifier: Option<TFieldIdentifier>,
502
    // Underlying transport used for byte-level operations.
503
    transport: T,
504
    config: TConfiguration,
505
    recursion_depth: usize,
506
}
507
508
impl<T> TCompactOutputProtocol<T>
509
where
510
    T: TWriteTransport,
511
{
512
    /// Create a `TCompactOutputProtocol` that writes bytes to `transport`.
513
2.40k
    pub fn new(transport: T) -> TCompactOutputProtocol<T> {
514
2.40k
        Self::with_config(transport, TConfiguration::default())
515
2.40k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>>>::new
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel>>::new
Line
Count
Source
513
2.40k
    pub fn new(transport: T) -> TCompactOutputProtocol<T> {
514
2.40k
        Self::with_config(transport, TConfiguration::default())
515
2.40k
    }
516
517
2.40k
    pub fn with_config(transport: T, config: TConfiguration) -> TCompactOutputProtocol<T> {
518
2.40k
        TCompactOutputProtocol {
519
2.40k
            last_write_field_id: 0,
520
2.40k
            write_field_id_stack: Vec::new(),
521
2.40k
            pending_write_bool_field_identifier: None,
522
2.40k
            transport,
523
2.40k
            config,
524
2.40k
            recursion_depth: 0,
525
2.40k
        }
526
2.40k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>>>::with_config
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel>>::with_config
Line
Count
Source
517
2.40k
    pub fn with_config(transport: T, config: TConfiguration) -> TCompactOutputProtocol<T> {
518
2.40k
        TCompactOutputProtocol {
519
2.40k
            last_write_field_id: 0,
520
2.40k
            write_field_id_stack: Vec::new(),
521
2.40k
            pending_write_bool_field_identifier: None,
522
2.40k
            transport,
523
2.40k
            config,
524
2.40k
            recursion_depth: 0,
525
2.40k
        }
526
2.40k
    }
527
528
446k
    fn check_recursion_depth(&self) -> crate::Result<()> {
529
446k
        if let Some(limit) = self.config.max_recursion_depth() {
530
446k
            if self.recursion_depth >= limit {
531
0
                return Err(crate::Error::Protocol(ProtocolError::new(
532
0
                    ProtocolErrorKind::DepthLimit,
533
0
                    format!("Maximum recursion depth {} exceeded", limit),
534
0
                )));
535
446k
            }
536
0
        }
537
446k
        Ok(())
538
446k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>>>::check_recursion_depth
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel>>::check_recursion_depth
Line
Count
Source
528
446k
    fn check_recursion_depth(&self) -> crate::Result<()> {
529
446k
        if let Some(limit) = self.config.max_recursion_depth() {
530
446k
            if self.recursion_depth >= limit {
531
0
                return Err(crate::Error::Protocol(ProtocolError::new(
532
0
                    ProtocolErrorKind::DepthLimit,
533
0
                    format!("Maximum recursion depth {} exceeded", limit),
534
0
                )));
535
446k
            }
536
0
        }
537
446k
        Ok(())
538
446k
    }
539
540
    // FIXME: field_type as unconstrained u8 is bad
541
635k
    fn write_field_header(&mut self, field_type: u8, field_id: i16) -> crate::Result<()> {
542
635k
        let field_delta = field_id - self.last_write_field_id;
543
635k
        if field_delta > 0 && field_delta < 15 {
544
634k
            self.write_byte(((field_delta as u8) << 4) | field_type)?;
545
        } else {
546
999
            self.write_byte(field_type)?;
547
999
            self.write_i16(field_id)?;
548
        }
549
635k
        self.last_write_field_id = field_id;
550
635k
        Ok(())
551
635k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>>>::write_field_header
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel>>::write_field_header
Line
Count
Source
541
635k
    fn write_field_header(&mut self, field_type: u8, field_id: i16) -> crate::Result<()> {
542
635k
        let field_delta = field_id - self.last_write_field_id;
543
635k
        if field_delta > 0 && field_delta < 15 {
544
634k
            self.write_byte(((field_delta as u8) << 4) | field_type)?;
545
        } else {
546
999
            self.write_byte(field_type)?;
547
999
            self.write_i16(field_id)?;
548
        }
549
635k
        self.last_write_field_id = field_id;
550
635k
        Ok(())
551
635k
    }
552
553
41.1k
    fn write_list_set_begin(
554
41.1k
        &mut self,
555
41.1k
        element_type: TType,
556
41.1k
        element_count: i32,
557
41.1k
    ) -> crate::Result<()> {
558
41.1k
        let elem_identifier = collection_type_to_u8(element_type);
559
41.1k
        if element_count <= 14 {
560
38.6k
            let header = ((element_count as u8) << 4) | elem_identifier;
561
38.6k
            self.write_byte(header)
562
        } else {
563
2.50k
            let header = 0xF0 | elem_identifier;
564
2.50k
            self.write_byte(header)?;
565
            // element count is strictly positive as per the spec, so
566
            // cast i32 as u32 so that varint writing won't use zigzag encoding
567
2.50k
            self.transport
568
2.50k
                .write_varint(element_count as u32)
569
2.50k
                .map_err(From::from)
570
2.50k
                .map(|_| ())
571
        }
572
41.1k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>>>::write_list_set_begin
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel>>::write_list_set_begin
Line
Count
Source
553
41.1k
    fn write_list_set_begin(
554
41.1k
        &mut self,
555
41.1k
        element_type: TType,
556
41.1k
        element_count: i32,
557
41.1k
    ) -> crate::Result<()> {
558
41.1k
        let elem_identifier = collection_type_to_u8(element_type);
559
41.1k
        if element_count <= 14 {
560
38.6k
            let header = ((element_count as u8) << 4) | elem_identifier;
561
38.6k
            self.write_byte(header)
562
        } else {
563
2.50k
            let header = 0xF0 | elem_identifier;
564
2.50k
            self.write_byte(header)?;
565
            // element count is strictly positive as per the spec, so
566
            // cast i32 as u32 so that varint writing won't use zigzag encoding
567
2.50k
            self.transport
568
2.50k
                .write_varint(element_count as u32)
569
2.50k
                .map_err(From::from)
570
2.50k
                .map(|_| ())
571
        }
572
41.1k
    }
573
574
1.51M
    fn assert_no_pending_bool_write(&self) {
575
1.51M
        if let Some(ref f) = self.pending_write_bool_field_identifier {
576
0
            panic!("pending bool field {:?} not written", f)
577
1.51M
        }
578
1.51M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>>>::assert_no_pending_bool_write
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel>>::assert_no_pending_bool_write
Line
Count
Source
574
1.51M
    fn assert_no_pending_bool_write(&self) {
575
1.51M
        if let Some(ref f) = self.pending_write_bool_field_identifier {
576
0
            panic!("pending bool field {:?} not written", f)
577
1.51M
        }
578
1.51M
    }
579
}
580
581
impl<T> TOutputProtocol for TCompactOutputProtocol<T>
582
where
583
    T: TWriteTransport,
584
{
585
0
    fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> {
586
0
        self.write_byte(COMPACT_PROTOCOL_ID)?;
587
0
        self.write_byte((u8::from(identifier.message_type) << 5) | COMPACT_VERSION)?;
588
        // cast i32 as u32 so that varint writing won't use zigzag encoding
589
0
        self.transport
590
0
            .write_varint(identifier.sequence_number as u32)?;
591
0
        self.write_string(&identifier.name)?;
592
0
        Ok(())
593
0
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_message_begin
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_message_begin
594
595
0
    fn write_message_end(&mut self) -> crate::Result<()> {
596
0
        self.assert_no_pending_bool_write();
597
0
        Ok(())
598
0
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_message_end
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_message_end
599
600
446k
    fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> {
601
446k
        self.check_recursion_depth()?;
602
446k
        self.recursion_depth += 1;
603
446k
        self.write_field_id_stack.push(self.last_write_field_id);
604
446k
        self.last_write_field_id = 0;
605
446k
        Ok(())
606
446k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_struct_begin
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_struct_begin
Line
Count
Source
600
446k
    fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> {
601
446k
        self.check_recursion_depth()?;
602
446k
        self.recursion_depth += 1;
603
446k
        self.write_field_id_stack.push(self.last_write_field_id);
604
446k
        self.last_write_field_id = 0;
605
446k
        Ok(())
606
446k
    }
607
608
441k
    fn write_struct_end(&mut self) -> crate::Result<()> {
609
441k
        self.assert_no_pending_bool_write();
610
441k
        self.last_write_field_id = self
611
441k
            .write_field_id_stack
612
441k
            .pop()
613
441k
            .expect("should have previous field ids");
614
441k
        self.recursion_depth -= 1;
615
441k
        Ok(())
616
441k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_struct_end
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_struct_end
Line
Count
Source
608
441k
    fn write_struct_end(&mut self) -> crate::Result<()> {
609
441k
        self.assert_no_pending_bool_write();
610
441k
        self.last_write_field_id = self
611
441k
            .write_field_id_stack
612
441k
            .pop()
613
441k
            .expect("should have previous field ids");
614
441k
        self.recursion_depth -= 1;
615
441k
        Ok(())
616
441k
    }
617
618
635k
    fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> {
619
635k
        match identifier.field_type {
620
            TType::Bool => {
621
19.4k
                if self.pending_write_bool_field_identifier.is_some() {
622
0
                    panic!(
623
0
                        "should not have a pending bool while writing another bool with id: \
624
0
                         {:?}",
625
                        identifier
626
                    )
627
19.4k
                }
628
19.4k
                self.pending_write_bool_field_identifier = Some(identifier.clone());
629
19.4k
                Ok(())
630
            }
631
            _ => {
632
615k
                let field_type = type_to_u8(identifier.field_type);
633
615k
                let field_id = identifier.id.expect("non-stop field should have field id");
634
615k
                self.write_field_header(field_type, field_id)
635
            }
636
        }
637
635k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_field_begin
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_field_begin
Line
Count
Source
618
635k
    fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> {
619
635k
        match identifier.field_type {
620
            TType::Bool => {
621
19.4k
                if self.pending_write_bool_field_identifier.is_some() {
622
0
                    panic!(
623
0
                        "should not have a pending bool while writing another bool with id: \
624
0
                         {:?}",
625
                        identifier
626
                    )
627
19.4k
                }
628
19.4k
                self.pending_write_bool_field_identifier = Some(identifier.clone());
629
19.4k
                Ok(())
630
            }
631
            _ => {
632
615k
                let field_type = type_to_u8(identifier.field_type);
633
615k
                let field_id = identifier.id.expect("non-stop field should have field id");
634
615k
                self.write_field_header(field_type, field_id)
635
            }
636
        }
637
635k
    }
638
639
629k
    fn write_field_end(&mut self) -> crate::Result<()> {
640
629k
        self.assert_no_pending_bool_write();
641
629k
        Ok(())
642
629k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_field_end
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_field_end
Line
Count
Source
639
629k
    fn write_field_end(&mut self) -> crate::Result<()> {
640
629k
        self.assert_no_pending_bool_write();
641
629k
        Ok(())
642
629k
    }
643
644
441k
    fn write_field_stop(&mut self) -> crate::Result<()> {
645
441k
        self.assert_no_pending_bool_write();
646
441k
        self.write_byte(type_to_u8(TType::Stop))
647
441k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_field_stop
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_field_stop
Line
Count
Source
644
441k
    fn write_field_stop(&mut self) -> crate::Result<()> {
645
441k
        self.assert_no_pending_bool_write();
646
441k
        self.write_byte(type_to_u8(TType::Stop))
647
441k
    }
648
649
19.4k
    fn write_bool(&mut self, b: bool) -> crate::Result<()> {
650
19.4k
        match self.pending_write_bool_field_identifier.take() {
651
19.4k
            Some(pending) => {
652
19.4k
                let field_id = pending.id.expect("bool field should have a field id");
653
19.4k
                let field_type_as_u8 = if b { 0x01 } else { 0x02 };
654
19.4k
                self.write_field_header(field_type_as_u8, field_id)
655
            }
656
            None => {
657
0
                if b {
658
0
                    self.write_byte(0x01)
659
                } else {
660
0
                    self.write_byte(0x02)
661
                }
662
            }
663
        }
664
19.4k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_bool
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_bool
Line
Count
Source
649
19.4k
    fn write_bool(&mut self, b: bool) -> crate::Result<()> {
650
19.4k
        match self.pending_write_bool_field_identifier.take() {
651
19.4k
            Some(pending) => {
652
19.4k
                let field_id = pending.id.expect("bool field should have a field id");
653
19.4k
                let field_type_as_u8 = if b { 0x01 } else { 0x02 };
654
19.4k
                self.write_field_header(field_type_as_u8, field_id)
655
            }
656
            None => {
657
0
                if b {
658
0
                    self.write_byte(0x01)
659
                } else {
660
0
                    self.write_byte(0x02)
661
                }
662
            }
663
        }
664
19.4k
    }
665
666
86.0k
    fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> {
667
        // length is strictly positive as per the spec, so
668
        // cast i32 as u32 so that varint writing won't use zigzag encoding
669
86.0k
        self.transport.write_varint(b.len() as u32)?;
670
85.7k
        self.transport.write_all(b).map_err(From::from)
671
86.0k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_bytes
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_bytes
Line
Count
Source
666
86.0k
    fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> {
667
        // length is strictly positive as per the spec, so
668
        // cast i32 as u32 so that varint writing won't use zigzag encoding
669
86.0k
        self.transport.write_varint(b.len() as u32)?;
670
85.7k
        self.transport.write_all(b).map_err(From::from)
671
86.0k
    }
672
673
17.9k
    fn write_i8(&mut self, i: i8) -> crate::Result<()> {
674
17.9k
        self.write_byte(i as u8)
675
17.9k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_i8
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_i8
Line
Count
Source
673
17.9k
    fn write_i8(&mut self, i: i8) -> crate::Result<()> {
674
17.9k
        self.write_byte(i as u8)
675
17.9k
    }
676
677
18.9k
    fn write_i16(&mut self, i: i16) -> crate::Result<()> {
678
18.9k
        self.transport
679
18.9k
            .write_varint(i)
680
18.9k
            .map_err(From::from)
681
18.9k
            .map(|_| ())
682
18.9k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_i16
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_i16
Line
Count
Source
677
18.9k
    fn write_i16(&mut self, i: i16) -> crate::Result<()> {
678
18.9k
        self.transport
679
18.9k
            .write_varint(i)
680
18.9k
            .map_err(From::from)
681
18.9k
            .map(|_| ())
682
18.9k
    }
683
684
475k
    fn write_i32(&mut self, i: i32) -> crate::Result<()> {
685
475k
        self.transport
686
475k
            .write_varint(i)
687
475k
            .map_err(From::from)
688
475k
            .map(|_| ())
689
475k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_i32
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_i32
Line
Count
Source
684
475k
    fn write_i32(&mut self, i: i32) -> crate::Result<()> {
685
475k
        self.transport
686
475k
            .write_varint(i)
687
475k
            .map_err(From::from)
688
475k
            .map(|_| ())
689
475k
    }
690
691
36.5k
    fn write_i64(&mut self, i: i64) -> crate::Result<()> {
692
36.5k
        self.transport
693
36.5k
            .write_varint(i)
694
36.5k
            .map_err(From::from)
695
36.5k
            .map(|_| ())
696
36.5k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_i64
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_i64
Line
Count
Source
691
36.5k
    fn write_i64(&mut self, i: i64) -> crate::Result<()> {
692
36.5k
        self.transport
693
36.5k
            .write_varint(i)
694
36.5k
            .map_err(From::from)
695
36.5k
            .map(|_| ())
696
36.5k
    }
697
698
17.8k
    fn write_double(&mut self, d: f64) -> crate::Result<()> {
699
17.8k
        self.transport
700
17.8k
            .write_f64::<LittleEndian>(d)
701
17.8k
            .map_err(From::from)
702
17.8k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_double
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_double
Line
Count
Source
698
17.8k
    fn write_double(&mut self, d: f64) -> crate::Result<()> {
699
17.8k
        self.transport
700
17.8k
            .write_f64::<LittleEndian>(d)
701
17.8k
            .map_err(From::from)
702
17.8k
    }
703
704
17.0k
    fn write_uuid(&mut self, uuid: &uuid::Uuid) -> crate::Result<()> {
705
17.0k
        self.transport
706
17.0k
            .write_all(uuid.as_bytes())
707
17.0k
            .map_err(From::from)
708
17.0k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_uuid
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_uuid
Line
Count
Source
704
17.0k
    fn write_uuid(&mut self, uuid: &uuid::Uuid) -> crate::Result<()> {
705
17.0k
        self.transport
706
17.0k
            .write_all(uuid.as_bytes())
707
17.0k
            .map_err(From::from)
708
17.0k
    }
709
710
67.9k
    fn write_string(&mut self, s: &str) -> crate::Result<()> {
711
67.9k
        self.write_bytes(s.as_bytes())
712
67.9k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_string
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_string
Line
Count
Source
710
67.9k
    fn write_string(&mut self, s: &str) -> crate::Result<()> {
711
67.9k
        self.write_bytes(s.as_bytes())
712
67.9k
    }
713
714
38.3k
    fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> {
715
38.3k
        self.write_list_set_begin(identifier.element_type, identifier.size)
716
38.3k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_list_begin
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_list_begin
Line
Count
Source
714
38.3k
    fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> {
715
38.3k
        self.write_list_set_begin(identifier.element_type, identifier.size)
716
38.3k
    }
717
718
37.5k
    fn write_list_end(&mut self) -> crate::Result<()> {
719
37.5k
        Ok(())
720
37.5k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_list_end
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_list_end
Line
Count
Source
718
37.5k
    fn write_list_end(&mut self) -> crate::Result<()> {
719
37.5k
        Ok(())
720
37.5k
    }
721
722
2.72k
    fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> {
723
2.72k
        self.write_list_set_begin(identifier.element_type, identifier.size)
724
2.72k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_set_begin
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_set_begin
Line
Count
Source
722
2.72k
    fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> {
723
2.72k
        self.write_list_set_begin(identifier.element_type, identifier.size)
724
2.72k
    }
725
726
2.61k
    fn write_set_end(&mut self) -> crate::Result<()> {
727
2.61k
        Ok(())
728
2.61k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_set_end
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_set_end
Line
Count
Source
726
2.61k
    fn write_set_end(&mut self) -> crate::Result<()> {
727
2.61k
        Ok(())
728
2.61k
    }
729
730
2.94k
    fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> {
731
2.94k
        if identifier.size == 0 {
732
2.27k
            self.write_byte(0)
733
        } else {
734
            // element count is strictly positive as per the spec, so
735
            // cast i32 as u32 so that varint writing won't use zigzag encoding
736
678
            self.transport.write_varint(identifier.size as u32)?;
737
738
671
            let key_type = identifier
739
671
                .key_type
740
671
                .expect("map identifier to write should contain key type");
741
671
            let key_type_byte = collection_type_to_u8(key_type) << 4;
742
743
671
            let val_type = identifier
744
671
                .value_type
745
671
                .expect("map identifier to write should contain value type");
746
671
            let val_type_byte = collection_type_to_u8(val_type);
747
748
671
            let map_type_header = key_type_byte | val_type_byte;
749
671
            self.write_byte(map_type_header)
750
        }
751
2.94k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_map_begin
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_map_begin
Line
Count
Source
730
2.94k
    fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> {
731
2.94k
        if identifier.size == 0 {
732
2.27k
            self.write_byte(0)
733
        } else {
734
            // element count is strictly positive as per the spec, so
735
            // cast i32 as u32 so that varint writing won't use zigzag encoding
736
678
            self.transport.write_varint(identifier.size as u32)?;
737
738
671
            let key_type = identifier
739
671
                .key_type
740
671
                .expect("map identifier to write should contain key type");
741
671
            let key_type_byte = collection_type_to_u8(key_type) << 4;
742
743
671
            let val_type = identifier
744
671
                .value_type
745
671
                .expect("map identifier to write should contain value type");
746
671
            let val_type_byte = collection_type_to_u8(val_type);
747
748
671
            let map_type_header = key_type_byte | val_type_byte;
749
671
            self.write_byte(map_type_header)
750
        }
751
2.94k
    }
752
753
2.83k
    fn write_map_end(&mut self) -> crate::Result<()> {
754
2.83k
        Ok(())
755
2.83k
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_map_end
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_map_end
Line
Count
Source
753
2.83k
    fn write_map_end(&mut self) -> crate::Result<()> {
754
2.83k
        Ok(())
755
2.83k
    }
756
757
773
    fn flush(&mut self) -> crate::Result<()> {
758
773
        self.transport.flush().map_err(From::from)
759
773
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::flush
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::flush
Line
Count
Source
757
773
    fn flush(&mut self) -> crate::Result<()> {
758
773
        self.transport.flush().map_err(From::from)
759
773
    }
760
761
    // utility
762
    //
763
764
1.13M
    fn write_byte(&mut self, b: u8) -> crate::Result<()> {
765
1.13M
        self.transport.write(&[b]).map_err(From::from).map(|_| ())
766
1.13M
    }
Unexecuted instantiation: <thrift::protocol::compact::TCompactOutputProtocol<alloc::boxed::Box<dyn thrift::transport::TWriteTransport + core::marker::Send>> as thrift::protocol::TOutputProtocol>::write_byte
<thrift::protocol::compact::TCompactOutputProtocol<&mut thrift::transport::mem::TBufferChannel> as thrift::protocol::TOutputProtocol>::write_byte
Line
Count
Source
764
1.13M
    fn write_byte(&mut self, b: u8) -> crate::Result<()> {
765
1.13M
        self.transport.write(&[b]).map_err(From::from).map(|_| ())
766
1.13M
    }
767
}
768
769
/// Factory for creating instances of `TCompactOutputProtocol`.
770
#[derive(Default)]
771
pub struct TCompactOutputProtocolFactory;
772
773
impl TCompactOutputProtocolFactory {
774
    /// Create a `TCompactOutputProtocolFactory`.
775
0
    pub fn new() -> TCompactOutputProtocolFactory {
776
0
        TCompactOutputProtocolFactory {}
777
0
    }
778
}
779
780
impl TOutputProtocolFactory for TCompactOutputProtocolFactory {
781
0
    fn create(
782
0
        &self,
783
0
        transport: Box<dyn TWriteTransport + Send>,
784
0
    ) -> Box<dyn TOutputProtocol + Send> {
785
0
        Box::new(TCompactOutputProtocol::new(transport))
786
0
    }
787
}
788
789
42.4k
fn collection_type_to_u8(field_type: TType) -> u8 {
790
42.4k
    match field_type {
791
0
        TType::Bool => 0x01,
792
42.4k
        f => type_to_u8(f),
793
    }
794
42.4k
}
795
796
1.09M
fn type_to_u8(field_type: TType) -> u8 {
797
1.09M
    match field_type {
798
441k
        TType::Stop => 0x00,
799
17.9k
        TType::I08 => 0x03, // equivalent to TType::Byte
800
17.9k
        TType::I16 => 0x04,
801
466k
        TType::I32 => 0x05,
802
19.8k
        TType::I64 => 0x06,
803
17.8k
        TType::Double => 0x07,
804
38.0k
        TType::String => 0x08,
805
17.6k
        TType::List => 0x09,
806
2.72k
        TType::Set => 0x0A,
807
2.94k
        TType::Map => 0x0B,
808
39.7k
        TType::Struct => 0x0C,
809
17.0k
        TType::Uuid => 0x0D,
810
0
        _ => panic!("should not have attempted to convert {} to u8", field_type),
811
    }
812
1.09M
}
813
814
2.77M
fn collection_u8_to_type(b: u8) -> crate::Result<TType> {
815
2.77M
    match b {
816
        // For historical and compatibility reasons, a reader should be capable to deal with both cases.
817
        // The only valid value in the original spec was 2, but due to a widespread implementation bug
818
        // the defacto standard across large parts of the library became 1 instead.
819
        // As a result, both values are now allowed.
820
494k
        0x01 | 0x02 => Ok(TType::Bool),
821
2.27M
        o => u8_to_type(o),
822
    }
823
2.77M
}
824
825
4.95M
fn u8_to_type(b: u8) -> crate::Result<TType> {
826
4.95M
    match b {
827
1.49M
        0x00 => Ok(TType::Stop),
828
117k
        0x03 => Ok(TType::I08), // equivalent to TType::Byte
829
438k
        0x04 => Ok(TType::I16),
830
304k
        0x05 => Ok(TType::I32),
831
624k
        0x06 => Ok(TType::I64),
832
64.8k
        0x07 => Ok(TType::Double),
833
206k
        0x08 => Ok(TType::String),
834
773k
        0x09 => Ok(TType::List),
835
332k
        0x0A => Ok(TType::Set),
836
36.0k
        0x0B => Ok(TType::Map),
837
173k
        0x0C => Ok(TType::Struct),
838
386k
        0x0D => Ok(TType::Uuid),
839
223
        unkn => Err(crate::Error::Protocol(crate::ProtocolError {
840
223
            kind: crate::ProtocolErrorKind::InvalidData,
841
223
            message: format!("cannot convert {} into TType", unkn),
842
223
        })),
843
    }
844
4.95M
}
845
846
#[cfg(test)]
847
mod tests {
848
849
    use crate::protocol::{
850
        TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
851
        TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
852
    };
853
    use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
854
855
    use super::*;
856
857
    #[test]
858
    fn must_write_message_begin_largest_maximum_positive_sequence_number() {
859
        let (_, mut o_prot) = test_objects();
860
861
        assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
862
            "bar",
863
            TMessageType::Reply,
864
            i32::MAX
865
        )));
866
867
        #[rustfmt::skip]
868
        let expected: [u8; 11] = [
869
            0x82, /* protocol ID */
870
            0x41, /* message type | protocol version */
871
            0xFF,
872
            0xFF,
873
            0xFF,
874
            0xFF,
875
            0x07, /* non-zig-zag varint sequence number */
876
            0x03, /* message-name length */
877
            0x62,
878
            0x61,
879
            0x72 /* "bar" */,
880
        ];
881
882
        assert_eq_written_bytes!(o_prot, expected);
883
    }
884
885
    #[test]
886
    fn must_read_message_begin_largest_maximum_positive_sequence_number() {
887
        let (mut i_prot, _) = test_objects();
888
889
        #[rustfmt::skip]
890
        let source_bytes: [u8; 11] = [
891
            0x82, /* protocol ID */
892
            0x41, /* message type | protocol version */
893
            0xFF,
894
            0xFF,
895
            0xFF,
896
            0xFF,
897
            0x07, /* non-zig-zag varint sequence number */
898
            0x03, /* message-name length */
899
            0x62,
900
            0x61,
901
            0x72 /* "bar" */,
902
        ];
903
904
        i_prot.transport.set_readable_bytes(&source_bytes);
905
906
        let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MAX);
907
        let res = assert_success!(i_prot.read_message_begin());
908
909
        assert_eq!(&expected, &res);
910
    }
911
912
    #[test]
913
    fn must_write_message_begin_positive_sequence_number_0() {
914
        let (_, mut o_prot) = test_objects();
915
916
        assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
917
            "foo",
918
            TMessageType::Call,
919
            431
920
        )));
921
922
        #[rustfmt::skip]
923
        let expected: [u8; 8] = [
924
            0x82, /* protocol ID */
925
            0x21, /* message type | protocol version */
926
            0xAF,
927
            0x03, /* non-zig-zag varint sequence number */
928
            0x03, /* message-name length */
929
            0x66,
930
            0x6F,
931
            0x6F /* "foo" */,
932
        ];
933
934
        assert_eq_written_bytes!(o_prot, expected);
935
    }
936
937
    #[test]
938
    fn must_read_message_begin_positive_sequence_number_0() {
939
        let (mut i_prot, _) = test_objects();
940
941
        #[rustfmt::skip]
942
        let source_bytes: [u8; 8] = [
943
            0x82, /* protocol ID */
944
            0x21, /* message type | protocol version */
945
            0xAF,
946
            0x03, /* non-zig-zag varint sequence number */
947
            0x03, /* message-name length */
948
            0x66,
949
            0x6F,
950
            0x6F /* "foo" */,
951
        ];
952
953
        i_prot.transport.set_readable_bytes(&source_bytes);
954
955
        let expected = TMessageIdentifier::new("foo", TMessageType::Call, 431);
956
        let res = assert_success!(i_prot.read_message_begin());
957
958
        assert_eq!(&expected, &res);
959
    }
960
961
    #[test]
962
    fn must_write_message_begin_positive_sequence_number_1() {
963
        let (_, mut o_prot) = test_objects();
964
965
        assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
966
            "bar",
967
            TMessageType::Reply,
968
            991_828
969
        )));
970
971
        #[rustfmt::skip]
972
        let expected: [u8; 9] = [
973
            0x82, /* protocol ID */
974
            0x41, /* message type | protocol version */
975
            0xD4,
976
            0xC4,
977
            0x3C, /* non-zig-zag varint sequence number */
978
            0x03, /* message-name length */
979
            0x62,
980
            0x61,
981
            0x72 /* "bar" */,
982
        ];
983
984
        assert_eq_written_bytes!(o_prot, expected);
985
    }
986
987
    #[test]
988
    fn must_read_message_begin_positive_sequence_number_1() {
989
        let (mut i_prot, _) = test_objects();
990
991
        #[rustfmt::skip]
992
        let source_bytes: [u8; 9] = [
993
            0x82, /* protocol ID */
994
            0x41, /* message type | protocol version */
995
            0xD4,
996
            0xC4,
997
            0x3C, /* non-zig-zag varint sequence number */
998
            0x03, /* message-name length */
999
            0x62,
1000
            0x61,
1001
            0x72 /* "bar" */,
1002
        ];
1003
1004
        i_prot.transport.set_readable_bytes(&source_bytes);
1005
1006
        let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 991_828);
1007
        let res = assert_success!(i_prot.read_message_begin());
1008
1009
        assert_eq!(&expected, &res);
1010
    }
1011
1012
    #[test]
1013
    fn must_write_message_begin_zero_sequence_number() {
1014
        let (_, mut o_prot) = test_objects();
1015
1016
        assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1017
            "bar",
1018
            TMessageType::Reply,
1019
            0
1020
        )));
1021
1022
        #[rustfmt::skip]
1023
        let expected: [u8; 7] = [
1024
            0x82, /* protocol ID */
1025
            0x41, /* message type | protocol version */
1026
            0x00, /* non-zig-zag varint sequence number */
1027
            0x03, /* message-name length */
1028
            0x62,
1029
            0x61,
1030
            0x72 /* "bar" */,
1031
        ];
1032
1033
        assert_eq_written_bytes!(o_prot, expected);
1034
    }
1035
1036
    #[test]
1037
    fn must_read_message_begin_zero_sequence_number() {
1038
        let (mut i_prot, _) = test_objects();
1039
1040
        #[rustfmt::skip]
1041
        let source_bytes: [u8; 7] = [
1042
            0x82, /* protocol ID */
1043
            0x41, /* message type | protocol version */
1044
            0x00, /* non-zig-zag varint sequence number */
1045
            0x03, /* message-name length */
1046
            0x62,
1047
            0x61,
1048
            0x72 /* "bar" */,
1049
        ];
1050
1051
        i_prot.transport.set_readable_bytes(&source_bytes);
1052
1053
        let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 0);
1054
        let res = assert_success!(i_prot.read_message_begin());
1055
1056
        assert_eq!(&expected, &res);
1057
    }
1058
1059
    #[test]
1060
    fn must_write_message_begin_largest_minimum_negative_sequence_number() {
1061
        let (_, mut o_prot) = test_objects();
1062
1063
        assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1064
            "bar",
1065
            TMessageType::Reply,
1066
            i32::MIN
1067
        )));
1068
1069
        // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
1070
        #[rustfmt::skip]
1071
        let expected: [u8; 11] = [
1072
            0x82, /* protocol ID */
1073
            0x41, /* message type | protocol version */
1074
            0x80,
1075
            0x80,
1076
            0x80,
1077
            0x80,
1078
            0x08, /* non-zig-zag varint sequence number */
1079
            0x03, /* message-name length */
1080
            0x62,
1081
            0x61,
1082
            0x72 /* "bar" */,
1083
        ];
1084
1085
        assert_eq_written_bytes!(o_prot, expected);
1086
    }
1087
1088
    #[test]
1089
    fn must_read_message_begin_largest_minimum_negative_sequence_number() {
1090
        let (mut i_prot, _) = test_objects();
1091
1092
        // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000
1093
        #[rustfmt::skip]
1094
        let source_bytes: [u8; 11] = [
1095
            0x82, /* protocol ID */
1096
            0x41, /* message type | protocol version */
1097
            0x80,
1098
            0x80,
1099
            0x80,
1100
            0x80,
1101
            0x08, /* non-zig-zag varint sequence number */
1102
            0x03, /* message-name length */
1103
            0x62,
1104
            0x61,
1105
            0x72 /* "bar" */,
1106
        ];
1107
1108
        i_prot.transport.set_readable_bytes(&source_bytes);
1109
1110
        let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MIN);
1111
        let res = assert_success!(i_prot.read_message_begin());
1112
1113
        assert_eq!(&expected, &res);
1114
    }
1115
1116
    #[test]
1117
    fn must_write_message_begin_negative_sequence_number_0() {
1118
        let (_, mut o_prot) = test_objects();
1119
1120
        assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1121
            "foo",
1122
            TMessageType::Call,
1123
            -431
1124
        )));
1125
1126
        // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
1127
        #[rustfmt::skip]
1128
        let expected: [u8; 11] = [
1129
            0x82, /* protocol ID */
1130
            0x21, /* message type | protocol version */
1131
            0xD1,
1132
            0xFC,
1133
            0xFF,
1134
            0xFF,
1135
            0x0F, /* non-zig-zag varint sequence number */
1136
            0x03, /* message-name length */
1137
            0x66,
1138
            0x6F,
1139
            0x6F /* "foo" */,
1140
        ];
1141
1142
        assert_eq_written_bytes!(o_prot, expected);
1143
    }
1144
1145
    #[test]
1146
    fn must_read_message_begin_negative_sequence_number_0() {
1147
        let (mut i_prot, _) = test_objects();
1148
1149
        // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001
1150
        #[rustfmt::skip]
1151
        let source_bytes: [u8; 11] = [
1152
            0x82, /* protocol ID */
1153
            0x21, /* message type | protocol version */
1154
            0xD1,
1155
            0xFC,
1156
            0xFF,
1157
            0xFF,
1158
            0x0F, /* non-zig-zag varint sequence number */
1159
            0x03, /* message-name length */
1160
            0x66,
1161
            0x6F,
1162
            0x6F /* "foo" */,
1163
        ];
1164
1165
        i_prot.transport.set_readable_bytes(&source_bytes);
1166
1167
        let expected = TMessageIdentifier::new("foo", TMessageType::Call, -431);
1168
        let res = assert_success!(i_prot.read_message_begin());
1169
1170
        assert_eq!(&expected, &res);
1171
    }
1172
1173
    #[test]
1174
    fn must_write_message_begin_negative_sequence_number_1() {
1175
        let (_, mut o_prot) = test_objects();
1176
1177
        assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1178
            "foo",
1179
            TMessageType::Call,
1180
            -73_184_125
1181
        )));
1182
1183
        // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1184
        #[rustfmt::skip]
1185
        let expected: [u8; 11] = [
1186
            0x82, /* protocol ID */
1187
            0x21, /* message type | protocol version */
1188
            0x83,
1189
            0x99,
1190
            0x8D,
1191
            0xDD,
1192
            0x0F, /* non-zig-zag varint sequence number */
1193
            0x03, /* message-name length */
1194
            0x66,
1195
            0x6F,
1196
            0x6F /* "foo" */,
1197
        ];
1198
1199
        assert_eq_written_bytes!(o_prot, expected);
1200
    }
1201
1202
    #[test]
1203
    fn must_read_message_begin_negative_sequence_number_1() {
1204
        let (mut i_prot, _) = test_objects();
1205
1206
        // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011
1207
        #[rustfmt::skip]
1208
        let source_bytes: [u8; 11] = [
1209
            0x82, /* protocol ID */
1210
            0x21, /* message type | protocol version */
1211
            0x83,
1212
            0x99,
1213
            0x8D,
1214
            0xDD,
1215
            0x0F, /* non-zig-zag varint sequence number */
1216
            0x03, /* message-name length */
1217
            0x66,
1218
            0x6F,
1219
            0x6F /* "foo" */,
1220
        ];
1221
1222
        i_prot.transport.set_readable_bytes(&source_bytes);
1223
1224
        let expected = TMessageIdentifier::new("foo", TMessageType::Call, -73_184_125);
1225
        let res = assert_success!(i_prot.read_message_begin());
1226
1227
        assert_eq!(&expected, &res);
1228
    }
1229
1230
    #[test]
1231
    fn must_write_message_begin_negative_sequence_number_2() {
1232
        let (_, mut o_prot) = test_objects();
1233
1234
        assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
1235
            "foo",
1236
            TMessageType::Call,
1237
            -1_073_741_823
1238
        )));
1239
1240
        // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
1241
        #[rustfmt::skip]
1242
        let expected: [u8; 11] = [
1243
            0x82, /* protocol ID */
1244
            0x21, /* message type | protocol version */
1245
            0x81,
1246
            0x80,
1247
            0x80,
1248
            0x80,
1249
            0x0C, /* non-zig-zag varint sequence number */
1250
            0x03, /* message-name length */
1251
            0x66,
1252
            0x6F,
1253
            0x6F /* "foo" */,
1254
        ];
1255
1256
        assert_eq_written_bytes!(o_prot, expected);
1257
    }
1258
1259
    #[test]
1260
    fn must_read_message_begin_negative_sequence_number_2() {
1261
        let (mut i_prot, _) = test_objects();
1262
1263
        // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001
1264
        #[rustfmt::skip]
1265
        let source_bytes: [u8; 11] = [
1266
            0x82, /* protocol ID */
1267
            0x21, /* message type | protocol version */
1268
            0x81,
1269
            0x80,
1270
            0x80,
1271
            0x80,
1272
            0x0C, /* non-zig-zag varint sequence number */
1273
            0x03, /* message-name length */
1274
            0x66,
1275
            0x6F,
1276
            0x6F, /* "foo" */
1277
        ];
1278
1279
        i_prot.transport.set_readable_bytes(&source_bytes);
1280
1281
        let expected = TMessageIdentifier::new("foo", TMessageType::Call, -1_073_741_823);
1282
        let res = assert_success!(i_prot.read_message_begin());
1283
1284
        assert_eq!(&expected, &res);
1285
    }
1286
1287
    #[test]
1288
    fn must_round_trip_upto_i64_maxvalue() {
1289
        // See https://issues.apache.org/jira/browse/THRIFT-5131
1290
        for i in 0..64 {
1291
            let (mut i_prot, mut o_prot) = test_objects();
1292
            let val: i64 = ((1u64 << i) - 1) as i64;
1293
1294
            o_prot
1295
                .write_field_begin(&TFieldIdentifier::new("val", TType::I64, 1))
1296
                .unwrap();
1297
            o_prot.write_i64(val).unwrap();
1298
            o_prot.write_field_end().unwrap();
1299
            o_prot.flush().unwrap();
1300
1301
            copy_write_buffer_to_read_buffer!(o_prot);
1302
1303
            i_prot.read_field_begin().unwrap();
1304
            assert_eq!(val, i_prot.read_i64().unwrap());
1305
        }
1306
    }
1307
1308
    #[test]
1309
    fn must_round_trip_message_begin() {
1310
        let (mut i_prot, mut o_prot) = test_objects();
1311
1312
        let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948);
1313
1314
        assert_success!(o_prot.write_message_begin(&ident));
1315
1316
        copy_write_buffer_to_read_buffer!(o_prot);
1317
1318
        let res = assert_success!(i_prot.read_message_begin());
1319
        assert_eq!(&res, &ident);
1320
    }
1321
1322
    #[test]
1323
    fn must_write_message_end() {
1324
        assert_no_write(|o| o.write_message_end());
1325
    }
1326
1327
    // NOTE: structs and fields are tested together
1328
    //
1329
1330
    #[test]
1331
    fn must_write_struct_with_delta_fields() {
1332
        let (_, mut o_prot) = test_objects();
1333
1334
        // no bytes should be written however
1335
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1336
1337
        // write three fields with tiny field ids
1338
        // since they're small the field ids will be encoded as deltas
1339
1340
        // since this is the first field (and it's zero) it gets the full varint write
1341
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0)));
1342
        assert_success!(o_prot.write_field_end());
1343
1344
        // since this delta > 0 and < 15 it can be encoded as a delta
1345
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4)));
1346
        assert_success!(o_prot.write_field_end());
1347
1348
        // since this delta > 0 and < 15 it can be encoded as a delta
1349
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9)));
1350
        assert_success!(o_prot.write_field_end());
1351
1352
        // now, finish the struct off
1353
        assert_success!(o_prot.write_field_stop());
1354
        assert_success!(o_prot.write_struct_end());
1355
1356
        #[rustfmt::skip]
1357
        let expected: [u8; 5] = [
1358
            0x03, /* field type */
1359
            0x00, /* first field id */
1360
            0x44, /* field delta (4) | field type */
1361
            0x59, /* field delta (5) | field type */
1362
            0x00 /* field stop */,
1363
        ];
1364
1365
        assert_eq_written_bytes!(o_prot, expected);
1366
    }
1367
1368
    #[test]
1369
    fn must_round_trip_struct_with_delta_fields() {
1370
        let (mut i_prot, mut o_prot) = test_objects();
1371
1372
        // no bytes should be written however
1373
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1374
1375
        // write three fields with tiny field ids
1376
        // since they're small the field ids will be encoded as deltas
1377
1378
        // since this is the first field (and it's zero) it gets the full varint write
1379
        let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0);
1380
        assert_success!(o_prot.write_field_begin(&field_ident_1));
1381
        assert_success!(o_prot.write_field_end());
1382
1383
        // since this delta > 0 and < 15 it can be encoded as a delta
1384
        let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4);
1385
        assert_success!(o_prot.write_field_begin(&field_ident_2));
1386
        assert_success!(o_prot.write_field_end());
1387
1388
        // since this delta > 0 and < 15 it can be encoded as a delta
1389
        let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9);
1390
        assert_success!(o_prot.write_field_begin(&field_ident_3));
1391
        assert_success!(o_prot.write_field_end());
1392
1393
        // now, finish the struct off
1394
        assert_success!(o_prot.write_field_stop());
1395
        assert_success!(o_prot.write_struct_end());
1396
1397
        copy_write_buffer_to_read_buffer!(o_prot);
1398
1399
        // read the struct back
1400
        assert_success!(i_prot.read_struct_begin());
1401
1402
        let read_ident_1 = assert_success!(i_prot.read_field_begin());
1403
        assert_eq!(
1404
            read_ident_1,
1405
            TFieldIdentifier {
1406
                name: None,
1407
                ..field_ident_1
1408
            }
1409
        );
1410
        assert_success!(i_prot.read_field_end());
1411
1412
        let read_ident_2 = assert_success!(i_prot.read_field_begin());
1413
        assert_eq!(
1414
            read_ident_2,
1415
            TFieldIdentifier {
1416
                name: None,
1417
                ..field_ident_2
1418
            }
1419
        );
1420
        assert_success!(i_prot.read_field_end());
1421
1422
        let read_ident_3 = assert_success!(i_prot.read_field_begin());
1423
        assert_eq!(
1424
            read_ident_3,
1425
            TFieldIdentifier {
1426
                name: None,
1427
                ..field_ident_3
1428
            }
1429
        );
1430
        assert_success!(i_prot.read_field_end());
1431
1432
        let read_ident_4 = assert_success!(i_prot.read_field_begin());
1433
        assert_eq!(
1434
            read_ident_4,
1435
            TFieldIdentifier {
1436
                name: None,
1437
                field_type: TType::Stop,
1438
                id: None,
1439
            }
1440
        );
1441
1442
        assert_success!(i_prot.read_struct_end());
1443
    }
1444
1445
    #[test]
1446
    fn must_write_struct_with_non_zero_initial_field_and_delta_fields() {
1447
        let (_, mut o_prot) = test_objects();
1448
1449
        // no bytes should be written however
1450
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1451
1452
        // write three fields with tiny field ids
1453
        // since they're small the field ids will be encoded as deltas
1454
1455
        // gets a delta write
1456
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1)));
1457
        assert_success!(o_prot.write_field_end());
1458
1459
        // since this delta > 0 and < 15 it can be encoded as a delta
1460
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2)));
1461
        assert_success!(o_prot.write_field_end());
1462
1463
        // since this delta > 0 and < 15 it can be encoded as a delta
1464
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6)));
1465
        assert_success!(o_prot.write_field_end());
1466
1467
        // now, finish the struct off
1468
        assert_success!(o_prot.write_field_stop());
1469
        assert_success!(o_prot.write_struct_end());
1470
1471
        #[rustfmt::skip]
1472
        let expected: [u8; 4] = [
1473
            0x15, /* field delta (1) | field type */
1474
            0x1A, /* field delta (1) | field type */
1475
            0x48, /* field delta (4) | field type */
1476
            0x00 /* field stop */,
1477
        ];
1478
1479
        assert_eq_written_bytes!(o_prot, expected);
1480
    }
1481
1482
    #[test]
1483
    fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() {
1484
        let (mut i_prot, mut o_prot) = test_objects();
1485
1486
        // no bytes should be written however
1487
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1488
1489
        // write three fields with tiny field ids
1490
        // since they're small the field ids will be encoded as deltas
1491
1492
        // gets a delta write
1493
        let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1);
1494
        assert_success!(o_prot.write_field_begin(&field_ident_1));
1495
        assert_success!(o_prot.write_field_end());
1496
1497
        // since this delta > 0 and < 15 it can be encoded as a delta
1498
        let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2);
1499
        assert_success!(o_prot.write_field_begin(&field_ident_2));
1500
        assert_success!(o_prot.write_field_end());
1501
1502
        // since this delta > 0 and < 15 it can be encoded as a delta
1503
        let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6);
1504
        assert_success!(o_prot.write_field_begin(&field_ident_3));
1505
        assert_success!(o_prot.write_field_end());
1506
1507
        // now, finish the struct off
1508
        assert_success!(o_prot.write_field_stop());
1509
        assert_success!(o_prot.write_struct_end());
1510
1511
        copy_write_buffer_to_read_buffer!(o_prot);
1512
1513
        // read the struct back
1514
        assert_success!(i_prot.read_struct_begin());
1515
1516
        let read_ident_1 = assert_success!(i_prot.read_field_begin());
1517
        assert_eq!(
1518
            read_ident_1,
1519
            TFieldIdentifier {
1520
                name: None,
1521
                ..field_ident_1
1522
            }
1523
        );
1524
        assert_success!(i_prot.read_field_end());
1525
1526
        let read_ident_2 = assert_success!(i_prot.read_field_begin());
1527
        assert_eq!(
1528
            read_ident_2,
1529
            TFieldIdentifier {
1530
                name: None,
1531
                ..field_ident_2
1532
            }
1533
        );
1534
        assert_success!(i_prot.read_field_end());
1535
1536
        let read_ident_3 = assert_success!(i_prot.read_field_begin());
1537
        assert_eq!(
1538
            read_ident_3,
1539
            TFieldIdentifier {
1540
                name: None,
1541
                ..field_ident_3
1542
            }
1543
        );
1544
        assert_success!(i_prot.read_field_end());
1545
1546
        let read_ident_4 = assert_success!(i_prot.read_field_begin());
1547
        assert_eq!(
1548
            read_ident_4,
1549
            TFieldIdentifier {
1550
                name: None,
1551
                field_type: TType::Stop,
1552
                id: None,
1553
            }
1554
        );
1555
1556
        assert_success!(i_prot.read_struct_end());
1557
    }
1558
1559
    #[test]
1560
    fn must_write_struct_with_long_fields() {
1561
        let (_, mut o_prot) = test_objects();
1562
1563
        // no bytes should be written however
1564
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1565
1566
        // write three fields with field ids that cannot be encoded as deltas
1567
1568
        // since this is the first field (and it's zero) it gets the full varint write
1569
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0)));
1570
        assert_success!(o_prot.write_field_end());
1571
1572
        // since this delta is > 15 it is encoded as a zig-zag varint
1573
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16)));
1574
        assert_success!(o_prot.write_field_end());
1575
1576
        // since this delta is > 15 it is encoded as a zig-zag varint
1577
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99)));
1578
        assert_success!(o_prot.write_field_end());
1579
1580
        // now, finish the struct off
1581
        assert_success!(o_prot.write_field_stop());
1582
        assert_success!(o_prot.write_struct_end());
1583
1584
        #[rustfmt::skip]
1585
        let expected: [u8; 8] = [
1586
            0x05, /* field type */
1587
            0x00, /* first field id */
1588
            0x06, /* field type */
1589
            0x20, /* zig-zag varint field id */
1590
            0x0A, /* field type */
1591
            0xC6,
1592
            0x01, /* zig-zag varint field id */
1593
            0x00 /* field stop */,
1594
        ];
1595
1596
        assert_eq_written_bytes!(o_prot, expected);
1597
    }
1598
1599
    #[test]
1600
    fn must_round_trip_struct_with_long_fields() {
1601
        let (mut i_prot, mut o_prot) = test_objects();
1602
1603
        // no bytes should be written however
1604
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1605
1606
        // write three fields with field ids that cannot be encoded as deltas
1607
1608
        // since this is the first field (and it's zero) it gets the full varint write
1609
        let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0);
1610
        assert_success!(o_prot.write_field_begin(&field_ident_1));
1611
        assert_success!(o_prot.write_field_end());
1612
1613
        // since this delta is > 15 it is encoded as a zig-zag varint
1614
        let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16);
1615
        assert_success!(o_prot.write_field_begin(&field_ident_2));
1616
        assert_success!(o_prot.write_field_end());
1617
1618
        // since this delta is > 15 it is encoded as a zig-zag varint
1619
        let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99);
1620
        assert_success!(o_prot.write_field_begin(&field_ident_3));
1621
        assert_success!(o_prot.write_field_end());
1622
1623
        // now, finish the struct off
1624
        assert_success!(o_prot.write_field_stop());
1625
        assert_success!(o_prot.write_struct_end());
1626
1627
        copy_write_buffer_to_read_buffer!(o_prot);
1628
1629
        // read the struct back
1630
        assert_success!(i_prot.read_struct_begin());
1631
1632
        let read_ident_1 = assert_success!(i_prot.read_field_begin());
1633
        assert_eq!(
1634
            read_ident_1,
1635
            TFieldIdentifier {
1636
                name: None,
1637
                ..field_ident_1
1638
            }
1639
        );
1640
        assert_success!(i_prot.read_field_end());
1641
1642
        let read_ident_2 = assert_success!(i_prot.read_field_begin());
1643
        assert_eq!(
1644
            read_ident_2,
1645
            TFieldIdentifier {
1646
                name: None,
1647
                ..field_ident_2
1648
            }
1649
        );
1650
        assert_success!(i_prot.read_field_end());
1651
1652
        let read_ident_3 = assert_success!(i_prot.read_field_begin());
1653
        assert_eq!(
1654
            read_ident_3,
1655
            TFieldIdentifier {
1656
                name: None,
1657
                ..field_ident_3
1658
            }
1659
        );
1660
        assert_success!(i_prot.read_field_end());
1661
1662
        let read_ident_4 = assert_success!(i_prot.read_field_begin());
1663
        assert_eq!(
1664
            read_ident_4,
1665
            TFieldIdentifier {
1666
                name: None,
1667
                field_type: TType::Stop,
1668
                id: None,
1669
            }
1670
        );
1671
1672
        assert_success!(i_prot.read_struct_end());
1673
    }
1674
1675
    #[test]
1676
    fn must_write_struct_with_mix_of_long_and_delta_fields() {
1677
        let (_, mut o_prot) = test_objects();
1678
1679
        // no bytes should be written however
1680
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1681
1682
        // write three fields with field ids that cannot be encoded as deltas
1683
1684
        // since the delta is > 0 and < 15 it gets a delta write
1685
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1686
        assert_success!(o_prot.write_field_end());
1687
1688
        // since this delta > 0 and < 15 it gets a delta write
1689
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1690
        assert_success!(o_prot.write_field_end());
1691
1692
        // since this delta is > 15 it is encoded as a zig-zag varint
1693
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000)));
1694
        assert_success!(o_prot.write_field_end());
1695
1696
        // since this delta is > 15 it is encoded as a zig-zag varint
1697
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001)));
1698
        assert_success!(o_prot.write_field_end());
1699
1700
        // since this is only 3 up from the previous it is recorded as a delta
1701
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004)));
1702
        assert_success!(o_prot.write_field_end());
1703
1704
        // now, finish the struct off
1705
        assert_success!(o_prot.write_field_stop());
1706
        assert_success!(o_prot.write_struct_end());
1707
1708
        #[rustfmt::skip]
1709
        let expected: [u8; 10] = [
1710
            0x16, /* field delta (1) | field type */
1711
            0x85, /* field delta (8) | field type */
1712
            0x0A, /* field type */
1713
            0xD0,
1714
            0x0F, /* zig-zag varint field id */
1715
            0x0A, /* field type */
1716
            0xA2,
1717
            0x1F, /* zig-zag varint field id */
1718
            0x3A, /* field delta (3) | field type */
1719
            0x00 /* field stop */,
1720
        ];
1721
1722
        assert_eq_written_bytes!(o_prot, expected);
1723
    }
1724
1725
    #[allow(clippy::cognitive_complexity)]
1726
    #[test]
1727
    fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
1728
        let (mut i_prot, mut o_prot) = test_objects();
1729
1730
        // no bytes should be written however
1731
        let struct_ident = TStructIdentifier::new("foo");
1732
        assert_success!(o_prot.write_struct_begin(&struct_ident));
1733
1734
        // write three fields with field ids that cannot be encoded as deltas
1735
1736
        // since the delta is > 0 and < 15 it gets a delta write
1737
        let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1738
        assert_success!(o_prot.write_field_begin(&field_ident_1));
1739
        assert_success!(o_prot.write_field_end());
1740
1741
        // since this delta > 0 and < 15 it gets a delta write
1742
        let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1743
        assert_success!(o_prot.write_field_begin(&field_ident_2));
1744
        assert_success!(o_prot.write_field_end());
1745
1746
        // since this delta is > 15 it is encoded as a zig-zag varint
1747
        let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000);
1748
        assert_success!(o_prot.write_field_begin(&field_ident_3));
1749
        assert_success!(o_prot.write_field_end());
1750
1751
        // since this delta is > 15 it is encoded as a zig-zag varint
1752
        let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001);
1753
        assert_success!(o_prot.write_field_begin(&field_ident_4));
1754
        assert_success!(o_prot.write_field_end());
1755
1756
        // since this is only 3 up from the previous it is recorded as a delta
1757
        let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004);
1758
        assert_success!(o_prot.write_field_begin(&field_ident_5));
1759
        assert_success!(o_prot.write_field_end());
1760
1761
        // now, finish the struct off
1762
        assert_success!(o_prot.write_field_stop());
1763
        assert_success!(o_prot.write_struct_end());
1764
1765
        copy_write_buffer_to_read_buffer!(o_prot);
1766
1767
        // read the struct back
1768
        assert_success!(i_prot.read_struct_begin());
1769
1770
        let read_ident_1 = assert_success!(i_prot.read_field_begin());
1771
        assert_eq!(
1772
            read_ident_1,
1773
            TFieldIdentifier {
1774
                name: None,
1775
                ..field_ident_1
1776
            }
1777
        );
1778
        assert_success!(i_prot.read_field_end());
1779
1780
        let read_ident_2 = assert_success!(i_prot.read_field_begin());
1781
        assert_eq!(
1782
            read_ident_2,
1783
            TFieldIdentifier {
1784
                name: None,
1785
                ..field_ident_2
1786
            }
1787
        );
1788
        assert_success!(i_prot.read_field_end());
1789
1790
        let read_ident_3 = assert_success!(i_prot.read_field_begin());
1791
        assert_eq!(
1792
            read_ident_3,
1793
            TFieldIdentifier {
1794
                name: None,
1795
                ..field_ident_3
1796
            }
1797
        );
1798
        assert_success!(i_prot.read_field_end());
1799
1800
        let read_ident_4 = assert_success!(i_prot.read_field_begin());
1801
        assert_eq!(
1802
            read_ident_4,
1803
            TFieldIdentifier {
1804
                name: None,
1805
                ..field_ident_4
1806
            }
1807
        );
1808
        assert_success!(i_prot.read_field_end());
1809
1810
        let read_ident_5 = assert_success!(i_prot.read_field_begin());
1811
        assert_eq!(
1812
            read_ident_5,
1813
            TFieldIdentifier {
1814
                name: None,
1815
                ..field_ident_5
1816
            }
1817
        );
1818
        assert_success!(i_prot.read_field_end());
1819
1820
        let read_ident_6 = assert_success!(i_prot.read_field_begin());
1821
        assert_eq!(
1822
            read_ident_6,
1823
            TFieldIdentifier {
1824
                name: None,
1825
                field_type: TType::Stop,
1826
                id: None,
1827
            }
1828
        );
1829
1830
        assert_success!(i_prot.read_struct_end());
1831
    }
1832
1833
    #[test]
1834
    fn must_write_nested_structs_0() {
1835
        // last field of the containing struct is a delta
1836
        // first field of the the contained struct is a delta
1837
1838
        let (_, mut o_prot) = test_objects();
1839
1840
        // start containing struct
1841
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1842
1843
        // containing struct
1844
        // since the delta is > 0 and < 15 it gets a delta write
1845
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
1846
        assert_success!(o_prot.write_field_end());
1847
1848
        // containing struct
1849
        // since this delta > 0 and < 15 it gets a delta write
1850
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
1851
        assert_success!(o_prot.write_field_end());
1852
1853
        // start contained struct
1854
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1855
1856
        // contained struct
1857
        // since the delta is > 0 and < 15 it gets a delta write
1858
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7)));
1859
        assert_success!(o_prot.write_field_end());
1860
1861
        // contained struct
1862
        // since this delta > 15 it gets a full write
1863
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
1864
        assert_success!(o_prot.write_field_end());
1865
1866
        // end contained struct
1867
        assert_success!(o_prot.write_field_stop());
1868
        assert_success!(o_prot.write_struct_end());
1869
1870
        // end containing struct
1871
        assert_success!(o_prot.write_field_stop());
1872
        assert_success!(o_prot.write_struct_end());
1873
1874
        #[rustfmt::skip]
1875
        let expected: [u8; 7] = [
1876
            0x16, /* field delta (1) | field type */
1877
            0x85, /* field delta (8) | field type */
1878
            0x73, /* field delta (7) | field type */
1879
            0x07, /* field type */
1880
            0x30, /* zig-zag varint field id */
1881
            0x00, /* field stop - contained */
1882
            0x00 /* field stop - containing */,
1883
        ];
1884
1885
        assert_eq_written_bytes!(o_prot, expected);
1886
    }
1887
1888
    #[allow(clippy::cognitive_complexity)]
1889
    #[test]
1890
    fn must_round_trip_nested_structs_0() {
1891
        // last field of the containing struct is a delta
1892
        // first field of the the contained struct is a delta
1893
1894
        let (mut i_prot, mut o_prot) = test_objects();
1895
1896
        // start containing struct
1897
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1898
1899
        // containing struct
1900
        // since the delta is > 0 and < 15 it gets a delta write
1901
        let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
1902
        assert_success!(o_prot.write_field_begin(&field_ident_1));
1903
        assert_success!(o_prot.write_field_end());
1904
1905
        // containing struct
1906
        // since this delta > 0 and < 15 it gets a delta write
1907
        let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
1908
        assert_success!(o_prot.write_field_begin(&field_ident_2));
1909
        assert_success!(o_prot.write_field_end());
1910
1911
        // start contained struct
1912
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
1913
1914
        // contained struct
1915
        // since the delta is > 0 and < 15 it gets a delta write
1916
        let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7);
1917
        assert_success!(o_prot.write_field_begin(&field_ident_3));
1918
        assert_success!(o_prot.write_field_end());
1919
1920
        // contained struct
1921
        // since this delta > 15 it gets a full write
1922
        let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24);
1923
        assert_success!(o_prot.write_field_begin(&field_ident_4));
1924
        assert_success!(o_prot.write_field_end());
1925
1926
        // end contained struct
1927
        assert_success!(o_prot.write_field_stop());
1928
        assert_success!(o_prot.write_struct_end());
1929
1930
        // end containing struct
1931
        assert_success!(o_prot.write_field_stop());
1932
        assert_success!(o_prot.write_struct_end());
1933
1934
        copy_write_buffer_to_read_buffer!(o_prot);
1935
1936
        // read containing struct back
1937
        assert_success!(i_prot.read_struct_begin());
1938
1939
        let read_ident_1 = assert_success!(i_prot.read_field_begin());
1940
        assert_eq!(
1941
            read_ident_1,
1942
            TFieldIdentifier {
1943
                name: None,
1944
                ..field_ident_1
1945
            }
1946
        );
1947
        assert_success!(i_prot.read_field_end());
1948
1949
        let read_ident_2 = assert_success!(i_prot.read_field_begin());
1950
        assert_eq!(
1951
            read_ident_2,
1952
            TFieldIdentifier {
1953
                name: None,
1954
                ..field_ident_2
1955
            }
1956
        );
1957
        assert_success!(i_prot.read_field_end());
1958
1959
        // read contained struct back
1960
        assert_success!(i_prot.read_struct_begin());
1961
1962
        let read_ident_3 = assert_success!(i_prot.read_field_begin());
1963
        assert_eq!(
1964
            read_ident_3,
1965
            TFieldIdentifier {
1966
                name: None,
1967
                ..field_ident_3
1968
            }
1969
        );
1970
        assert_success!(i_prot.read_field_end());
1971
1972
        let read_ident_4 = assert_success!(i_prot.read_field_begin());
1973
        assert_eq!(
1974
            read_ident_4,
1975
            TFieldIdentifier {
1976
                name: None,
1977
                ..field_ident_4
1978
            }
1979
        );
1980
        assert_success!(i_prot.read_field_end());
1981
1982
        // end contained struct
1983
        let read_ident_6 = assert_success!(i_prot.read_field_begin());
1984
        assert_eq!(
1985
            read_ident_6,
1986
            TFieldIdentifier {
1987
                name: None,
1988
                field_type: TType::Stop,
1989
                id: None,
1990
            }
1991
        );
1992
        assert_success!(i_prot.read_struct_end());
1993
1994
        // end containing struct
1995
        let read_ident_7 = assert_success!(i_prot.read_field_begin());
1996
        assert_eq!(
1997
            read_ident_7,
1998
            TFieldIdentifier {
1999
                name: None,
2000
                field_type: TType::Stop,
2001
                id: None,
2002
            }
2003
        );
2004
        assert_success!(i_prot.read_struct_end());
2005
    }
2006
2007
    #[test]
2008
    fn must_write_nested_structs_1() {
2009
        // last field of the containing struct is a delta
2010
        // first field of the the contained struct is a full write
2011
2012
        let (_, mut o_prot) = test_objects();
2013
2014
        // start containing struct
2015
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2016
2017
        // containing struct
2018
        // since the delta is > 0 and < 15 it gets a delta write
2019
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2020
        assert_success!(o_prot.write_field_end());
2021
2022
        // containing struct
2023
        // since this delta > 0 and < 15 it gets a delta write
2024
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9)));
2025
        assert_success!(o_prot.write_field_end());
2026
2027
        // start contained struct
2028
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2029
2030
        // contained struct
2031
        // since this delta > 15 it gets a full write
2032
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24)));
2033
        assert_success!(o_prot.write_field_end());
2034
2035
        // contained struct
2036
        // since the delta is > 0 and < 15 it gets a delta write
2037
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
2038
        assert_success!(o_prot.write_field_end());
2039
2040
        // end contained struct
2041
        assert_success!(o_prot.write_field_stop());
2042
        assert_success!(o_prot.write_struct_end());
2043
2044
        // end containing struct
2045
        assert_success!(o_prot.write_field_stop());
2046
        assert_success!(o_prot.write_struct_end());
2047
2048
        #[rustfmt::skip]
2049
        let expected: [u8; 7] = [
2050
            0x16, /* field delta (1) | field type */
2051
            0x85, /* field delta (8) | field type */
2052
            0x07, /* field type */
2053
            0x30, /* zig-zag varint field id */
2054
            0x33, /* field delta (3) | field type */
2055
            0x00, /* field stop - contained */
2056
            0x00 /* field stop - containing */,
2057
        ];
2058
2059
        assert_eq_written_bytes!(o_prot, expected);
2060
    }
2061
2062
    #[allow(clippy::cognitive_complexity)]
2063
    #[test]
2064
    fn must_round_trip_nested_structs_1() {
2065
        // last field of the containing struct is a delta
2066
        // first field of the the contained struct is a full write
2067
2068
        let (mut i_prot, mut o_prot) = test_objects();
2069
2070
        // start containing struct
2071
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2072
2073
        // containing struct
2074
        // since the delta is > 0 and < 15 it gets a delta write
2075
        let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2076
        assert_success!(o_prot.write_field_begin(&field_ident_1));
2077
        assert_success!(o_prot.write_field_end());
2078
2079
        // containing struct
2080
        // since this delta > 0 and < 15 it gets a delta write
2081
        let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9);
2082
        assert_success!(o_prot.write_field_begin(&field_ident_2));
2083
        assert_success!(o_prot.write_field_end());
2084
2085
        // start contained struct
2086
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2087
2088
        // contained struct
2089
        // since this delta > 15 it gets a full write
2090
        let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24);
2091
        assert_success!(o_prot.write_field_begin(&field_ident_3));
2092
        assert_success!(o_prot.write_field_end());
2093
2094
        // contained struct
2095
        // since the delta is > 0 and < 15 it gets a delta write
2096
        let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2097
        assert_success!(o_prot.write_field_begin(&field_ident_4));
2098
        assert_success!(o_prot.write_field_end());
2099
2100
        // end contained struct
2101
        assert_success!(o_prot.write_field_stop());
2102
        assert_success!(o_prot.write_struct_end());
2103
2104
        // end containing struct
2105
        assert_success!(o_prot.write_field_stop());
2106
        assert_success!(o_prot.write_struct_end());
2107
2108
        copy_write_buffer_to_read_buffer!(o_prot);
2109
2110
        // read containing struct back
2111
        assert_success!(i_prot.read_struct_begin());
2112
2113
        let read_ident_1 = assert_success!(i_prot.read_field_begin());
2114
        assert_eq!(
2115
            read_ident_1,
2116
            TFieldIdentifier {
2117
                name: None,
2118
                ..field_ident_1
2119
            }
2120
        );
2121
        assert_success!(i_prot.read_field_end());
2122
2123
        let read_ident_2 = assert_success!(i_prot.read_field_begin());
2124
        assert_eq!(
2125
            read_ident_2,
2126
            TFieldIdentifier {
2127
                name: None,
2128
                ..field_ident_2
2129
            }
2130
        );
2131
        assert_success!(i_prot.read_field_end());
2132
2133
        // read contained struct back
2134
        assert_success!(i_prot.read_struct_begin());
2135
2136
        let read_ident_3 = assert_success!(i_prot.read_field_begin());
2137
        assert_eq!(
2138
            read_ident_3,
2139
            TFieldIdentifier {
2140
                name: None,
2141
                ..field_ident_3
2142
            }
2143
        );
2144
        assert_success!(i_prot.read_field_end());
2145
2146
        let read_ident_4 = assert_success!(i_prot.read_field_begin());
2147
        assert_eq!(
2148
            read_ident_4,
2149
            TFieldIdentifier {
2150
                name: None,
2151
                ..field_ident_4
2152
            }
2153
        );
2154
        assert_success!(i_prot.read_field_end());
2155
2156
        // end contained struct
2157
        let read_ident_6 = assert_success!(i_prot.read_field_begin());
2158
        assert_eq!(
2159
            read_ident_6,
2160
            TFieldIdentifier {
2161
                name: None,
2162
                field_type: TType::Stop,
2163
                id: None,
2164
            }
2165
        );
2166
        assert_success!(i_prot.read_struct_end());
2167
2168
        // end containing struct
2169
        let read_ident_7 = assert_success!(i_prot.read_field_begin());
2170
        assert_eq!(
2171
            read_ident_7,
2172
            TFieldIdentifier {
2173
                name: None,
2174
                field_type: TType::Stop,
2175
                id: None,
2176
            }
2177
        );
2178
        assert_success!(i_prot.read_struct_end());
2179
    }
2180
2181
    #[test]
2182
    fn must_write_nested_structs_2() {
2183
        // last field of the containing struct is a full write
2184
        // first field of the the contained struct is a delta write
2185
2186
        let (_, mut o_prot) = test_objects();
2187
2188
        // start containing struct
2189
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2190
2191
        // containing struct
2192
        // since the delta is > 0 and < 15 it gets a delta write
2193
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2194
        assert_success!(o_prot.write_field_end());
2195
2196
        // containing struct
2197
        // since this delta > 15 it gets a full write
2198
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2199
        assert_success!(o_prot.write_field_end());
2200
2201
        // start contained struct
2202
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2203
2204
        // contained struct
2205
        // since this delta > 0 and < 15 it gets a delta write
2206
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7)));
2207
        assert_success!(o_prot.write_field_end());
2208
2209
        // contained struct
2210
        // since the delta is > 0 and < 15 it gets a delta write
2211
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10)));
2212
        assert_success!(o_prot.write_field_end());
2213
2214
        // end contained struct
2215
        assert_success!(o_prot.write_field_stop());
2216
        assert_success!(o_prot.write_struct_end());
2217
2218
        // end containing struct
2219
        assert_success!(o_prot.write_field_stop());
2220
        assert_success!(o_prot.write_struct_end());
2221
2222
        #[rustfmt::skip]
2223
        let expected: [u8; 7] = [
2224
            0x16, /* field delta (1) | field type */
2225
            0x08, /* field type */
2226
            0x2A, /* zig-zag varint field id */
2227
            0x77, /* field delta(7) | field type */
2228
            0x33, /* field delta (3) | field type */
2229
            0x00, /* field stop - contained */
2230
            0x00 /* field stop - containing */,
2231
        ];
2232
2233
        assert_eq_written_bytes!(o_prot, expected);
2234
    }
2235
2236
    #[allow(clippy::cognitive_complexity)]
2237
    #[test]
2238
    fn must_round_trip_nested_structs_2() {
2239
        let (mut i_prot, mut o_prot) = test_objects();
2240
2241
        // start containing struct
2242
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2243
2244
        // containing struct
2245
        // since the delta is > 0 and < 15 it gets a delta write
2246
        let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2247
        assert_success!(o_prot.write_field_begin(&field_ident_1));
2248
        assert_success!(o_prot.write_field_end());
2249
2250
        // containing struct
2251
        // since this delta > 15 it gets a full write
2252
        let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2253
        assert_success!(o_prot.write_field_begin(&field_ident_2));
2254
        assert_success!(o_prot.write_field_end());
2255
2256
        // start contained struct
2257
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2258
2259
        // contained struct
2260
        // since this delta > 0 and < 15 it gets a delta write
2261
        let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7);
2262
        assert_success!(o_prot.write_field_begin(&field_ident_3));
2263
        assert_success!(o_prot.write_field_end());
2264
2265
        // contained struct
2266
        // since the delta is > 0 and < 15 it gets a delta write
2267
        let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10);
2268
        assert_success!(o_prot.write_field_begin(&field_ident_4));
2269
        assert_success!(o_prot.write_field_end());
2270
2271
        // end contained struct
2272
        assert_success!(o_prot.write_field_stop());
2273
        assert_success!(o_prot.write_struct_end());
2274
2275
        // end containing struct
2276
        assert_success!(o_prot.write_field_stop());
2277
        assert_success!(o_prot.write_struct_end());
2278
2279
        copy_write_buffer_to_read_buffer!(o_prot);
2280
2281
        // read containing struct back
2282
        assert_success!(i_prot.read_struct_begin());
2283
2284
        let read_ident_1 = assert_success!(i_prot.read_field_begin());
2285
        assert_eq!(
2286
            read_ident_1,
2287
            TFieldIdentifier {
2288
                name: None,
2289
                ..field_ident_1
2290
            }
2291
        );
2292
        assert_success!(i_prot.read_field_end());
2293
2294
        let read_ident_2 = assert_success!(i_prot.read_field_begin());
2295
        assert_eq!(
2296
            read_ident_2,
2297
            TFieldIdentifier {
2298
                name: None,
2299
                ..field_ident_2
2300
            }
2301
        );
2302
        assert_success!(i_prot.read_field_end());
2303
2304
        // read contained struct back
2305
        assert_success!(i_prot.read_struct_begin());
2306
2307
        let read_ident_3 = assert_success!(i_prot.read_field_begin());
2308
        assert_eq!(
2309
            read_ident_3,
2310
            TFieldIdentifier {
2311
                name: None,
2312
                ..field_ident_3
2313
            }
2314
        );
2315
        assert_success!(i_prot.read_field_end());
2316
2317
        let read_ident_4 = assert_success!(i_prot.read_field_begin());
2318
        assert_eq!(
2319
            read_ident_4,
2320
            TFieldIdentifier {
2321
                name: None,
2322
                ..field_ident_4
2323
            }
2324
        );
2325
        assert_success!(i_prot.read_field_end());
2326
2327
        // end contained struct
2328
        let read_ident_6 = assert_success!(i_prot.read_field_begin());
2329
        assert_eq!(
2330
            read_ident_6,
2331
            TFieldIdentifier {
2332
                name: None,
2333
                field_type: TType::Stop,
2334
                id: None,
2335
            }
2336
        );
2337
        assert_success!(i_prot.read_struct_end());
2338
2339
        // end containing struct
2340
        let read_ident_7 = assert_success!(i_prot.read_field_begin());
2341
        assert_eq!(
2342
            read_ident_7,
2343
            TFieldIdentifier {
2344
                name: None,
2345
                field_type: TType::Stop,
2346
                id: None,
2347
            }
2348
        );
2349
        assert_success!(i_prot.read_struct_end());
2350
    }
2351
2352
    #[test]
2353
    fn must_write_nested_structs_3() {
2354
        // last field of the containing struct is a full write
2355
        // first field of the the contained struct is a full write
2356
2357
        let (_, mut o_prot) = test_objects();
2358
2359
        // start containing struct
2360
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2361
2362
        // containing struct
2363
        // since the delta is > 0 and < 15 it gets a delta write
2364
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1)));
2365
        assert_success!(o_prot.write_field_end());
2366
2367
        // containing struct
2368
        // since this delta > 15 it gets a full write
2369
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21)));
2370
        assert_success!(o_prot.write_field_end());
2371
2372
        // start contained struct
2373
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2374
2375
        // contained struct
2376
        // since this delta > 15 it gets a full write
2377
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21)));
2378
        assert_success!(o_prot.write_field_end());
2379
2380
        // contained struct
2381
        // since the delta is > 0 and < 15 it gets a delta write
2382
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27)));
2383
        assert_success!(o_prot.write_field_end());
2384
2385
        // end contained struct
2386
        assert_success!(o_prot.write_field_stop());
2387
        assert_success!(o_prot.write_struct_end());
2388
2389
        // end containing struct
2390
        assert_success!(o_prot.write_field_stop());
2391
        assert_success!(o_prot.write_struct_end());
2392
2393
        #[rustfmt::skip]
2394
        let expected: [u8; 8] = [
2395
            0x16, /* field delta (1) | field type */
2396
            0x08, /* field type */
2397
            0x2A, /* zig-zag varint field id */
2398
            0x07, /* field type */
2399
            0x2A, /* zig-zag varint field id */
2400
            0x63, /* field delta (6) | field type */
2401
            0x00, /* field stop - contained */
2402
            0x00 /* field stop - containing */,
2403
        ];
2404
2405
        assert_eq_written_bytes!(o_prot, expected);
2406
    }
2407
2408
    #[allow(clippy::cognitive_complexity)]
2409
    #[test]
2410
    fn must_round_trip_nested_structs_3() {
2411
        // last field of the containing struct is a full write
2412
        // first field of the the contained struct is a full write
2413
2414
        let (mut i_prot, mut o_prot) = test_objects();
2415
2416
        // start containing struct
2417
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2418
2419
        // containing struct
2420
        // since the delta is > 0 and < 15 it gets a delta write
2421
        let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1);
2422
        assert_success!(o_prot.write_field_begin(&field_ident_1));
2423
        assert_success!(o_prot.write_field_end());
2424
2425
        // containing struct
2426
        // since this delta > 15 it gets a full write
2427
        let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21);
2428
        assert_success!(o_prot.write_field_begin(&field_ident_2));
2429
        assert_success!(o_prot.write_field_end());
2430
2431
        // start contained struct
2432
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2433
2434
        // contained struct
2435
        // since this delta > 15 it gets a full write
2436
        let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21);
2437
        assert_success!(o_prot.write_field_begin(&field_ident_3));
2438
        assert_success!(o_prot.write_field_end());
2439
2440
        // contained struct
2441
        // since the delta is > 0 and < 15 it gets a delta write
2442
        let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27);
2443
        assert_success!(o_prot.write_field_begin(&field_ident_4));
2444
        assert_success!(o_prot.write_field_end());
2445
2446
        // end contained struct
2447
        assert_success!(o_prot.write_field_stop());
2448
        assert_success!(o_prot.write_struct_end());
2449
2450
        // end containing struct
2451
        assert_success!(o_prot.write_field_stop());
2452
        assert_success!(o_prot.write_struct_end());
2453
2454
        copy_write_buffer_to_read_buffer!(o_prot);
2455
2456
        // read containing struct back
2457
        assert_success!(i_prot.read_struct_begin());
2458
2459
        let read_ident_1 = assert_success!(i_prot.read_field_begin());
2460
        assert_eq!(
2461
            read_ident_1,
2462
            TFieldIdentifier {
2463
                name: None,
2464
                ..field_ident_1
2465
            }
2466
        );
2467
        assert_success!(i_prot.read_field_end());
2468
2469
        let read_ident_2 = assert_success!(i_prot.read_field_begin());
2470
        assert_eq!(
2471
            read_ident_2,
2472
            TFieldIdentifier {
2473
                name: None,
2474
                ..field_ident_2
2475
            }
2476
        );
2477
        assert_success!(i_prot.read_field_end());
2478
2479
        // read contained struct back
2480
        assert_success!(i_prot.read_struct_begin());
2481
2482
        let read_ident_3 = assert_success!(i_prot.read_field_begin());
2483
        assert_eq!(
2484
            read_ident_3,
2485
            TFieldIdentifier {
2486
                name: None,
2487
                ..field_ident_3
2488
            }
2489
        );
2490
        assert_success!(i_prot.read_field_end());
2491
2492
        let read_ident_4 = assert_success!(i_prot.read_field_begin());
2493
        assert_eq!(
2494
            read_ident_4,
2495
            TFieldIdentifier {
2496
                name: None,
2497
                ..field_ident_4
2498
            }
2499
        );
2500
        assert_success!(i_prot.read_field_end());
2501
2502
        // end contained struct
2503
        let read_ident_6 = assert_success!(i_prot.read_field_begin());
2504
        assert_eq!(
2505
            read_ident_6,
2506
            TFieldIdentifier {
2507
                name: None,
2508
                field_type: TType::Stop,
2509
                id: None,
2510
            }
2511
        );
2512
        assert_success!(i_prot.read_struct_end());
2513
2514
        // end containing struct
2515
        let read_ident_7 = assert_success!(i_prot.read_field_begin());
2516
        assert_eq!(
2517
            read_ident_7,
2518
            TFieldIdentifier {
2519
                name: None,
2520
                field_type: TType::Stop,
2521
                id: None,
2522
            }
2523
        );
2524
        assert_success!(i_prot.read_struct_end());
2525
    }
2526
2527
    #[test]
2528
    fn must_write_bool_field() {
2529
        let (_, mut o_prot) = test_objects();
2530
2531
        // no bytes should be written however
2532
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2533
2534
        // write three fields with field ids that cannot be encoded as deltas
2535
2536
        // since the delta is > 0 and < 16 it gets a delta write
2537
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2538
        assert_success!(o_prot.write_bool(true));
2539
        assert_success!(o_prot.write_field_end());
2540
2541
        // since this delta > 0 and < 15 it gets a delta write
2542
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9)));
2543
        assert_success!(o_prot.write_bool(false));
2544
        assert_success!(o_prot.write_field_end());
2545
2546
        // since this delta > 15 it gets a full write
2547
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26)));
2548
        assert_success!(o_prot.write_bool(true));
2549
        assert_success!(o_prot.write_field_end());
2550
2551
        // since this delta > 15 it gets a full write
2552
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45)));
2553
        assert_success!(o_prot.write_bool(false));
2554
        assert_success!(o_prot.write_field_end());
2555
2556
        // now, finish the struct off
2557
        assert_success!(o_prot.write_field_stop());
2558
        assert_success!(o_prot.write_struct_end());
2559
2560
        #[rustfmt::skip]
2561
        let expected: [u8; 7] = [
2562
            0x11, /* field delta (1) | true */
2563
            0x82, /* field delta (8) | false */
2564
            0x01, /* true */
2565
            0x34, /* field id */
2566
            0x02, /* false */
2567
            0x5A, /* field id */
2568
            0x00 /* stop field */,
2569
        ];
2570
2571
        assert_eq_written_bytes!(o_prot, expected);
2572
    }
2573
2574
    #[allow(clippy::cognitive_complexity)]
2575
    #[test]
2576
    fn must_round_trip_bool_field() {
2577
        let (mut i_prot, mut o_prot) = test_objects();
2578
2579
        // no bytes should be written however
2580
        let struct_ident = TStructIdentifier::new("foo");
2581
        assert_success!(o_prot.write_struct_begin(&struct_ident));
2582
2583
        // write two fields
2584
2585
        // since the delta is > 0 and < 16 it gets a delta write
2586
        let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1);
2587
        assert_success!(o_prot.write_field_begin(&field_ident_1));
2588
        assert_success!(o_prot.write_bool(true));
2589
        assert_success!(o_prot.write_field_end());
2590
2591
        // since this delta > 0 and < 15 it gets a delta write
2592
        let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9);
2593
        assert_success!(o_prot.write_field_begin(&field_ident_2));
2594
        assert_success!(o_prot.write_bool(false));
2595
        assert_success!(o_prot.write_field_end());
2596
2597
        // since this delta > 15 it gets a full write
2598
        let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26);
2599
        assert_success!(o_prot.write_field_begin(&field_ident_3));
2600
        assert_success!(o_prot.write_bool(true));
2601
        assert_success!(o_prot.write_field_end());
2602
2603
        // since this delta > 15 it gets a full write
2604
        let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45);
2605
        assert_success!(o_prot.write_field_begin(&field_ident_4));
2606
        assert_success!(o_prot.write_bool(false));
2607
        assert_success!(o_prot.write_field_end());
2608
2609
        // now, finish the struct off
2610
        assert_success!(o_prot.write_field_stop());
2611
        assert_success!(o_prot.write_struct_end());
2612
2613
        copy_write_buffer_to_read_buffer!(o_prot);
2614
2615
        // read the struct back
2616
        assert_success!(i_prot.read_struct_begin());
2617
2618
        let read_ident_1 = assert_success!(i_prot.read_field_begin());
2619
        assert_eq!(
2620
            read_ident_1,
2621
            TFieldIdentifier {
2622
                name: None,
2623
                ..field_ident_1
2624
            }
2625
        );
2626
        let read_value_1 = assert_success!(i_prot.read_bool());
2627
        assert!(read_value_1);
2628
        assert_success!(i_prot.read_field_end());
2629
2630
        let read_ident_2 = assert_success!(i_prot.read_field_begin());
2631
        assert_eq!(
2632
            read_ident_2,
2633
            TFieldIdentifier {
2634
                name: None,
2635
                ..field_ident_2
2636
            }
2637
        );
2638
        let read_value_2 = assert_success!(i_prot.read_bool());
2639
        assert!(!read_value_2);
2640
        assert_success!(i_prot.read_field_end());
2641
2642
        let read_ident_3 = assert_success!(i_prot.read_field_begin());
2643
        assert_eq!(
2644
            read_ident_3,
2645
            TFieldIdentifier {
2646
                name: None,
2647
                ..field_ident_3
2648
            }
2649
        );
2650
        let read_value_3 = assert_success!(i_prot.read_bool());
2651
        assert!(read_value_3);
2652
        assert_success!(i_prot.read_field_end());
2653
2654
        let read_ident_4 = assert_success!(i_prot.read_field_begin());
2655
        assert_eq!(
2656
            read_ident_4,
2657
            TFieldIdentifier {
2658
                name: None,
2659
                ..field_ident_4
2660
            }
2661
        );
2662
        let read_value_4 = assert_success!(i_prot.read_bool());
2663
        assert!(!read_value_4);
2664
        assert_success!(i_prot.read_field_end());
2665
2666
        let read_ident_5 = assert_success!(i_prot.read_field_begin());
2667
        assert_eq!(
2668
            read_ident_5,
2669
            TFieldIdentifier {
2670
                name: None,
2671
                field_type: TType::Stop,
2672
                id: None,
2673
            }
2674
        );
2675
2676
        assert_success!(i_prot.read_struct_end());
2677
    }
2678
2679
    #[test]
2680
    #[should_panic]
2681
    fn must_fail_if_write_field_end_without_writing_bool_value() {
2682
        let (_, mut o_prot) = test_objects();
2683
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2684
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2685
        o_prot.write_field_end().unwrap();
2686
    }
2687
2688
    #[test]
2689
    #[should_panic]
2690
    fn must_fail_if_write_stop_field_without_writing_bool_value() {
2691
        let (_, mut o_prot) = test_objects();
2692
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2693
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2694
        o_prot.write_field_stop().unwrap();
2695
    }
2696
2697
    #[test]
2698
    #[should_panic]
2699
    fn must_fail_if_write_struct_end_without_writing_bool_value() {
2700
        let (_, mut o_prot) = test_objects();
2701
        assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo")));
2702
        assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1)));
2703
        o_prot.write_struct_end().unwrap();
2704
    }
2705
2706
    #[test]
2707
    #[should_panic]
2708
    fn must_fail_if_write_struct_end_without_any_fields() {
2709
        let (_, mut o_prot) = test_objects();
2710
        o_prot.write_struct_end().unwrap();
2711
    }
2712
2713
    #[test]
2714
    fn must_write_field_end() {
2715
        assert_no_write(|o| o.write_field_end());
2716
    }
2717
2718
    #[test]
2719
    fn must_write_small_sized_list_begin() {
2720
        let (_, mut o_prot) = test_objects();
2721
2722
        assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4)));
2723
2724
        let expected: [u8; 1] = [0x46 /* size | elem_type */];
2725
2726
        assert_eq_written_bytes!(o_prot, expected);
2727
    }
2728
2729
    #[test]
2730
    fn must_round_trip_small_sized_list_begin() {
2731
        let (mut i_prot, mut o_prot) = test_objects();
2732
2733
        let ident = TListIdentifier::new(TType::I32, 3);
2734
        assert_success!(o_prot.write_list_begin(&ident));
2735
2736
        assert_success!(o_prot.write_i32(100));
2737
        assert_success!(o_prot.write_i32(200));
2738
        assert_success!(o_prot.write_i32(300));
2739
2740
        assert_success!(o_prot.write_list_end());
2741
2742
        copy_write_buffer_to_read_buffer!(o_prot);
2743
2744
        let res = assert_success!(i_prot.read_list_begin());
2745
        assert_eq!(&res, &ident);
2746
2747
        assert_eq!(i_prot.read_i32().unwrap(), 100);
2748
        assert_eq!(i_prot.read_i32().unwrap(), 200);
2749
        assert_eq!(i_prot.read_i32().unwrap(), 300);
2750
2751
        assert_success!(i_prot.read_list_end());
2752
    }
2753
2754
    #[test]
2755
    fn must_write_large_sized_list_begin() {
2756
        let (_, mut o_prot) = test_objects();
2757
2758
        let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999));
2759
        assert!(res.is_ok());
2760
2761
        let expected: [u8; 3] = [
2762
            0xF9, /* 0xF0 | elem_type */
2763
            0x8F, 0x4E, /* size as varint */
2764
        ];
2765
2766
        assert_eq_written_bytes!(o_prot, expected);
2767
    }
2768
2769
    #[test]
2770
    fn must_round_trip_large_sized_list_begin() {
2771
        let (mut i_prot, mut o_prot) = test_objects_no_limits();
2772
2773
        let ident = TListIdentifier::new(TType::Set, 47381);
2774
        assert_success!(o_prot.write_list_begin(&ident));
2775
2776
        copy_write_buffer_to_read_buffer!(o_prot);
2777
2778
        let res = assert_success!(i_prot.read_list_begin());
2779
        assert_eq!(&res, &ident);
2780
    }
2781
2782
    #[test]
2783
    fn must_write_list_end() {
2784
        assert_no_write(|o| o.write_list_end());
2785
    }
2786
2787
    #[test]
2788
    fn must_write_small_sized_set_begin() {
2789
        let (_, mut o_prot) = test_objects();
2790
2791
        assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2)));
2792
2793
        let expected: [u8; 1] = [0x2C /* size | elem_type */];
2794
2795
        assert_eq_written_bytes!(o_prot, expected);
2796
    }
2797
2798
    #[test]
2799
    fn must_round_trip_small_sized_set_begin() {
2800
        let (mut i_prot, mut o_prot) = test_objects();
2801
2802
        let ident = TSetIdentifier::new(TType::I16, 3);
2803
        assert_success!(o_prot.write_set_begin(&ident));
2804
2805
        assert_success!(o_prot.write_i16(111));
2806
        assert_success!(o_prot.write_i16(222));
2807
        assert_success!(o_prot.write_i16(333));
2808
2809
        assert_success!(o_prot.write_set_end());
2810
2811
        copy_write_buffer_to_read_buffer!(o_prot);
2812
2813
        let res = assert_success!(i_prot.read_set_begin());
2814
        assert_eq!(&res, &ident);
2815
2816
        assert_eq!(i_prot.read_i16().unwrap(), 111);
2817
        assert_eq!(i_prot.read_i16().unwrap(), 222);
2818
        assert_eq!(i_prot.read_i16().unwrap(), 333);
2819
2820
        assert_success!(i_prot.read_set_end());
2821
    }
2822
2823
    #[test]
2824
    fn must_write_large_sized_set_begin() {
2825
        let (_, mut o_prot) = test_objects();
2826
2827
        assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891)));
2828
2829
        let expected: [u8; 4] = [
2830
            0xF7, /* 0xF0 | elem_type */
2831
            0xD3, 0xBA, 0x01, /* size as varint */
2832
        ];
2833
2834
        assert_eq_written_bytes!(o_prot, expected);
2835
    }
2836
2837
    #[test]
2838
    fn must_round_trip_large_sized_set_begin() {
2839
        let (mut i_prot, mut o_prot) = test_objects_no_limits();
2840
2841
        let ident = TSetIdentifier::new(TType::Map, 3_928_429);
2842
        assert_success!(o_prot.write_set_begin(&ident));
2843
2844
        copy_write_buffer_to_read_buffer!(o_prot);
2845
2846
        let res = assert_success!(i_prot.read_set_begin());
2847
        assert_eq!(&res, &ident);
2848
    }
2849
2850
    #[test]
2851
    fn must_write_set_end() {
2852
        assert_no_write(|o| o.write_set_end());
2853
    }
2854
2855
    #[test]
2856
    fn must_write_zero_sized_map_begin() {
2857
        let (_, mut o_prot) = test_objects();
2858
2859
        assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0)));
2860
2861
        let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything
2862
2863
        assert_eq_written_bytes!(o_prot, expected);
2864
    }
2865
2866
    #[test]
2867
    fn must_read_zero_sized_map_begin() {
2868
        let (mut i_prot, mut o_prot) = test_objects();
2869
2870
        assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0)));
2871
2872
        copy_write_buffer_to_read_buffer!(o_prot);
2873
2874
        let res = assert_success!(i_prot.read_map_begin());
2875
        assert_eq!(
2876
            &res,
2877
            &TMapIdentifier {
2878
                key_type: None,
2879
                value_type: None,
2880
                size: 0,
2881
            }
2882
        );
2883
    }
2884
2885
    #[test]
2886
    fn must_write_map_begin() {
2887
        let (_, mut o_prot) = test_objects();
2888
2889
        assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
2890
            TType::Double,
2891
            TType::String,
2892
            238
2893
        )));
2894
2895
        let expected: [u8; 3] = [
2896
            0xEE, 0x01, /* size as varint */
2897
            0x78, /* key type | val type */
2898
        ];
2899
2900
        assert_eq_written_bytes!(o_prot, expected);
2901
    }
2902
2903
    #[test]
2904
    fn must_round_trip_map_begin() {
2905
        let (mut i_prot, mut o_prot) = test_objects_no_limits();
2906
2907
        let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349);
2908
        assert_success!(o_prot.write_map_begin(&ident));
2909
2910
        copy_write_buffer_to_read_buffer!(o_prot);
2911
2912
        let res = assert_success!(i_prot.read_map_begin());
2913
        assert_eq!(&res, &ident);
2914
    }
2915
2916
    #[test]
2917
    fn must_write_map_end() {
2918
        assert_no_write(|o| o.write_map_end());
2919
    }
2920
2921
    #[test]
2922
    fn must_write_map_with_bool_key_and_value() {
2923
        let (_, mut o_prot) = test_objects();
2924
2925
        assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1)));
2926
        assert_success!(o_prot.write_bool(true));
2927
        assert_success!(o_prot.write_bool(false));
2928
        assert_success!(o_prot.write_map_end());
2929
2930
        let expected: [u8; 4] = [
2931
            0x01, /* size as varint */
2932
            0x11, /* key type | val type */
2933
            0x01, /* key: true */
2934
            0x02, /* val: false */
2935
        ];
2936
2937
        assert_eq_written_bytes!(o_prot, expected);
2938
    }
2939
2940
    #[test]
2941
    fn must_round_trip_map_with_bool_value() {
2942
        let (mut i_prot, mut o_prot) = test_objects();
2943
2944
        let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2);
2945
        assert_success!(o_prot.write_map_begin(&map_ident));
2946
        assert_success!(o_prot.write_bool(true));
2947
        assert_success!(o_prot.write_bool(false));
2948
        assert_success!(o_prot.write_bool(false));
2949
        assert_success!(o_prot.write_bool(true));
2950
        assert_success!(o_prot.write_map_end());
2951
2952
        copy_write_buffer_to_read_buffer!(o_prot);
2953
2954
        // map header
2955
        let rcvd_ident = assert_success!(i_prot.read_map_begin());
2956
        assert_eq!(&rcvd_ident, &map_ident);
2957
        // key 1
2958
        let b = assert_success!(i_prot.read_bool());
2959
        assert!(b);
2960
        // val 1
2961
        let b = assert_success!(i_prot.read_bool());
2962
        assert!(!b);
2963
        // key 2
2964
        let b = assert_success!(i_prot.read_bool());
2965
        assert!(!b);
2966
        // val 2
2967
        let b = assert_success!(i_prot.read_bool());
2968
        assert!(b);
2969
        // map end
2970
        assert_success!(i_prot.read_map_end());
2971
    }
2972
2973
    #[test]
2974
    fn must_read_map_end() {
2975
        let (mut i_prot, _) = test_objects();
2976
        assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
2977
    }
2978
2979
    #[test]
2980
    fn must_reject_overlong_varint_i64() {
2981
        let (mut i_prot, _) = test_objects();
2982
        i_prot.transport.set_readable_bytes(&[0x80u8; 11]); // 11 continuation bytes, no terminator
2983
        let res = i_prot.read_i64();
2984
        assert!(res.is_err());
2985
        match res {
2986
            Err(crate::Error::Protocol(e)) => {
2987
                assert_eq!(e.kind, ProtocolErrorKind::InvalidData);
2988
            }
2989
            _ => panic!("expected Protocol/InvalidData error"),
2990
        }
2991
    }
2992
2993
    #[test]
2994
    fn must_accept_valid_10_byte_varint_i64() {
2995
        let (mut i_prot, _) = test_objects();
2996
        let mut bytes = [0x80u8; 10];
2997
        bytes[9] = 0x01; // terminating byte
2998
        i_prot.transport.set_readable_bytes(&bytes);
2999
        assert!(i_prot.read_i64().is_ok());
3000
    }
3001
3002
    fn test_objects() -> (
3003
        TCompactInputProtocol<ReadHalf<TBufferChannel>>,
3004
        TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
3005
    ) {
3006
        let mem = TBufferChannel::with_capacity(200, 200);
3007
3008
        let (r_mem, w_mem) = mem.split().unwrap();
3009
3010
        let i_prot = TCompactInputProtocol::new(r_mem);
3011
        let o_prot = TCompactOutputProtocol::new(w_mem);
3012
3013
        (i_prot, o_prot)
3014
    }
3015
3016
    fn test_objects_no_limits() -> (
3017
        TCompactInputProtocol<ReadHalf<TBufferChannel>>,
3018
        TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
3019
    ) {
3020
        let mem = TBufferChannel::with_capacity(200, 200);
3021
3022
        let (r_mem, w_mem) = mem.split().unwrap();
3023
3024
        let i_prot = TCompactInputProtocol::with_config(r_mem, TConfiguration::no_limits());
3025
        let o_prot = TCompactOutputProtocol::new(w_mem);
3026
3027
        (i_prot, o_prot)
3028
    }
3029
3030
    #[test]
3031
    fn must_read_write_double() {
3032
        let (mut i_prot, mut o_prot) = test_objects();
3033
3034
        #[allow(clippy::approx_constant)]
3035
        let double = 3.141_592_653_589_793;
3036
        o_prot.write_double(double).unwrap();
3037
        copy_write_buffer_to_read_buffer!(o_prot);
3038
3039
        let read_double = i_prot.read_double().unwrap();
3040
        assert!((read_double - double).abs() < f64::EPSILON);
3041
    }
3042
3043
    #[test]
3044
    fn must_encode_double_as_other_langs() {
3045
        let (_, mut o_prot) = test_objects();
3046
        let expected = [24, 45, 68, 84, 251, 33, 9, 64];
3047
3048
        #[allow(clippy::approx_constant)]
3049
        let double = 3.141_592_653_589_793;
3050
        o_prot.write_double(double).unwrap();
3051
3052
        assert_eq_written_bytes!(o_prot, expected);
3053
    }
3054
3055
    fn assert_no_write<F>(mut write_fn: F)
3056
    where
3057
        F: FnMut(&mut TCompactOutputProtocol<WriteHalf<TBufferChannel>>) -> crate::Result<()>,
3058
    {
3059
        let (_, mut o_prot) = test_objects();
3060
        assert!(write_fn(&mut o_prot).is_ok());
3061
        assert_eq!(o_prot.transport.write_bytes().len(), 0);
3062
    }
3063
3064
    #[test]
3065
    fn must_read_boolean_list() {
3066
        let (mut i_prot, _) = test_objects();
3067
3068
        let source_bytes: [u8; 3] = [0x21, 2, 1];
3069
3070
        i_prot.transport.set_readable_bytes(&source_bytes);
3071
3072
        let (ttype, element_count) = assert_success!(i_prot.read_list_set_begin());
3073
3074
        assert_eq!(ttype, TType::Bool);
3075
        assert_eq!(element_count, 2);
3076
        assert_eq!(i_prot.read_bool().unwrap(), false);
3077
        assert_eq!(i_prot.read_bool().unwrap(), true);
3078
3079
        assert_success!(i_prot.read_list_end());
3080
    }
3081
3082
    #[test]
3083
    fn must_read_boolean_list_alternative_encoding() {
3084
        let (mut i_prot, _) = test_objects();
3085
3086
        let source_bytes: [u8; 3] = [0x22, 0, 1];
3087
3088
        i_prot.transport.set_readable_bytes(&source_bytes);
3089
3090
        let (ttype, element_count) = assert_success!(i_prot.read_list_set_begin());
3091
3092
        assert_eq!(ttype, TType::Bool);
3093
        assert_eq!(element_count, 2);
3094
        assert_eq!(i_prot.read_bool().unwrap(), false);
3095
        assert_eq!(i_prot.read_bool().unwrap(), true);
3096
3097
        assert_success!(i_prot.read_list_end());
3098
    }
3099
3100
    #[test]
3101
    fn must_enforce_recursion_depth_limit() {
3102
        let channel = TBufferChannel::with_capacity(100, 100);
3103
3104
        // Create a configuration with a small recursion limit
3105
        let config = TConfiguration::builder()
3106
            .max_recursion_depth(Some(2))
3107
            .build()
3108
            .unwrap();
3109
3110
        let mut protocol = TCompactInputProtocol::with_config(channel, config);
3111
3112
        // First struct - should succeed
3113
        assert!(protocol.read_struct_begin().is_ok());
3114
3115
        // Second struct - should succeed (at limit)
3116
        assert!(protocol.read_struct_begin().is_ok());
3117
3118
        // Third struct - should fail (exceeds limit)
3119
        let result = protocol.read_struct_begin();
3120
        assert!(result.is_err());
3121
        match result {
3122
            Err(crate::Error::Protocol(e)) => {
3123
                assert_eq!(e.kind, ProtocolErrorKind::DepthLimit);
3124
            }
3125
            _ => panic!("Expected protocol error with DepthLimit"),
3126
        }
3127
    }
3128
3129
    #[test]
3130
    fn must_check_container_size_overflow() {
3131
        // Configure a small message size limit
3132
        let config = TConfiguration::builder()
3133
            .max_message_size(Some(1000))
3134
            .max_frame_size(Some(1000))
3135
            .build()
3136
            .unwrap();
3137
        let transport = TBufferChannel::with_capacity(100, 0);
3138
        let mut i_prot = TCompactInputProtocol::with_config(transport, config);
3139
3140
        // Write a list header that would require more memory than message size limit
3141
        // List of 100 UUIDs (16 bytes each) = 1600 bytes > 1000 limit
3142
        i_prot.transport.set_readable_bytes(&[
3143
            0xFD, // element type UUID (0x0D) | count in next bytes (0xF0)
3144
            0x64, // varint 100
3145
        ]);
3146
3147
        let result = i_prot.read_list_begin();
3148
        assert!(result.is_err());
3149
        match result {
3150
            Err(crate::Error::Protocol(e)) => {
3151
                assert_eq!(e.kind, ProtocolErrorKind::SizeLimit);
3152
                assert!(e
3153
                    .message
3154
                    .contains("1600 bytes, exceeding message size limit of 1000"));
3155
            }
3156
            _ => panic!("Expected protocol error with SizeLimit"),
3157
        }
3158
    }
3159
3160
    #[test]
3161
    fn must_reject_negative_container_sizes() {
3162
        let mut channel = TBufferChannel::with_capacity(100, 100);
3163
3164
        let mut protocol = TCompactInputProtocol::new(channel.clone());
3165
3166
        // Write header with negative size when decoded
3167
        // In compact protocol, lists/sets use a header byte followed by size
3168
        // We'll use 0x0F for element type and then a varint-encoded negative number
3169
        channel.set_readable_bytes(&[
3170
            0xF0, // Header: 15 in upper nibble (triggers varint read), List type in lower
3171
            0xFF, 0xFF, 0xFF, 0xFF, 0x0F, // Varint encoding of -1
3172
        ]);
3173
3174
        let result = protocol.read_list_begin();
3175
        assert!(result.is_err());
3176
        match result {
3177
            Err(crate::Error::Protocol(e)) => {
3178
                assert_eq!(e.kind, ProtocolErrorKind::NegativeSize);
3179
            }
3180
            _ => panic!("Expected protocol error with NegativeSize"),
3181
        }
3182
    }
3183
3184
    #[test]
3185
    fn must_enforce_container_size_limit() {
3186
        let channel = TBufferChannel::with_capacity(100, 100);
3187
        let (r_channel, mut w_channel) = channel.split().unwrap();
3188
3189
        // Create protocol with explicit container size limit
3190
        let config = TConfiguration::builder()
3191
            .max_container_size(Some(1000))
3192
            .build()
3193
            .unwrap();
3194
        let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3195
3196
        // Write header with large size
3197
        // Compact protocol: 0xF0 means size >= 15 is encoded as varint
3198
        // Then we write a varint encoding 10000 (exceeds our limit of 1000)
3199
        w_channel.set_readable_bytes(&[
3200
            0xF0, // Header: 15 in upper nibble (triggers varint read), element type in lower
3201
            0x90, 0x4E, // Varint encoding of 10000
3202
        ]);
3203
3204
        let result = protocol.read_list_begin();
3205
        assert!(result.is_err());
3206
        match result {
3207
            Err(crate::Error::Protocol(e)) => {
3208
                assert_eq!(e.kind, ProtocolErrorKind::SizeLimit);
3209
                assert!(e.message.contains("exceeds maximum allowed size"));
3210
            }
3211
            _ => panic!("Expected protocol error with SizeLimit"),
3212
        }
3213
    }
3214
3215
    #[test]
3216
    fn must_handle_varint_size_overflow() {
3217
        // Test that compact protocol properly handles varint-encoded sizes that would cause overflow
3218
        let mut channel = TBufferChannel::with_capacity(100, 100);
3219
3220
        let mut protocol = TCompactInputProtocol::new(channel.clone());
3221
3222
        // Create input that encodes a very large size using varint encoding
3223
        // 0xFA = list header with size >= 15 (so size follows as varint)
3224
        // Then multiple 0xFF bytes which in varint encoding create a very large number
3225
        channel.set_readable_bytes(&[
3226
            0xFA, // List header: size >= 15, element type = 0x0A
3227
            0xFF, 0xFF, 0xFF, 0xFF, 0x7F, // Varint encoding of a huge number
3228
        ]);
3229
3230
        let result = protocol.read_list_begin();
3231
        assert!(result.is_err());
3232
        match result {
3233
            Err(crate::Error::Protocol(e)) => {
3234
                // The varint decoder might interpret this as negative, which is also fine
3235
                assert!(
3236
                    e.kind == ProtocolErrorKind::SizeLimit
3237
                        || e.kind == ProtocolErrorKind::NegativeSize,
3238
                    "Expected SizeLimit or NegativeSize but got {:?}",
3239
                    e.kind
3240
                );
3241
            }
3242
            _ => panic!("Expected protocol error"),
3243
        }
3244
    }
3245
3246
    #[test]
3247
    fn must_enforce_string_size_limit() {
3248
        let channel = TBufferChannel::with_capacity(100, 100);
3249
        let (r_channel, mut w_channel) = channel.split().unwrap();
3250
3251
        // Create protocol with string limit of 100 bytes
3252
        let config = TConfiguration::builder()
3253
            .max_string_size(Some(100))
3254
            .build()
3255
            .unwrap();
3256
        let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3257
3258
        // Write a varint-encoded string size that exceeds the limit
3259
        w_channel.set_readable_bytes(&[
3260
            0xC8, 0x01, // Varint encoding of 200
3261
        ]);
3262
3263
        let result = protocol.read_string();
3264
        assert!(result.is_err());
3265
        match result {
3266
            Err(crate::Error::Protocol(e)) => {
3267
                assert_eq!(e.kind, ProtocolErrorKind::SizeLimit);
3268
                assert!(e.message.contains("exceeds maximum allowed size"));
3269
            }
3270
            _ => panic!("Expected protocol error with SizeLimit"),
3271
        }
3272
    }
3273
3274
    #[test]
3275
    fn must_allow_no_limit_configuration() {
3276
        let channel = TBufferChannel::with_capacity(40, 40);
3277
3278
        let config = TConfiguration::no_limits();
3279
        let mut protocol = TCompactInputProtocol::with_config(channel, config);
3280
3281
        // Should be able to nest structs deeply without limit
3282
        for _ in 0..100 {
3283
            assert!(protocol.read_struct_begin().is_ok());
3284
        }
3285
3286
        for _ in 0..100 {
3287
            assert!(protocol.read_struct_end().is_ok());
3288
        }
3289
    }
3290
3291
    #[test]
3292
    fn must_allow_containers_within_limit() {
3293
        let channel = TBufferChannel::with_capacity(200, 200);
3294
        let (r_channel, mut w_channel) = channel.split().unwrap();
3295
3296
        // Create protocol with container limit of 100
3297
        let config = TConfiguration::builder()
3298
            .max_container_size(Some(100))
3299
            .build()
3300
            .unwrap();
3301
        let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3302
3303
        // Write a list with 5 i32 elements (well within limit of 100)
3304
        // Compact protocol: size < 15 is encoded in header
3305
        w_channel.set_readable_bytes(&[
3306
            0x55, // Header: size=5, element type=5 (i32)
3307
            // 5 varint-encoded i32 values
3308
            0x0A, // 10
3309
            0x14, // 20
3310
            0x1E, // 30
3311
            0x28, // 40
3312
            0x32, // 50
3313
        ]);
3314
3315
        let result = protocol.read_list_begin();
3316
        assert!(result.is_ok());
3317
        let list_ident = result.unwrap();
3318
        assert_eq!(list_ident.size, 5);
3319
        assert_eq!(list_ident.element_type, TType::I32);
3320
    }
3321
3322
    #[test]
3323
    fn must_allow_strings_within_limit() {
3324
        let channel = TBufferChannel::with_capacity(100, 100);
3325
        let (r_channel, mut w_channel) = channel.split().unwrap();
3326
3327
        let config = TConfiguration::builder()
3328
            .max_string_size(Some(1000))
3329
            .build()
3330
            .unwrap();
3331
        let mut protocol = TCompactInputProtocol::with_config(r_channel, config);
3332
3333
        // Write a string "hello" (5 bytes, well within limit)
3334
        w_channel.set_readable_bytes(&[
3335
            0x05, // Varint-encoded length: 5
3336
            b'h', b'e', b'l', b'l', b'o',
3337
        ]);
3338
3339
        let result = protocol.read_string();
3340
        assert!(result.is_ok());
3341
        assert_eq!(result.unwrap(), "hello");
3342
    }
3343
}