1use std::{
30 cmp::Ordering,
31 io::{Read, Write},
32};
33
34use crate::{
35 errors::{ParquetError, Result},
36 write_thrift_field,
37};
38use std::io::Error;
39use std::str::Utf8Error;
40
41#[derive(Debug)]
42pub(crate) enum ThriftProtocolError {
43 Eof,
44 IO(Error),
45 InvalidFieldType(u8),
46 InvalidElementType(u8),
47 FieldDeltaOverflow { field_delta: u8, last_field_id: i16 },
48 InvalidBoolean(u8),
49 Utf8Error,
50 SkipDepth(FieldType),
51 SkipUnsupportedType(FieldType),
52}
53
54impl From<ThriftProtocolError> for ParquetError {
55 #[inline(never)]
56 fn from(e: ThriftProtocolError) -> Self {
57 match e {
58 ThriftProtocolError::Eof => eof_err!("Unexpected EOF"),
59 ThriftProtocolError::IO(e) => e.into(),
60 ThriftProtocolError::InvalidFieldType(value) => {
61 general_err!("Unexpected struct field type {}", value)
62 }
63 ThriftProtocolError::InvalidElementType(value) => {
64 general_err!("Unexpected list/set element type {}", value)
65 }
66 ThriftProtocolError::FieldDeltaOverflow {
67 field_delta,
68 last_field_id,
69 } => general_err!("cannot add {} to {}", field_delta, last_field_id),
70 ThriftProtocolError::InvalidBoolean(value) => {
71 general_err!("cannot convert {} into bool", value)
72 }
73 ThriftProtocolError::Utf8Error => general_err!("invalid utf8"),
74 ThriftProtocolError::SkipDepth(field_type) => {
75 general_err!("cannot parse past {:?}", field_type)
76 }
77 ThriftProtocolError::SkipUnsupportedType(field_type) => {
78 general_err!("cannot skip field type {:?}", field_type)
79 }
80 }
81 }
82}
83
84impl From<Utf8Error> for ThriftProtocolError {
85 fn from(_: Utf8Error) -> Self {
86 Self::Utf8Error
88 }
89}
90
91impl From<Error> for ThriftProtocolError {
92 fn from(e: Error) -> Self {
93 Self::IO(e)
94 }
95}
96
97pub type ThriftProtocolResult<T> = Result<T, ThriftProtocolError>;
98
99#[derive(Debug, Clone, Copy, PartialEq)]
103pub struct OrderedF64(f64);
104
105impl From<f64> for OrderedF64 {
106 fn from(value: f64) -> Self {
107 Self(value)
108 }
109}
110
111impl From<OrderedF64> for f64 {
112 fn from(value: OrderedF64) -> Self {
113 value.0
114 }
115}
116
117impl Eq for OrderedF64 {} impl Ord for OrderedF64 {
120 fn cmp(&self, other: &Self) -> Ordering {
121 self.0.total_cmp(&other.0)
122 }
123}
124
125impl PartialOrd for OrderedF64 {
126 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
127 Some(self.cmp(other))
128 }
129}
130
131#[derive(Clone, Copy, Debug, Eq, PartialEq)]
133pub(crate) enum FieldType {
134 Stop = 0,
135 BooleanTrue = 1,
136 BooleanFalse = 2,
137 Byte = 3,
138 I16 = 4,
139 I32 = 5,
140 I64 = 6,
141 Double = 7,
142 Binary = 8,
143 List = 9,
144 Set = 10,
145 Map = 11,
146 Struct = 12,
147}
148
149impl TryFrom<u8> for FieldType {
150 type Error = ThriftProtocolError;
151 fn try_from(value: u8) -> ThriftProtocolResult<Self> {
152 match value {
153 0 => Ok(Self::Stop),
154 1 => Ok(Self::BooleanTrue),
155 2 => Ok(Self::BooleanFalse),
156 3 => Ok(Self::Byte),
157 4 => Ok(Self::I16),
158 5 => Ok(Self::I32),
159 6 => Ok(Self::I64),
160 7 => Ok(Self::Double),
161 8 => Ok(Self::Binary),
162 9 => Ok(Self::List),
163 10 => Ok(Self::Set),
164 11 => Ok(Self::Map),
165 12 => Ok(Self::Struct),
166 _ => Err(ThriftProtocolError::InvalidFieldType(value)),
167 }
168 }
169}
170
171impl TryFrom<ElementType> for FieldType {
172 type Error = ThriftProtocolError;
173 fn try_from(value: ElementType) -> std::result::Result<Self, Self::Error> {
174 match value {
175 ElementType::Bool => Ok(Self::BooleanTrue),
176 ElementType::Byte => Ok(Self::Byte),
177 ElementType::I16 => Ok(Self::I16),
178 ElementType::I32 => Ok(Self::I32),
179 ElementType::I64 => Ok(Self::I64),
180 ElementType::Double => Ok(Self::Double),
181 ElementType::Binary => Ok(Self::Binary),
182 ElementType::List => Ok(Self::List),
183 ElementType::Struct => Ok(Self::Struct),
184 _ => Err(ThriftProtocolError::InvalidFieldType(value as u8)),
185 }
186 }
187}
188
189#[derive(Clone, Copy, Debug, Eq, PartialEq)]
191pub(crate) enum ElementType {
192 Bool = 2,
193 Byte = 3,
194 I16 = 4,
195 I32 = 5,
196 I64 = 6,
197 Double = 7,
198 Binary = 8,
199 List = 9,
200 Set = 10,
201 Map = 11,
202 Struct = 12,
203}
204
205impl TryFrom<u8> for ElementType {
206 type Error = ThriftProtocolError;
207 fn try_from(value: u8) -> ThriftProtocolResult<Self> {
208 match value {
209 1 | 2 => Ok(Self::Bool),
215 3 => Ok(Self::Byte),
216 4 => Ok(Self::I16),
217 5 => Ok(Self::I32),
218 6 => Ok(Self::I64),
219 7 => Ok(Self::Double),
220 8 => Ok(Self::Binary),
221 9 => Ok(Self::List),
222 10 => Ok(Self::Set),
223 11 => Ok(Self::Map),
224 12 => Ok(Self::Struct),
225 _ => Err(ThriftProtocolError::InvalidElementType(value)),
226 }
227 }
228}
229
230pub(crate) struct FieldIdentifier {
234 pub(crate) field_type: FieldType,
236 pub(crate) id: i16,
238 pub(crate) bool_val: Option<bool>,
243}
244
245#[derive(Clone, Debug, Eq, PartialEq)]
249pub(crate) struct ListIdentifier {
250 pub(crate) element_type: ElementType,
252 pub(crate) size: i32,
254}
255
256pub(crate) trait ThriftCompactInputProtocol<'a> {
264 fn read_byte(&mut self) -> ThriftProtocolResult<u8>;
266
267 fn read_bytes(&mut self) -> ThriftProtocolResult<&'a [u8]>;
271
272 fn read_bytes_owned(&mut self) -> ThriftProtocolResult<Vec<u8>>;
273
274 fn skip_bytes(&mut self, n: usize) -> ThriftProtocolResult<()>;
276
277 fn read_vlq(&mut self) -> ThriftProtocolResult<u64> {
279 let byte = self.read_byte()?;
281 if byte & 0x80 == 0 {
282 return Ok(byte as u64);
283 }
284 let mut in_progress = (byte & 0x7f) as u64;
285 let mut shift = 7;
286 loop {
287 let byte = self.read_byte()?;
288 in_progress |= ((byte & 0x7F) as u64).wrapping_shl(shift);
289 if byte & 0x80 == 0 {
290 return Ok(in_progress);
291 }
292 shift += 7;
293 }
294 }
295
296 fn read_zig_zag(&mut self) -> ThriftProtocolResult<i64> {
298 let val = self.read_vlq()?;
299 Ok((val >> 1) as i64 ^ -((val & 1) as i64))
300 }
301
302 fn read_list_begin(&mut self) -> ThriftProtocolResult<ListIdentifier> {
304 let header = self.read_byte()?;
305 if header == 0 {
308 return Ok(ListIdentifier {
309 element_type: ElementType::Byte,
310 size: 0,
311 });
312 }
313 let element_type = ElementType::try_from(header & 0x0f)?;
314
315 let possible_element_count = (header & 0xF0) >> 4;
316 let element_count = if possible_element_count != 15 {
317 possible_element_count as i32
319 } else {
320 self.read_vlq()? as _
321 };
322
323 Ok(ListIdentifier {
324 element_type,
325 size: element_count,
326 })
327 }
328
329 #[cold]
333 fn read_full_field_id(&mut self) -> ThriftProtocolResult<i16> {
334 self.read_i16()
335 }
336
337 fn read_field_begin(&mut self, last_field_id: i16) -> ThriftProtocolResult<FieldIdentifier> {
339 let field_type = self.read_byte()?;
343 let field_delta = (field_type & 0xf0) >> 4;
344 let field_type = FieldType::try_from(field_type & 0xf)?;
345 let mut bool_val: Option<bool> = None;
346
347 match field_type {
348 FieldType::Stop => Ok(FieldIdentifier {
349 field_type: FieldType::Stop,
350 id: 0,
351 bool_val,
352 }),
353 _ => {
354 if field_type == FieldType::BooleanFalse {
356 bool_val = Some(false);
357 } else if field_type == FieldType::BooleanTrue {
358 bool_val = Some(true);
359 }
360 let field_id = if field_delta != 0 {
361 last_field_id.checked_add(field_delta as i16).ok_or(
362 ThriftProtocolError::FieldDeltaOverflow {
363 field_delta,
364 last_field_id,
365 },
366 )?
367 } else {
368 self.read_full_field_id()?
369 };
370
371 Ok(FieldIdentifier {
372 field_type,
373 id: field_id,
374 bool_val,
375 })
376 }
377 }
378 }
379
380 fn read_field_header(&mut self) -> ThriftProtocolResult<(u8, u8)> {
387 let field_type = self.read_byte()?;
388 let field_delta = (field_type & 0xf0) >> 4;
389 let field_type = field_type & 0xf;
390 Ok((field_type, field_delta))
391 }
392
393 fn read_bool(&mut self) -> ThriftProtocolResult<bool> {
396 let b = self.read_byte()?;
397 match b {
402 0x01 => Ok(true),
403 0x00 | 0x02 => Ok(false),
404 _ => Err(ThriftProtocolError::InvalidBoolean(b)),
405 }
406 }
407
408 fn read_string(&mut self) -> ThriftProtocolResult<&'a str> {
412 let slice = self.read_bytes()?;
413 Ok(std::str::from_utf8(slice)?)
414 }
415
416 fn read_i8(&mut self) -> ThriftProtocolResult<i8> {
418 Ok(self.read_byte()? as _)
419 }
420
421 fn read_i16(&mut self) -> ThriftProtocolResult<i16> {
423 Ok(self.read_zig_zag()? as _)
424 }
425
426 fn read_i32(&mut self) -> ThriftProtocolResult<i32> {
428 Ok(self.read_zig_zag()? as _)
429 }
430
431 fn read_i64(&mut self) -> ThriftProtocolResult<i64> {
433 self.read_zig_zag()
434 }
435
436 fn read_double(&mut self) -> ThriftProtocolResult<f64>;
438
439 fn skip_vlq(&mut self) -> ThriftProtocolResult<()> {
441 loop {
442 let byte = self.read_byte()?;
443 if byte & 0x80 == 0 {
444 return Ok(());
445 }
446 }
447 }
448
449 fn skip_binary(&mut self) -> ThriftProtocolResult<()> {
453 let len = self.read_vlq()? as usize;
454 self.skip_bytes(len)
455 }
456
457 fn skip(&mut self, field_type: FieldType) -> ThriftProtocolResult<()> {
460 const DEFAULT_SKIP_DEPTH: i8 = 64;
461 self.skip_till_depth(field_type, DEFAULT_SKIP_DEPTH)
462 }
463
464 fn skip_empty_struct(&mut self) -> Result<()> {
468 let b = self.read_byte()?;
469 if b != 0 {
470 Err(general_err!("Empty struct has fields"))
471 } else {
472 Ok(())
473 }
474 }
475
476 fn skip_till_depth(&mut self, field_type: FieldType, depth: i8) -> ThriftProtocolResult<()> {
478 if depth == 0 {
479 return Err(ThriftProtocolError::SkipDepth(field_type));
480 }
481
482 match field_type {
483 FieldType::BooleanFalse | FieldType::BooleanTrue => Ok(()),
485 FieldType::Byte => self.read_i8().map(|_| ()),
486 FieldType::I16 => self.skip_vlq().map(|_| ()),
487 FieldType::I32 => self.skip_vlq().map(|_| ()),
488 FieldType::I64 => self.skip_vlq().map(|_| ()),
489 FieldType::Double => self.skip_bytes(8).map(|_| ()),
490 FieldType::Binary => self.skip_binary().map(|_| ()),
491 FieldType::Struct => {
492 let mut last_field_id = 0i16;
493 loop {
494 let field_ident = self.read_field_begin(last_field_id)?;
495 if field_ident.field_type == FieldType::Stop {
496 break;
497 }
498 self.skip_till_depth(field_ident.field_type, depth - 1)?;
499 last_field_id = field_ident.id;
500 }
501 Ok(())
502 }
503 FieldType::List => {
504 let list_ident = self.read_list_begin()?;
505 for _ in 0..list_ident.size {
506 let element_type = FieldType::try_from(list_ident.element_type)?;
507 self.skip_till_depth(element_type, depth - 1)?;
508 }
509 Ok(())
510 }
511 _ => Err(ThriftProtocolError::SkipUnsupportedType(field_type)),
513 }
514 }
515}
516
517pub(crate) struct ThriftSliceInputProtocol<'a> {
519 buf: &'a [u8],
520}
521
522impl<'a> ThriftSliceInputProtocol<'a> {
523 pub fn new(buf: &'a [u8]) -> Self {
525 Self { buf }
526 }
527
528 pub fn as_slice(&self) -> &'a [u8] {
530 self.buf
531 }
532}
533
534impl<'b, 'a: 'b> ThriftCompactInputProtocol<'b> for ThriftSliceInputProtocol<'a> {
535 #[inline]
536 fn read_byte(&mut self) -> ThriftProtocolResult<u8> {
537 let ret = *self.buf.first().ok_or(ThriftProtocolError::Eof)?;
538 self.buf = &self.buf[1..];
539 Ok(ret)
540 }
541
542 fn read_bytes(&mut self) -> ThriftProtocolResult<&'b [u8]> {
543 let len = self.read_vlq()? as usize;
544 let ret = self.buf.get(..len).ok_or(ThriftProtocolError::Eof)?;
545 self.buf = &self.buf[len..];
546 Ok(ret)
547 }
548
549 fn read_bytes_owned(&mut self) -> ThriftProtocolResult<Vec<u8>> {
550 Ok(self.read_bytes()?.to_vec())
551 }
552
553 #[inline]
554 fn skip_bytes(&mut self, n: usize) -> ThriftProtocolResult<()> {
555 self.buf.get(..n).ok_or(ThriftProtocolError::Eof)?;
556 self.buf = &self.buf[n..];
557 Ok(())
558 }
559
560 fn read_double(&mut self) -> ThriftProtocolResult<f64> {
561 let slice = self.buf.get(..8).ok_or(ThriftProtocolError::Eof)?;
562 self.buf = &self.buf[8..];
563 match slice.try_into() {
564 Ok(slice) => Ok(f64::from_le_bytes(slice)),
565 Err(_) => unreachable!(),
566 }
567 }
568}
569
570pub(crate) struct ThriftReadInputProtocol<R: Read> {
575 reader: R,
576}
577
578impl<R: Read> ThriftReadInputProtocol<R> {
579 pub(crate) fn new(reader: R) -> Self {
580 Self { reader }
581 }
582}
583
584impl<'a, R: Read> ThriftCompactInputProtocol<'a> for ThriftReadInputProtocol<R> {
585 #[inline]
586 fn read_byte(&mut self) -> ThriftProtocolResult<u8> {
587 let mut buf = [0_u8; 1];
588 self.reader.read_exact(&mut buf)?;
589 Ok(buf[0])
590 }
591
592 fn read_bytes(&mut self) -> ThriftProtocolResult<&'a [u8]> {
593 unimplemented!()
594 }
595
596 fn read_bytes_owned(&mut self) -> ThriftProtocolResult<Vec<u8>> {
597 let len = self.read_vlq()? as usize;
598 let mut v = Vec::with_capacity(len);
599 std::io::copy(&mut self.reader.by_ref().take(len as u64), &mut v)?;
600 Ok(v)
601 }
602
603 fn skip_bytes(&mut self, n: usize) -> ThriftProtocolResult<()> {
604 std::io::copy(
605 &mut self.reader.by_ref().take(n as u64),
606 &mut std::io::sink(),
607 )?;
608 Ok(())
609 }
610
611 fn read_double(&mut self) -> ThriftProtocolResult<f64> {
612 let mut buf = [0_u8; 8];
613 self.reader.read_exact(&mut buf)?;
614 Ok(f64::from_le_bytes(buf))
615 }
616}
617
618pub(crate) trait ReadThrift<'a, R: ThriftCompactInputProtocol<'a>> {
621 fn read_thrift(prot: &mut R) -> Result<Self>
623 where
624 Self: Sized;
625}
626
627impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for bool {
628 fn read_thrift(prot: &mut R) -> Result<Self> {
629 Ok(prot.read_bool()?)
630 }
631}
632
633impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for i8 {
634 fn read_thrift(prot: &mut R) -> Result<Self> {
635 Ok(prot.read_i8()?)
636 }
637}
638
639impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for i16 {
640 fn read_thrift(prot: &mut R) -> Result<Self> {
641 Ok(prot.read_i16()?)
642 }
643}
644
645impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for i32 {
646 fn read_thrift(prot: &mut R) -> Result<Self> {
647 Ok(prot.read_i32()?)
648 }
649}
650
651impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for i64 {
652 fn read_thrift(prot: &mut R) -> Result<Self> {
653 Ok(prot.read_i64()?)
654 }
655}
656
657impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for OrderedF64 {
658 fn read_thrift(prot: &mut R) -> Result<Self> {
659 Ok(OrderedF64(prot.read_double()?))
660 }
661}
662
663impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for &'a str {
664 fn read_thrift(prot: &mut R) -> Result<Self> {
665 Ok(prot.read_string()?)
666 }
667}
668
669impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for String {
670 fn read_thrift(prot: &mut R) -> Result<Self> {
671 Ok(String::from_utf8(prot.read_bytes_owned()?)?)
672 }
673}
674
675impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for &'a [u8] {
676 fn read_thrift(prot: &mut R) -> Result<Self> {
677 Ok(prot.read_bytes()?)
678 }
679}
680
681pub(crate) fn read_thrift_vec<'a, T, R>(prot: &mut R) -> Result<Vec<T>>
685where
686 R: ThriftCompactInputProtocol<'a>,
687 T: ReadThrift<'a, R>,
688{
689 let list_ident = prot.read_list_begin()?;
690 let mut res = Vec::with_capacity(list_ident.size as usize);
691 for _ in 0..list_ident.size {
692 let val = T::read_thrift(prot)?;
693 res.push(val);
694 }
695 Ok(res)
696}
697
698pub(crate) struct ThriftCompactOutputProtocol<W: Write> {
710 writer: W,
711}
712
713impl<W: Write> ThriftCompactOutputProtocol<W> {
714 pub(crate) fn new(writer: W) -> Self {
716 Self { writer }
717 }
718
719 fn write_byte(&mut self, b: u8) -> Result<()> {
721 self.writer.write_all(&[b])?;
722 Ok(())
723 }
724
725 fn write_vlq(&mut self, val: u64) -> Result<()> {
727 let mut v = val;
728 while v > 0x7f {
729 self.write_byte(v as u8 | 0x80)?;
730 v >>= 7;
731 }
732 self.write_byte(v as u8)
733 }
734
735 fn write_zig_zag(&mut self, val: i64) -> Result<()> {
737 let s = (val < 0) as i64;
738 self.write_vlq((((val ^ -s) << 1) + s) as u64)
739 }
740
741 pub(crate) fn write_field_begin(
746 &mut self,
747 field_type: FieldType,
748 field_id: i16,
749 last_field_id: i16,
750 ) -> Result<()> {
751 let delta = field_id.wrapping_sub(last_field_id);
752 if delta > 0 && delta <= 0xf {
753 self.write_byte((delta as u8) << 4 | field_type as u8)
754 } else {
755 self.write_byte(field_type as u8)?;
756 self.write_i16(field_id)
757 }
758 }
759
760 pub(crate) fn write_list_begin(&mut self, element_type: ElementType, len: usize) -> Result<()> {
762 if len < 15 {
763 self.write_byte((len as u8) << 4 | element_type as u8)
764 } else {
765 self.write_byte(0xf0u8 | element_type as u8)?;
766 self.write_vlq(len as _)
767 }
768 }
769
770 pub(crate) fn write_struct_end(&mut self) -> Result<()> {
773 self.write_byte(0)
774 }
775
776 pub(crate) fn write_bytes(&mut self, val: &[u8]) -> Result<()> {
779 self.write_vlq(val.len() as u64)?;
780 self.writer.write_all(val)?;
781 Ok(())
782 }
783
784 pub(crate) fn write_empty_struct(&mut self, field_id: i16, last_field_id: i16) -> Result<i16> {
787 self.write_field_begin(FieldType::Struct, field_id, last_field_id)?;
788 self.write_struct_end()?;
789 Ok(last_field_id)
790 }
791
792 pub(crate) fn write_bool(&mut self, val: bool) -> Result<()> {
794 match val {
795 true => self.write_byte(1),
796 false => self.write_byte(2),
797 }
798 }
799
800 pub(crate) fn write_i8(&mut self, val: i8) -> Result<()> {
802 self.write_byte(val as u8)
803 }
804
805 pub(crate) fn write_i16(&mut self, val: i16) -> Result<()> {
807 self.write_zig_zag(val as _)
808 }
809
810 pub(crate) fn write_i32(&mut self, val: i32) -> Result<()> {
812 self.write_zig_zag(val as _)
813 }
814
815 pub(crate) fn write_i64(&mut self, val: i64) -> Result<()> {
817 self.write_zig_zag(val as _)
818 }
819
820 pub(crate) fn write_double(&mut self, val: f64) -> Result<()> {
822 self.writer.write_all(&val.to_le_bytes())?;
823 Ok(())
824 }
825}
826
827pub(crate) trait WriteThrift {
832 const ELEMENT_TYPE: ElementType;
834
835 fn write_thrift<W: Write>(&self, writer: &mut ThriftCompactOutputProtocol<W>) -> Result<()>;
837}
838
839impl<T> WriteThrift for Vec<T>
842where
843 T: WriteThrift,
844{
845 const ELEMENT_TYPE: ElementType = ElementType::List;
846
847 fn write_thrift<W: Write>(&self, writer: &mut ThriftCompactOutputProtocol<W>) -> Result<()> {
848 writer.write_list_begin(T::ELEMENT_TYPE, self.len())?;
849 for item in self {
850 item.write_thrift(writer)?;
851 }
852 Ok(())
853 }
854}
855
856impl WriteThrift for bool {
857 const ELEMENT_TYPE: ElementType = ElementType::Bool;
858
859 fn write_thrift<W: Write>(&self, writer: &mut ThriftCompactOutputProtocol<W>) -> Result<()> {
860 writer.write_bool(*self)
861 }
862}
863
864impl WriteThrift for i8 {
865 const ELEMENT_TYPE: ElementType = ElementType::Byte;
866
867 fn write_thrift<W: Write>(&self, writer: &mut ThriftCompactOutputProtocol<W>) -> Result<()> {
868 writer.write_i8(*self)
869 }
870}
871
872impl WriteThrift for i16 {
873 const ELEMENT_TYPE: ElementType = ElementType::I16;
874
875 fn write_thrift<W: Write>(&self, writer: &mut ThriftCompactOutputProtocol<W>) -> Result<()> {
876 writer.write_i16(*self)
877 }
878}
879
880impl WriteThrift for i32 {
881 const ELEMENT_TYPE: ElementType = ElementType::I32;
882
883 fn write_thrift<W: Write>(&self, writer: &mut ThriftCompactOutputProtocol<W>) -> Result<()> {
884 writer.write_i32(*self)
885 }
886}
887
888impl WriteThrift for i64 {
889 const ELEMENT_TYPE: ElementType = ElementType::I64;
890
891 fn write_thrift<W: Write>(&self, writer: &mut ThriftCompactOutputProtocol<W>) -> Result<()> {
892 writer.write_i64(*self)
893 }
894}
895
896impl WriteThrift for OrderedF64 {
897 const ELEMENT_TYPE: ElementType = ElementType::Double;
898
899 fn write_thrift<W: Write>(&self, writer: &mut ThriftCompactOutputProtocol<W>) -> Result<()> {
900 writer.write_double(self.0)
901 }
902}
903
904impl WriteThrift for f64 {
905 const ELEMENT_TYPE: ElementType = ElementType::Double;
906
907 fn write_thrift<W: Write>(&self, writer: &mut ThriftCompactOutputProtocol<W>) -> Result<()> {
908 writer.write_double(*self)
909 }
910}
911
912impl WriteThrift for &[u8] {
913 const ELEMENT_TYPE: ElementType = ElementType::Binary;
914
915 fn write_thrift<W: Write>(&self, writer: &mut ThriftCompactOutputProtocol<W>) -> Result<()> {
916 writer.write_bytes(self)
917 }
918}
919
920impl WriteThrift for &str {
921 const ELEMENT_TYPE: ElementType = ElementType::Binary;
922
923 fn write_thrift<W: Write>(&self, writer: &mut ThriftCompactOutputProtocol<W>) -> Result<()> {
924 writer.write_bytes(self.as_bytes())
925 }
926}
927
928impl WriteThrift for String {
929 const ELEMENT_TYPE: ElementType = ElementType::Binary;
930
931 fn write_thrift<W: Write>(&self, writer: &mut ThriftCompactOutputProtocol<W>) -> Result<()> {
932 writer.write_bytes(self.as_bytes())
933 }
934}
935
936pub(crate) trait WriteThriftField {
979 fn write_thrift_field<W: Write>(
986 &self,
987 writer: &mut ThriftCompactOutputProtocol<W>,
988 field_id: i16,
989 last_field_id: i16,
990 ) -> Result<i16>;
991}
992
993impl WriteThriftField for bool {
995 fn write_thrift_field<W: Write>(
996 &self,
997 writer: &mut ThriftCompactOutputProtocol<W>,
998 field_id: i16,
999 last_field_id: i16,
1000 ) -> Result<i16> {
1001 match *self {
1003 true => writer.write_field_begin(FieldType::BooleanTrue, field_id, last_field_id)?,
1004 false => writer.write_field_begin(FieldType::BooleanFalse, field_id, last_field_id)?,
1005 }
1006 Ok(field_id)
1007 }
1008}
1009
1010write_thrift_field!(i8, FieldType::Byte);
1011write_thrift_field!(i16, FieldType::I16);
1012write_thrift_field!(i32, FieldType::I32);
1013write_thrift_field!(i64, FieldType::I64);
1014write_thrift_field!(OrderedF64, FieldType::Double);
1015write_thrift_field!(f64, FieldType::Double);
1016write_thrift_field!(String, FieldType::Binary);
1017
1018impl WriteThriftField for &[u8] {
1019 fn write_thrift_field<W: Write>(
1020 &self,
1021 writer: &mut ThriftCompactOutputProtocol<W>,
1022 field_id: i16,
1023 last_field_id: i16,
1024 ) -> Result<i16> {
1025 writer.write_field_begin(FieldType::Binary, field_id, last_field_id)?;
1026 writer.write_bytes(self)?;
1027 Ok(field_id)
1028 }
1029}
1030
1031impl WriteThriftField for &str {
1032 fn write_thrift_field<W: Write>(
1033 &self,
1034 writer: &mut ThriftCompactOutputProtocol<W>,
1035 field_id: i16,
1036 last_field_id: i16,
1037 ) -> Result<i16> {
1038 writer.write_field_begin(FieldType::Binary, field_id, last_field_id)?;
1039 writer.write_bytes(self.as_bytes())?;
1040 Ok(field_id)
1041 }
1042}
1043
1044impl<T> WriteThriftField for Vec<T>
1045where
1046 T: WriteThrift,
1047{
1048 fn write_thrift_field<W: Write>(
1049 &self,
1050 writer: &mut ThriftCompactOutputProtocol<W>,
1051 field_id: i16,
1052 last_field_id: i16,
1053 ) -> Result<i16> {
1054 writer.write_field_begin(FieldType::List, field_id, last_field_id)?;
1055 self.write_thrift(writer)?;
1056 Ok(field_id)
1057 }
1058}
1059
1060#[cfg(test)]
1061pub(crate) mod tests {
1062 use crate::basic::{TimeUnit, Type};
1063
1064 use super::*;
1065 use std::fmt::Debug;
1066
1067 pub(crate) fn test_roundtrip<T>(val: T)
1068 where
1069 T: for<'a> ReadThrift<'a, ThriftSliceInputProtocol<'a>> + WriteThrift + PartialEq + Debug,
1070 {
1071 let mut buf = Vec::<u8>::new();
1072 {
1073 let mut writer = ThriftCompactOutputProtocol::new(&mut buf);
1074 val.write_thrift(&mut writer).unwrap();
1075 }
1076
1077 let mut prot = ThriftSliceInputProtocol::new(&buf);
1078 let read_val = T::read_thrift(&mut prot).unwrap();
1079 assert_eq!(val, read_val);
1080 }
1081
1082 #[test]
1083 fn test_enum_roundtrip() {
1084 test_roundtrip(Type::BOOLEAN);
1085 test_roundtrip(Type::INT32);
1086 test_roundtrip(Type::INT64);
1087 test_roundtrip(Type::INT96);
1088 test_roundtrip(Type::FLOAT);
1089 test_roundtrip(Type::DOUBLE);
1090 test_roundtrip(Type::BYTE_ARRAY);
1091 test_roundtrip(Type::FIXED_LEN_BYTE_ARRAY);
1092 }
1093
1094 #[test]
1095 fn test_union_all_empty_roundtrip() {
1096 test_roundtrip(TimeUnit::MILLIS);
1097 test_roundtrip(TimeUnit::MICROS);
1098 test_roundtrip(TimeUnit::NANOS);
1099 }
1100
1101 #[test]
1102 fn test_decode_empty_list() {
1103 let data = vec![0u8; 1];
1104 let mut prot = ThriftSliceInputProtocol::new(&data);
1105 let header = prot.read_list_begin().expect("error reading list header");
1106 assert_eq!(header.size, 0);
1107 assert_eq!(header.element_type, ElementType::Byte);
1108 }
1109}