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