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