From 8b690d73b7f2851d3df5107bd5208d620649d053 Mon Sep 17 00:00:00 2001 From: Ed Seidl Date: Mon, 4 May 2026 17:27:25 -0700 Subject: [PATCH 1/8] add element type checking to thrift list decoding --- parquet/src/basic.rs | 10 ++++++++++ parquet/src/parquet_macros.rs | 8 ++++++++ parquet/src/parquet_thrift.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/parquet/src/basic.rs b/parquet/src/basic.rs index ba8ffc2e92c3..a0147c27f0fb 100644 --- a/parquet/src/basic.rs +++ b/parquet/src/basic.rs @@ -315,6 +315,8 @@ pub enum LogicalType { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for LogicalType { + const ELEMENT_TYPE: ElementType = ElementType::Struct; + fn read_thrift(prot: &mut R) -> Result { let field_ident = prot.read_field_begin(0)?; if field_ident.field_type == FieldType::Stop { @@ -766,6 +768,8 @@ impl HeapSize for EncodingMask { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for EncodingMask { + const ELEMENT_TYPE: ElementType = ElementType::I32; + fn read_thrift(prot: &mut R) -> Result { let mut mask = 0; @@ -835,6 +839,8 @@ pub enum Compression { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for Compression { + const ELEMENT_TYPE: ElementType = ElementType::I32; + fn read_thrift(prot: &mut R) -> Result { let val = prot.read_i32()?; Ok(match val { @@ -1076,6 +1082,8 @@ impl FromStr for EdgeInterpolationAlgorithm { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for EdgeInterpolationAlgorithm { + const ELEMENT_TYPE: ElementType = ElementType::I32; + fn read_thrift(prot: &mut R) -> Result { let val = prot.read_i32()?; match val { @@ -1304,6 +1312,8 @@ impl ColumnOrder { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for ColumnOrder { + const ELEMENT_TYPE: ElementType = ElementType::Struct; + fn read_thrift(prot: &mut R) -> Result { let field_ident = prot.read_field_begin(0)?; if field_ident.field_type == FieldType::Stop { diff --git a/parquet/src/parquet_macros.rs b/parquet/src/parquet_macros.rs index 13c476343164..a881453f714f 100644 --- a/parquet/src/parquet_macros.rs +++ b/parquet/src/parquet_macros.rs @@ -50,6 +50,8 @@ macro_rules! thrift_enum { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for $identifier { + const ELEMENT_TYPE: ElementType = ElementType::I32; + #[allow(deprecated)] fn read_thrift(prot: &mut R) -> Result { let val = prot.read_i32()?; @@ -140,6 +142,8 @@ macro_rules! thrift_union_all_empty { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for $identifier { + const ELEMENT_TYPE: ElementType = ElementType::Struct; + fn read_thrift(prot: &mut R) -> Result { let field_ident = prot.read_field_begin(0)?; if field_ident.field_type == FieldType::Stop { @@ -214,6 +218,8 @@ macro_rules! thrift_union { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for $identifier $(<$lt>)? { + const ELEMENT_TYPE: ElementType = ElementType::Struct; + fn read_thrift(prot: &mut R) -> Result { let field_ident = prot.read_field_begin(0)?; if field_ident.field_type == FieldType::Stop { @@ -281,6 +287,8 @@ macro_rules! thrift_struct { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for $identifier $(<$lt>)? { + const ELEMENT_TYPE: ElementType = ElementType::Struct; + fn read_thrift(prot: &mut R) -> Result { $(let mut $field_name: Option<$crate::__thrift_field_type!($field_type $($field_lt)? $($element_type)?)> = None;)* let mut last_field_id = 0i16; diff --git a/parquet/src/parquet_thrift.rs b/parquet/src/parquet_thrift.rs index a13baa0924e0..3bcdeab72ae7 100644 --- a/parquet/src/parquet_thrift.rs +++ b/parquet/src/parquet_thrift.rs @@ -636,6 +636,9 @@ impl<'a, R: Read> ThriftCompactInputProtocol<'a> for ThriftReadInputProtocol /// Trait implemented for objects that can be deserialized from a Thrift input stream. /// Implementations are provided for Thrift primitive types. pub(crate) trait ReadThrift<'a, R: ThriftCompactInputProtocol<'a>> { + /// The [`ElementType`] to use when a list of this object is read. + const ELEMENT_TYPE: ElementType; + /// Read an object of type `Self` from the input protocol object. fn read_thrift(prot: &mut R) -> Result where @@ -643,54 +646,72 @@ pub(crate) trait ReadThrift<'a, R: ThriftCompactInputProtocol<'a>> { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for bool { + const ELEMENT_TYPE: ElementType = ElementType::Bool; + fn read_thrift(prot: &mut R) -> Result { Ok(prot.read_bool()?) } } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for i8 { + const ELEMENT_TYPE: ElementType = ElementType::Byte; + fn read_thrift(prot: &mut R) -> Result { Ok(prot.read_i8()?) } } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for i16 { + const ELEMENT_TYPE: ElementType = ElementType::I16; + fn read_thrift(prot: &mut R) -> Result { Ok(prot.read_i16()?) } } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for i32 { + const ELEMENT_TYPE: ElementType = ElementType::I32; + fn read_thrift(prot: &mut R) -> Result { Ok(prot.read_i32()?) } } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for i64 { + const ELEMENT_TYPE: ElementType = ElementType::I64; + fn read_thrift(prot: &mut R) -> Result { Ok(prot.read_i64()?) } } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for OrderedF64 { + const ELEMENT_TYPE: ElementType = ElementType::Double; + fn read_thrift(prot: &mut R) -> Result { Ok(OrderedF64(prot.read_double()?)) } } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for &'a str { + const ELEMENT_TYPE: ElementType = ElementType::Binary; + fn read_thrift(prot: &mut R) -> Result { Ok(prot.read_string()?) } } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for String { + const ELEMENT_TYPE: ElementType = ElementType::Binary; + fn read_thrift(prot: &mut R) -> Result { Ok(String::from_utf8(prot.read_bytes_owned()?)?) } } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for &'a [u8] { + const ELEMENT_TYPE: ElementType = ElementType::Binary; + fn read_thrift(prot: &mut R) -> Result { Ok(prot.read_bytes()?) } @@ -705,6 +726,13 @@ where T: ReadThrift<'a, R>, { let list_ident = prot.read_list_begin()?; + if list_ident.element_type != T::ELEMENT_TYPE { + return Err(general_err!( + "Expected list element type of {:?} but got {:?}", + T::ELEMENT_TYPE, + list_ident.element_type + )); + } let mut res = Vec::with_capacity(list_ident.size as usize); for _ in 0..list_ident.size { let val = T::read_thrift(prot)?; From 6590d514ef7b7e479eca47fa170b79025a4a0d7e Mon Sep 17 00:00:00 2001 From: Ed Seidl Date: Mon, 4 May 2026 17:28:18 -0700 Subject: [PATCH 2/8] fix test for earlier error detection --- parquet/src/file/serialized_reader.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parquet/src/file/serialized_reader.rs b/parquet/src/file/serialized_reader.rs index 254ccb779a4a..4b71e3c14e6d 100644 --- a/parquet/src/file/serialized_reader.rs +++ b/parquet/src/file/serialized_reader.rs @@ -2117,7 +2117,7 @@ mod tests { let ret = SerializedFileReader::new(Bytes::copy_from_slice(&data)); assert_eq!( ret.err().unwrap().to_string(), - "Parquet error: Received empty union from remote ColumnOrder" + "Parquet error: Expected list element type of Struct but got List" ); } From 64383c08bcc4eeef11796db94dfec4b698aa3682 Mon Sep 17 00:00:00 2001 From: Ed Seidl Date: Tue, 5 May 2026 11:32:26 -0700 Subject: [PATCH 3/8] add some more list checks where lists are manually decoded --- parquet/src/basic.rs | 7 +++++++ parquet/src/file/metadata/thrift/mod.rs | 21 +++++++++++++++++++++ parquet/src/file/page_index/offset_index.rs | 6 ++++++ 3 files changed, 34 insertions(+) diff --git a/parquet/src/basic.rs b/parquet/src/basic.rs index a0147c27f0fb..5b5951b34789 100644 --- a/parquet/src/basic.rs +++ b/parquet/src/basic.rs @@ -775,6 +775,13 @@ impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for EncodingMask { // This reads a Thrift `list` and turns it into a bitmask let list_ident = prot.read_list_begin()?; + // check for enum (encoded as I32) + if list_ident.element_type != ElementType::I32 { + return Err(general_err!( + "Expected list element type of Encoding but got {:?}", + list_ident.element_type + )); + } for _ in 0..list_ident.size { let val = Encoding::read_thrift(prot)?; mask |= 1 << val as i32; diff --git a/parquet/src/file/metadata/thrift/mod.rs b/parquet/src/file/metadata/thrift/mod.rs index ad8f6312c215..25e4515782c3 100644 --- a/parquet/src/file/metadata/thrift/mod.rs +++ b/parquet/src/file/metadata/thrift/mod.rs @@ -387,6 +387,13 @@ fn read_encoding_stats_as_mask<'a>( // read the vector of stats, setting mask bits for data pages let mut mask = 0i32; let list_ident = prot.read_list_begin()?; + // check for enum (encoded as I32) + if list_ident.element_type != ElementType::I32 { + return Err(general_err!( + "Expected list element type of Encoding but got {:?}", + list_ident.element_type + )); + } for _ in 0..list_ident.size { let pes = PageEncodingStats::read_thrift(prot)?; match pes.page_type { @@ -652,6 +659,13 @@ fn read_row_group( match field_ident.id { 1 => { let list_ident = prot.read_list_begin()?; + // check for list of struct + if list_ident.element_type != ElementType::Struct { + return Err(general_err!( + "Expected list element type of Struct but got {:?}", + list_ident.element_type + )); + } if schema_descr.num_columns() != list_ident.size as usize { return Err(general_err!( "Column count mismatch. Schema has {} columns while Row Group has {}", @@ -801,6 +815,13 @@ pub(crate) fn parquet_metadata_from_bytes( } let schema_descr = schema_descr.as_ref().unwrap(); let list_ident = prot.read_list_begin()?; + // check for list of struct + if list_ident.element_type != ElementType::Struct { + return Err(general_err!( + "Expected list element type of Struct but got {:?}", + list_ident.element_type + )); + } let mut rg_vec = Vec::with_capacity(list_ident.size as usize); // Read row groups and handle ordinal assignment diff --git a/parquet/src/file/page_index/offset_index.rs b/parquet/src/file/page_index/offset_index.rs index b1e30dd4590c..83cde3a0adc5 100644 --- a/parquet/src/file/page_index/offset_index.rs +++ b/parquet/src/file/page_index/offset_index.rs @@ -90,6 +90,12 @@ impl OffsetIndexMetaData { // we have to do this manually because we want to use the fast PageLocation decoder let list_ident = prot.read_list_begin()?; + if list_ident.element_type != ElementType::Struct { + return Err(general_err!( + "Expected list element type of Struct but got {:?}", + list_ident.element_type + )); + } let mut page_locations = Vec::with_capacity(list_ident.size as usize); for _ in 0..list_ident.size { page_locations.push(read_page_location(prot)?); From 37f377296aa704fa6ec6e8a3383f2251b2666e34 Mon Sep 17 00:00:00 2001 From: Ed Seidl Date: Tue, 5 May 2026 11:47:40 -0700 Subject: [PATCH 4/8] add test --- parquet/src/parquet_thrift.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/parquet/src/parquet_thrift.rs b/parquet/src/parquet_thrift.rs index 3bcdeab72ae7..c508e5dcfab2 100644 --- a/parquet/src/parquet_thrift.rs +++ b/parquet/src/parquet_thrift.rs @@ -1166,4 +1166,20 @@ pub(crate) mod tests { let result = prot.read_list_begin(); assert!(result.is_err(), "expected error, got {result:?}"); } + + #[test] + fn test_read_list_wrong_type() { + // list header: 4 elements of `Boolean` + let data = [0x42, 0x01]; + let mut prot = ThriftSliceInputProtocol::new(&data); + // try to read as list + let result = read_thrift_vec::(&mut prot); + println!("{result:?}"); + assert!( + result + .unwrap_err() + .to_string() + .contains("Expected list element type of I32 but got Bool") + ); + } } From bd9589029c3485dedfc32fc97a7208c2d9e69838 Mon Sep 17 00:00:00 2001 From: Ed Seidl Date: Tue, 5 May 2026 11:59:12 -0700 Subject: [PATCH 5/8] add helper to reduce bloat --- parquet/src/file/metadata/thrift/mod.rs | 26 +++++---------------- parquet/src/file/page_index/offset_index.rs | 9 ++----- parquet/src/parquet_thrift.rs | 19 +++++++++------ 3 files changed, 20 insertions(+), 34 deletions(-) diff --git a/parquet/src/file/metadata/thrift/mod.rs b/parquet/src/file/metadata/thrift/mod.rs index 25e4515782c3..b138de319368 100644 --- a/parquet/src/file/metadata/thrift/mod.rs +++ b/parquet/src/file/metadata/thrift/mod.rs @@ -51,7 +51,7 @@ use crate::{ parquet_thrift::{ ElementType, FieldType, ReadThrift, ThriftCompactInputProtocol, ThriftCompactOutputProtocol, ThriftSliceInputProtocol, WriteThrift, WriteThriftField, - read_thrift_vec, + read_thrift_vec, validate_list_type, }, schema::types::{ ColumnDescriptor, SchemaDescriptor, TypePtr, num_nodes, parquet_schema_from_array, @@ -387,13 +387,9 @@ fn read_encoding_stats_as_mask<'a>( // read the vector of stats, setting mask bits for data pages let mut mask = 0i32; let list_ident = prot.read_list_begin()?; - // check for enum (encoded as I32) - if list_ident.element_type != ElementType::I32 { - return Err(general_err!( - "Expected list element type of Encoding but got {:?}", - list_ident.element_type - )); - } + // check for PageEncodingStats struct + validate_list_type(ElementType::Struct, &list_ident)?; + for _ in 0..list_ident.size { let pes = PageEncodingStats::read_thrift(prot)?; match pes.page_type { @@ -660,12 +656,7 @@ fn read_row_group( 1 => { let list_ident = prot.read_list_begin()?; // check for list of struct - if list_ident.element_type != ElementType::Struct { - return Err(general_err!( - "Expected list element type of Struct but got {:?}", - list_ident.element_type - )); - } + validate_list_type(ElementType::Struct, &list_ident)?; if schema_descr.num_columns() != list_ident.size as usize { return Err(general_err!( "Column count mismatch. Schema has {} columns while Row Group has {}", @@ -816,12 +807,7 @@ pub(crate) fn parquet_metadata_from_bytes( let schema_descr = schema_descr.as_ref().unwrap(); let list_ident = prot.read_list_begin()?; // check for list of struct - if list_ident.element_type != ElementType::Struct { - return Err(general_err!( - "Expected list element type of Struct but got {:?}", - list_ident.element_type - )); - } + validate_list_type(ElementType::Struct, &list_ident)?; let mut rg_vec = Vec::with_capacity(list_ident.size as usize); // Read row groups and handle ordinal assignment diff --git a/parquet/src/file/page_index/offset_index.rs b/parquet/src/file/page_index/offset_index.rs index 83cde3a0adc5..06d21efb68c8 100644 --- a/parquet/src/file/page_index/offset_index.rs +++ b/parquet/src/file/page_index/offset_index.rs @@ -23,7 +23,7 @@ use std::io::Write; use crate::parquet_thrift::{ ElementType, FieldType, ReadThrift, ThriftCompactInputProtocol, ThriftCompactOutputProtocol, - WriteThrift, WriteThriftField, read_thrift_vec, + WriteThrift, WriteThriftField, read_thrift_vec, validate_list_type, }; use crate::{ errors::{ParquetError, Result}, @@ -90,12 +90,7 @@ impl OffsetIndexMetaData { // we have to do this manually because we want to use the fast PageLocation decoder let list_ident = prot.read_list_begin()?; - if list_ident.element_type != ElementType::Struct { - return Err(general_err!( - "Expected list element type of Struct but got {:?}", - list_ident.element_type - )); - } + validate_list_type(ElementType::Struct, &list_ident)?; let mut page_locations = Vec::with_capacity(list_ident.size as usize); for _ in 0..list_ident.size { page_locations.push(read_page_location(prot)?); diff --git a/parquet/src/parquet_thrift.rs b/parquet/src/parquet_thrift.rs index c508e5dcfab2..742eeac14936 100644 --- a/parquet/src/parquet_thrift.rs +++ b/parquet/src/parquet_thrift.rs @@ -726,13 +726,7 @@ where T: ReadThrift<'a, R>, { let list_ident = prot.read_list_begin()?; - if list_ident.element_type != T::ELEMENT_TYPE { - return Err(general_err!( - "Expected list element type of {:?} but got {:?}", - T::ELEMENT_TYPE, - list_ident.element_type - )); - } + validate_list_type(T::ELEMENT_TYPE, &list_ident)?; let mut res = Vec::with_capacity(list_ident.size as usize); for _ in 0..list_ident.size { let val = T::read_thrift(prot)?; @@ -741,6 +735,17 @@ where Ok(res) } +pub(crate) fn validate_list_type(expected: ElementType, got: &ListIdentifier) -> Result<()> { + if got.element_type != expected { + return Err(general_err!( + "Expected list element type of {:?} but got {:?}", + expected, + got.element_type + )); + } + Ok(()) +} + ///////////////////////// // thrift compact output From 68cb310a9850b642a7669953c74169c3d6af69e4 Mon Sep 17 00:00:00 2001 From: Ed Seidl Date: Tue, 5 May 2026 12:16:59 -0700 Subject: [PATCH 6/8] missed a list --- parquet/src/basic.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/parquet/src/basic.rs b/parquet/src/basic.rs index 5b5951b34789..85765cf57f84 100644 --- a/parquet/src/basic.rs +++ b/parquet/src/basic.rs @@ -28,7 +28,7 @@ pub use crate::compression::{BrotliLevel, GzipLevel, ZstdLevel}; use crate::file::metadata::HeapSize; use crate::parquet_thrift::{ ElementType, FieldType, ReadThrift, ThriftCompactInputProtocol, ThriftCompactOutputProtocol, - WriteThrift, WriteThriftField, + WriteThrift, WriteThriftField, validate_list_type, }; use crate::{thrift_enum, thrift_struct, thrift_union_all_empty, write_thrift_field}; @@ -776,12 +776,7 @@ impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for EncodingMask { // This reads a Thrift `list` and turns it into a bitmask let list_ident = prot.read_list_begin()?; // check for enum (encoded as I32) - if list_ident.element_type != ElementType::I32 { - return Err(general_err!( - "Expected list element type of Encoding but got {:?}", - list_ident.element_type - )); - } + validate_list_type(ElementType::I32, &list_ident)?; for _ in 0..list_ident.size { let val = Encoding::read_thrift(prot)?; mask |= 1 << val as i32; From e16ddc3d31b51f7880ec2e6f0bc3e68ef45b900c Mon Sep 17 00:00:00 2001 From: Ed Seidl Date: Tue, 5 May 2026 14:40:35 -0700 Subject: [PATCH 7/8] change expected error string --- parquet/tests/arrow_reader/bad_data.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parquet/tests/arrow_reader/bad_data.rs b/parquet/tests/arrow_reader/bad_data.rs index d9b0d89e2c5f..56fddf505dac 100644 --- a/parquet/tests/arrow_reader/bad_data.rs +++ b/parquet/tests/arrow_reader/bad_data.rs @@ -98,7 +98,7 @@ fn test_arrow_gh_41317() { let err = read_file("ARROW-GH-41317.parquet").unwrap_err(); assert_eq!( err.to_string(), - "External: Parquet argument error: Parquet error: StructArrayReader out of sync in read_records, expected 5 read, got 2" + "Parquet error: Expected list element type of I32 but got I16" ); } From 9e51a544590aa8d23ddf50402885fcfc368cf6a5 Mon Sep 17 00:00:00 2001 From: Ed Seidl Date: Tue, 5 May 2026 22:21:36 -0700 Subject: [PATCH 8/8] use ELEMENT_TYPE from WriteThrift --- parquet/src/basic.rs | 10 ---------- parquet/src/parquet_macros.rs | 8 -------- parquet/src/parquet_thrift.rs | 23 +---------------------- 3 files changed, 1 insertion(+), 40 deletions(-) diff --git a/parquet/src/basic.rs b/parquet/src/basic.rs index 85765cf57f84..0d66c118a4f2 100644 --- a/parquet/src/basic.rs +++ b/parquet/src/basic.rs @@ -315,8 +315,6 @@ pub enum LogicalType { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for LogicalType { - const ELEMENT_TYPE: ElementType = ElementType::Struct; - fn read_thrift(prot: &mut R) -> Result { let field_ident = prot.read_field_begin(0)?; if field_ident.field_type == FieldType::Stop { @@ -768,8 +766,6 @@ impl HeapSize for EncodingMask { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for EncodingMask { - const ELEMENT_TYPE: ElementType = ElementType::I32; - fn read_thrift(prot: &mut R) -> Result { let mut mask = 0; @@ -841,8 +837,6 @@ pub enum Compression { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for Compression { - const ELEMENT_TYPE: ElementType = ElementType::I32; - fn read_thrift(prot: &mut R) -> Result { let val = prot.read_i32()?; Ok(match val { @@ -1084,8 +1078,6 @@ impl FromStr for EdgeInterpolationAlgorithm { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for EdgeInterpolationAlgorithm { - const ELEMENT_TYPE: ElementType = ElementType::I32; - fn read_thrift(prot: &mut R) -> Result { let val = prot.read_i32()?; match val { @@ -1314,8 +1306,6 @@ impl ColumnOrder { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for ColumnOrder { - const ELEMENT_TYPE: ElementType = ElementType::Struct; - fn read_thrift(prot: &mut R) -> Result { let field_ident = prot.read_field_begin(0)?; if field_ident.field_type == FieldType::Stop { diff --git a/parquet/src/parquet_macros.rs b/parquet/src/parquet_macros.rs index a881453f714f..13c476343164 100644 --- a/parquet/src/parquet_macros.rs +++ b/parquet/src/parquet_macros.rs @@ -50,8 +50,6 @@ macro_rules! thrift_enum { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for $identifier { - const ELEMENT_TYPE: ElementType = ElementType::I32; - #[allow(deprecated)] fn read_thrift(prot: &mut R) -> Result { let val = prot.read_i32()?; @@ -142,8 +140,6 @@ macro_rules! thrift_union_all_empty { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for $identifier { - const ELEMENT_TYPE: ElementType = ElementType::Struct; - fn read_thrift(prot: &mut R) -> Result { let field_ident = prot.read_field_begin(0)?; if field_ident.field_type == FieldType::Stop { @@ -218,8 +214,6 @@ macro_rules! thrift_union { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for $identifier $(<$lt>)? { - const ELEMENT_TYPE: ElementType = ElementType::Struct; - fn read_thrift(prot: &mut R) -> Result { let field_ident = prot.read_field_begin(0)?; if field_ident.field_type == FieldType::Stop { @@ -287,8 +281,6 @@ macro_rules! thrift_struct { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for $identifier $(<$lt>)? { - const ELEMENT_TYPE: ElementType = ElementType::Struct; - fn read_thrift(prot: &mut R) -> Result { $(let mut $field_name: Option<$crate::__thrift_field_type!($field_type $($field_lt)? $($element_type)?)> = None;)* let mut last_field_id = 0i16; diff --git a/parquet/src/parquet_thrift.rs b/parquet/src/parquet_thrift.rs index 742eeac14936..5d9c09b37718 100644 --- a/parquet/src/parquet_thrift.rs +++ b/parquet/src/parquet_thrift.rs @@ -636,9 +636,6 @@ impl<'a, R: Read> ThriftCompactInputProtocol<'a> for ThriftReadInputProtocol /// Trait implemented for objects that can be deserialized from a Thrift input stream. /// Implementations are provided for Thrift primitive types. pub(crate) trait ReadThrift<'a, R: ThriftCompactInputProtocol<'a>> { - /// The [`ElementType`] to use when a list of this object is read. - const ELEMENT_TYPE: ElementType; - /// Read an object of type `Self` from the input protocol object. fn read_thrift(prot: &mut R) -> Result where @@ -646,72 +643,54 @@ pub(crate) trait ReadThrift<'a, R: ThriftCompactInputProtocol<'a>> { } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for bool { - const ELEMENT_TYPE: ElementType = ElementType::Bool; - fn read_thrift(prot: &mut R) -> Result { Ok(prot.read_bool()?) } } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for i8 { - const ELEMENT_TYPE: ElementType = ElementType::Byte; - fn read_thrift(prot: &mut R) -> Result { Ok(prot.read_i8()?) } } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for i16 { - const ELEMENT_TYPE: ElementType = ElementType::I16; - fn read_thrift(prot: &mut R) -> Result { Ok(prot.read_i16()?) } } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for i32 { - const ELEMENT_TYPE: ElementType = ElementType::I32; - fn read_thrift(prot: &mut R) -> Result { Ok(prot.read_i32()?) } } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for i64 { - const ELEMENT_TYPE: ElementType = ElementType::I64; - fn read_thrift(prot: &mut R) -> Result { Ok(prot.read_i64()?) } } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for OrderedF64 { - const ELEMENT_TYPE: ElementType = ElementType::Double; - fn read_thrift(prot: &mut R) -> Result { Ok(OrderedF64(prot.read_double()?)) } } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for &'a str { - const ELEMENT_TYPE: ElementType = ElementType::Binary; - fn read_thrift(prot: &mut R) -> Result { Ok(prot.read_string()?) } } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for String { - const ELEMENT_TYPE: ElementType = ElementType::Binary; - fn read_thrift(prot: &mut R) -> Result { Ok(String::from_utf8(prot.read_bytes_owned()?)?) } } impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for &'a [u8] { - const ELEMENT_TYPE: ElementType = ElementType::Binary; - fn read_thrift(prot: &mut R) -> Result { Ok(prot.read_bytes()?) } @@ -723,7 +702,7 @@ impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for &'a [u8] { pub(crate) fn read_thrift_vec<'a, T, R>(prot: &mut R) -> Result> where R: ThriftCompactInputProtocol<'a>, - T: ReadThrift<'a, R>, + T: ReadThrift<'a, R> + WriteThrift, { let list_ident = prot.read_list_begin()?; validate_list_type(T::ELEMENT_TYPE, &list_ident)?;