Skip to main content

thrift/protocol/
compact.rs

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