1use std::io::Write;
24use std::str::FromStr;
25use std::{fmt, str};
26
27pub use crate::compression::{BrotliLevel, GzipLevel, ZstdLevel};
28use crate::file::metadata::HeapSize;
29use crate::parquet_thrift::{
30 ElementType, FieldType, ReadThrift, ThriftCompactInputProtocol, ThriftCompactOutputProtocol,
31 WriteThrift, WriteThriftField, validate_list_type,
32};
33use crate::{
34 thrift_enum, thrift_struct, thrift_union_all_empty, thrift_union_with_unknown,
35 write_thrift_field,
36};
37
38use crate::errors::{ParquetError, Result};
39
40thrift_enum!(
47enum Type {
54 BOOLEAN = 0;
55 INT32 = 1;
56 INT64 = 2;
57 INT96 = 3; FLOAT = 4;
59 DOUBLE = 5;
60 BYTE_ARRAY = 6;
61 FIXED_LEN_BYTE_ARRAY = 7;
62}
63);
64
65thrift_enum!(
71enum ConvertedType {
79 NONE = -1;
81
82 UTF8 = 0;
84
85 MAP = 1;
87
88 MAP_KEY_VALUE = 2;
90
91 LIST = 3;
94
95 ENUM = 4;
97
98 DECIMAL = 5;
111
112 DATE = 6;
114
115 TIME_MILLIS = 7;
118
119 TIME_MICROS = 8;
122
123 TIMESTAMP_MILLIS = 9;
126
127 TIMESTAMP_MICROS = 10;
130
131 UINT_8 = 11;
133
134 UINT_16 = 12;
136
137 UINT_32 = 13;
139
140 UINT_64 = 14;
142
143 INT_8 = 15;
145
146 INT_16 = 16;
148
149 INT_32 = 17;
151
152 INT_64 = 18;
154
155 JSON = 19;
157
158 BSON = 20;
160
161 INTERVAL = 21;
171}
172);
173
174thrift_union_all_empty!(
178union TimeUnit {
180 1: MilliSeconds MILLIS
181 2: MicroSeconds MICROS
182 3: NanoSeconds NANOS
183}
184);
185
186thrift_struct!(
190pub struct DecimalType {
191 1: required i32 scale
193 2: required i32 precision
195}
196);
197
198thrift_struct!(
199pub struct TimestampType {
200 1: required bool is_adjusted_to_u_t_c
202 2: required TimeUnit unit
204}
205);
206
207pub use TimestampType as TimeType;
209
210thrift_struct!(
211pub struct IntType {
212 1: required i8 bit_width
214 2: required bool is_signed
216}
217);
218
219thrift_struct!(
220pub struct VariantType {
221 1: optional i8 specification_version
224}
225);
226
227thrift_struct!(
228pub struct GeometryType {
229 1: optional string crs;
232}
233);
234
235thrift_struct!(
236pub struct GeographyType {
237 1: optional string crs;
239 2: optional EdgeInterpolationAlgorithm algorithm;
242}
243);
244
245impl GeographyType {
246 pub fn algorithm(&self) -> Option<EdgeInterpolationAlgorithm> {
252 Some(self.algorithm.unwrap_or_default())
253 }
254}
255
256thrift_union_with_unknown!(
257union LogicalType {
263 1: String
265 2: Map
267 3: List
269 4: Enum
271 5: (DecimalType) Decimal
273 6: Date
275 7: (TimeType) Time
277 8: (TimestampType) Timestamp
279 10: (IntType) Integer
282 11: Unknown
284 12: Json
286 13: Bson
288 14: Uuid
290 15: Float16
292 16: (VariantType) Variant
294 17: (GeometryType) Geometry
296 18: (GeographyType) Geography
298 19: File
300}
301);
302
303impl LogicalType {
304 pub fn integer(bit_width: i8, is_signed: bool) -> Self {
306 Self::Integer(IntType {
307 bit_width,
308 is_signed,
309 })
310 }
311
312 pub fn decimal(scale: i32, precision: i32) -> Self {
314 Self::Decimal(DecimalType { scale, precision })
315 }
316
317 pub fn time(is_adjusted_to_u_t_c: bool, unit: TimeUnit) -> Self {
319 Self::Time(TimeType {
320 is_adjusted_to_u_t_c,
321 unit,
322 })
323 }
324
325 pub fn timestamp(is_adjusted_to_u_t_c: bool, unit: TimeUnit) -> Self {
327 Self::Timestamp(TimestampType {
328 is_adjusted_to_u_t_c,
329 unit,
330 })
331 }
332
333 pub fn variant(specification_version: Option<i8>) -> Self {
335 Self::Variant(VariantType {
336 specification_version,
337 })
338 }
339
340 pub fn geometry(crs: Option<String>) -> Self {
342 Self::Geometry(GeometryType { crs })
343 }
344
345 pub fn geography(crs: Option<String>, algorithm: Option<EdgeInterpolationAlgorithm>) -> Self {
347 Self::Geography(GeographyType { crs, algorithm })
348 }
349}
350
351thrift_enum!(
356enum FieldRepetitionType {
358 REQUIRED = 0;
360 OPTIONAL = 1;
362 REPEATED = 2;
364}
365);
366
367pub type Repetition = FieldRepetitionType;
369
370thrift_enum!(
374enum Encoding {
391 PLAIN = 0;
400 PLAIN_DICTIONARY = 2;
407 RLE = 3;
411 #[deprecated(
424 since = "51.0.0",
425 note = "Please see documentation for compatibility issues and use the RLE/bit-packing hybrid encoding instead"
426 )]
427 BIT_PACKED = 4;
428 DELTA_BINARY_PACKED = 5;
432 DELTA_LENGTH_BYTE_ARRAY = 6;
436 DELTA_BYTE_ARRAY = 7;
441 RLE_DICTIONARY = 8;
445 BYTE_STREAM_SPLIT = 9;
454 ALP = 10;
458}
459);
460
461impl FromStr for Encoding {
462 type Err = ParquetError;
463
464 fn from_str(s: &str) -> Result<Self, Self::Err> {
465 match s {
466 "PLAIN" | "plain" => Ok(Encoding::PLAIN),
467 "PLAIN_DICTIONARY" | "plain_dictionary" => Ok(Encoding::PLAIN_DICTIONARY),
468 "RLE" | "rle" => Ok(Encoding::RLE),
469 #[expect(deprecated)]
470 "BIT_PACKED" | "bit_packed" => Ok(Encoding::BIT_PACKED),
471 "DELTA_BINARY_PACKED" | "delta_binary_packed" => Ok(Encoding::DELTA_BINARY_PACKED),
472 "DELTA_LENGTH_BYTE_ARRAY" | "delta_length_byte_array" => {
473 Ok(Encoding::DELTA_LENGTH_BYTE_ARRAY)
474 }
475 "DELTA_BYTE_ARRAY" | "delta_byte_array" => Ok(Encoding::DELTA_BYTE_ARRAY),
476 "RLE_DICTIONARY" | "rle_dictionary" => Ok(Encoding::RLE_DICTIONARY),
477 "BYTE_STREAM_SPLIT" | "byte_stream_split" => Ok(Encoding::BYTE_STREAM_SPLIT),
478 "ALP" | "alp" => Ok(Encoding::ALP),
479 _ => Err(general_err!("unknown encoding: {}", s)),
480 }
481 }
482}
483
484#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
518pub struct EncodingMask(i32);
519
520impl EncodingMask {
521 const MAX_ENCODING: i32 = Encoding::MAX_DISCRIMINANT;
523 const ALLOWED_MASK: u32 =
526 !(1u32 << (EncodingMask::MAX_ENCODING as u32 + 1)).wrapping_sub(1) | (1 << 1);
527
528 pub fn try_new(val: i32) -> Result<Self> {
532 if val as u32 & Self::ALLOWED_MASK != 0 {
533 return Err(general_err!("Attempt to create invalid mask: 0x{:x}", val));
534 }
535 Ok(Self(val))
536 }
537
538 pub fn as_i32(&self) -> i32 {
540 self.0
541 }
542
543 pub fn new_from_encodings<'a>(encodings: impl Iterator<Item = &'a Encoding>) -> Self {
545 let mut mask = 0;
546 for &e in encodings {
547 mask |= 1 << (e as i32);
548 }
549 Self(mask)
550 }
551
552 pub fn insert(&mut self, val: Encoding) {
554 self.0 |= 1 << (val as i32);
555 }
556
557 pub fn is_set(&self, val: Encoding) -> bool {
559 self.0 & (1 << (val as i32)) != 0
560 }
561
562 pub fn is_only(&self, val: Encoding) -> bool {
564 self.0 == (1 << (val as i32))
565 }
566
567 pub fn all_set<'a>(&self, mut encodings: impl Iterator<Item = &'a Encoding>) -> bool {
569 encodings.all(|&e| self.is_set(e))
570 }
571
572 pub fn encodings(&self) -> impl Iterator<Item = Encoding> {
574 Self::mask_to_encodings_iter(self.0)
575 }
576
577 fn mask_to_encodings_iter(mask: i32) -> impl Iterator<Item = Encoding> {
578 (0..=Self::MAX_ENCODING)
579 .filter(move |i| mask & (1 << i) != 0)
580 .map(i32_to_encoding)
581 }
582}
583
584impl HeapSize for EncodingMask {
585 fn heap_size(&self) -> usize {
586 0 }
588}
589
590impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for EncodingMask {
591 fn read_thrift(prot: &mut R) -> Result<Self> {
592 let mut mask = 0;
593
594 let list_ident = prot.read_list_begin()?;
596 validate_list_type(ElementType::I32, &list_ident)?;
598 for _ in 0..list_ident.size {
599 let val = Encoding::read_thrift(prot)?;
600 mask |= 1 << val as i32;
601 }
602 Ok(Self(mask))
603 }
604}
605
606#[expect(deprecated)]
607fn i32_to_encoding(val: i32) -> Encoding {
608 match val {
609 0 => Encoding::PLAIN,
610 2 => Encoding::PLAIN_DICTIONARY,
611 3 => Encoding::RLE,
612 4 => Encoding::BIT_PACKED,
613 5 => Encoding::DELTA_BINARY_PACKED,
614 6 => Encoding::DELTA_LENGTH_BYTE_ARRAY,
615 7 => Encoding::DELTA_BYTE_ARRAY,
616 8 => Encoding::RLE_DICTIONARY,
617 9 => Encoding::BYTE_STREAM_SPLIT,
618 10 => Encoding::ALP,
619 _ => panic!("Impossible encoding {val}"),
620 }
621}
622
623thrift_enum!(
627enum CompressionCodec {
637 UNCOMPRESSED = 0;
638 SNAPPY = 1;
639 GZIP = 2;
640 LZO = 3;
641 BROTLI = 4; LZ4 = 5; ZSTD = 6; LZ4_RAW = 7; }
646);
647
648#[derive(Debug, Clone, Copy, PartialEq, Eq)]
669#[expect(non_camel_case_types)]
670pub enum Compression {
671 UNCOMPRESSED,
673 SNAPPY,
675 GZIP(GzipLevel),
677 LZO,
679 BROTLI(BrotliLevel),
681 LZ4,
683 ZSTD(ZstdLevel),
685 LZ4_RAW,
687}
688
689impl From<CompressionCodec> for Compression {
690 fn from(value: CompressionCodec) -> Self {
691 match value {
692 CompressionCodec::UNCOMPRESSED => Compression::UNCOMPRESSED,
693 CompressionCodec::SNAPPY => Compression::SNAPPY,
694 CompressionCodec::GZIP => Compression::GZIP(Default::default()),
695 CompressionCodec::LZO => Compression::LZO,
696 CompressionCodec::BROTLI => Compression::BROTLI(Default::default()),
697 CompressionCodec::LZ4 => Compression::LZ4,
698 CompressionCodec::ZSTD => Compression::ZSTD(Default::default()),
699 CompressionCodec::LZ4_RAW => Compression::LZ4_RAW,
700 }
701 }
702}
703
704impl From<Compression> for CompressionCodec {
705 fn from(value: Compression) -> Self {
706 match value {
707 Compression::UNCOMPRESSED => CompressionCodec::UNCOMPRESSED,
708 Compression::SNAPPY => CompressionCodec::SNAPPY,
709 Compression::GZIP(_) => CompressionCodec::GZIP,
710 Compression::LZO => CompressionCodec::LZO,
711 Compression::BROTLI(_) => CompressionCodec::BROTLI,
712 Compression::LZ4 => CompressionCodec::LZ4,
713 Compression::ZSTD(_) => CompressionCodec::ZSTD,
714 Compression::LZ4_RAW => CompressionCodec::LZ4_RAW,
715 }
716 }
717}
718
719fn split_compression_string(str_setting: &str) -> Result<(&str, Option<i32>), ParquetError> {
720 let split_setting = str_setting.split_once('(');
721
722 match split_setting {
723 Some((codec, level_str)) => {
724 let level = &level_str[..level_str.len() - 1]
725 .parse::<i32>()
726 .map_err(|_| {
727 ParquetError::General(format!("invalid compression level: {level_str}"))
728 })?;
729 Ok((codec, Some(*level)))
730 }
731 None => Ok((str_setting, None)),
732 }
733}
734
735fn check_level_is_none(level: Option<i32>) -> Result<(), ParquetError> {
736 if level.is_some() {
737 return Err(ParquetError::General(
738 "compression level is not supported".to_string(),
739 ));
740 }
741
742 Ok(())
743}
744
745fn require_level(codec: &str, level: Option<i32>) -> Result<i32, ParquetError> {
746 level.ok_or(ParquetError::General(format!(
747 "{codec} requires a compression level",
748 )))
749}
750
751impl FromStr for Compression {
752 type Err = ParquetError;
753
754 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
755 let (codec, level) = split_compression_string(s)?;
756
757 let c = match codec {
758 "UNCOMPRESSED" | "uncompressed" => {
759 check_level_is_none(level)?;
760 Compression::UNCOMPRESSED
761 }
762 "SNAPPY" | "snappy" => {
763 check_level_is_none(level)?;
764 Compression::SNAPPY
765 }
766 "GZIP" | "gzip" => {
767 let level = require_level(codec, level)?;
768 Compression::GZIP(GzipLevel::try_new(level.try_into()?)?)
769 }
770 "LZO" | "lzo" => {
771 check_level_is_none(level)?;
772 Compression::LZO
773 }
774 "BROTLI" | "brotli" => {
775 let level = require_level(codec, level)?;
776 Compression::BROTLI(BrotliLevel::try_new(level.try_into()?)?)
777 }
778 "LZ4" | "lz4" => {
779 check_level_is_none(level)?;
780 Compression::LZ4
781 }
782 "ZSTD" | "zstd" => {
783 let level = require_level(codec, level)?;
784 Compression::ZSTD(ZstdLevel::try_new(level)?)
785 }
786 "LZ4_RAW" | "lz4_raw" => {
787 check_level_is_none(level)?;
788 Compression::LZ4_RAW
789 }
790 _ => {
791 return Err(ParquetError::General(format!(
792 "unsupported compression {codec}"
793 )));
794 }
795 };
796
797 Ok(c)
798 }
799}
800
801thrift_enum!(
805enum PageType {
808 DATA_PAGE = 0;
809 INDEX_PAGE = 1;
810 DICTIONARY_PAGE = 2;
811 DATA_PAGE_V2 = 3;
812}
813);
814
815thrift_enum!(
819enum BoundaryOrder {
822 UNORDERED = 0;
823 ASCENDING = 1;
824 DESCENDING = 2;
825}
826);
827
828#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
835#[repr(i32)]
836#[derive(Default)]
837pub enum EdgeInterpolationAlgorithm {
838 #[default]
840 SPHERICAL = 0,
841 VINCENTY = 1,
843 THOMAS = 2,
845 ANDOYER = 3,
847 KARNEY = 4,
849 _Unknown(i32),
851}
852
853#[cfg(feature = "geospatial")]
854impl EdgeInterpolationAlgorithm {
855 pub fn try_as_edges(&self) -> Result<parquet_geospatial::WkbEdges> {
861 match &self {
862 Self::SPHERICAL => Ok(parquet_geospatial::WkbEdges::Spherical),
863 Self::VINCENTY => Ok(parquet_geospatial::WkbEdges::Vincenty),
864 Self::THOMAS => Ok(parquet_geospatial::WkbEdges::Thomas),
865 Self::ANDOYER => Ok(parquet_geospatial::WkbEdges::Andoyer),
866 Self::KARNEY => Ok(parquet_geospatial::WkbEdges::Karney),
867 unknown @ Self::_Unknown(_) => Err(general_err!(
868 "Unknown edge interpolation algorithm: {}",
869 unknown
870 )),
871 }
872 }
873}
874
875impl fmt::Display for EdgeInterpolationAlgorithm {
876 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
877 f.write_fmt(format_args!("{self:?}"))
878 }
879}
880
881#[cfg(feature = "geospatial")]
882impl From<parquet_geospatial::WkbEdges> for EdgeInterpolationAlgorithm {
883 fn from(value: parquet_geospatial::WkbEdges) -> Self {
884 match value {
885 parquet_geospatial::WkbEdges::Spherical => Self::SPHERICAL,
886 parquet_geospatial::WkbEdges::Vincenty => Self::VINCENTY,
887 parquet_geospatial::WkbEdges::Thomas => Self::THOMAS,
888 parquet_geospatial::WkbEdges::Andoyer => Self::ANDOYER,
889 parquet_geospatial::WkbEdges::Karney => Self::KARNEY,
890 }
891 }
892}
893
894impl FromStr for EdgeInterpolationAlgorithm {
895 type Err = ParquetError;
896
897 fn from_str(s: &str) -> Result<Self> {
898 match s.to_ascii_uppercase().as_str() {
899 "SPHERICAL" => Ok(EdgeInterpolationAlgorithm::SPHERICAL),
900 "VINCENTY" => Ok(EdgeInterpolationAlgorithm::VINCENTY),
901 "THOMAS" => Ok(EdgeInterpolationAlgorithm::THOMAS),
902 "ANDOYER" => Ok(EdgeInterpolationAlgorithm::ANDOYER),
903 "KARNEY" => Ok(EdgeInterpolationAlgorithm::KARNEY),
904 unknown => Err(general_err!(
905 "Unknown edge interpolation algorithm: {}",
906 unknown
907 )),
908 }
909 }
910}
911
912impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for EdgeInterpolationAlgorithm {
913 fn read_thrift(prot: &mut R) -> Result<Self> {
914 let val = prot.read_i32()?;
915 match val {
916 0 => Ok(Self::SPHERICAL),
917 1 => Ok(Self::VINCENTY),
918 2 => Ok(Self::THOMAS),
919 3 => Ok(Self::ANDOYER),
920 4 => Ok(Self::KARNEY),
921 _ => Ok(Self::_Unknown(val)),
922 }
923 }
924}
925
926impl WriteThrift for EdgeInterpolationAlgorithm {
927 const ELEMENT_TYPE: ElementType = ElementType::I32;
928 fn write_thrift<W: Write>(&self, writer: &mut ThriftCompactOutputProtocol<W>) -> Result<()> {
929 let val: i32 = match *self {
930 Self::SPHERICAL => 0,
931 Self::VINCENTY => 1,
932 Self::THOMAS => 2,
933 Self::ANDOYER => 3,
934 Self::KARNEY => 4,
935 Self::_Unknown(i) => i,
936 };
937 writer.write_i32(val)
938 }
939}
940
941write_thrift_field!(EdgeInterpolationAlgorithm, FieldType::I32);
942
943thrift_union_all_empty!(
947union BloomFilterAlgorithm {
949 1: SplitBlockAlgorithm BLOCK;
951}
952);
953
954thrift_union_all_empty!(
958union BloomFilterHash {
961 1: XxHash XXHASH;
963}
964);
965
966thrift_union_all_empty!(
970union BloomFilterCompression {
972 1: Uncompressed UNCOMPRESSED;
973}
974);
975
976#[derive(Debug, Clone, Copy, PartialEq, Eq)]
987#[expect(non_camel_case_types)]
988pub enum SortOrder {
989 SIGNED,
991 UNSIGNED,
993 UNDEFINED,
995 TOTAL_ORDER,
997 INT96_TIMESTAMP,
1002}
1003
1004impl SortOrder {
1005 pub fn is_signed(&self) -> bool {
1007 matches!(self, Self::SIGNED)
1008 }
1009}
1010
1011#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1032#[expect(non_camel_case_types)]
1033pub enum ColumnOrder {
1034 TYPE_DEFINED_ORDER(SortOrder),
1037 IEEE_754_TOTAL_ORDER,
1039 INT96_TIMESTAMP_ORDER,
1041 UNDEFINED,
1045 UNKNOWN,
1048}
1049
1050impl ColumnOrder {
1051 pub fn column_order_for_type(
1053 logical_type: Option<&LogicalType>,
1054 converted_type: ConvertedType,
1055 physical_type: Type,
1056 ) -> ColumnOrder {
1057 if Some(&LogicalType::Float16) == logical_type
1058 || matches!(physical_type, Type::FLOAT | Type::DOUBLE)
1059 {
1060 ColumnOrder::IEEE_754_TOTAL_ORDER
1061 } else if matches!(physical_type, Type::INT96) {
1062 ColumnOrder::INT96_TIMESTAMP_ORDER
1063 } else {
1064 let sort_order =
1065 Self::get_sort_order_for_type(logical_type, converted_type, physical_type, true);
1066 ColumnOrder::TYPE_DEFINED_ORDER(sort_order)
1067 }
1068 }
1069
1070 #[deprecated(since = "60.0.0", note = "use `ColumnOrder::sort_order` instead")]
1077 pub fn sort_order_for_type(
1078 logical_type: Option<&LogicalType>,
1079 converted_type: ConvertedType,
1080 physical_type: Type,
1081 is_type_defined: bool,
1082 ) -> SortOrder {
1083 ColumnOrder::get_sort_order_for_type(
1084 logical_type,
1085 converted_type,
1086 physical_type,
1087 is_type_defined,
1088 )
1089 }
1090
1091 pub(crate) fn get_sort_order_for_type(
1094 logical_type: Option<&LogicalType>,
1095 converted_type: ConvertedType,
1096 physical_type: Type,
1097 is_type_defined: bool,
1098 ) -> SortOrder {
1099 match logical_type {
1100 Some(logical) => match logical {
1101 LogicalType::String | LogicalType::Enum | LogicalType::Json | LogicalType::Bson => {
1102 SortOrder::UNSIGNED
1103 }
1104 LogicalType::Integer(int) => match int.is_signed {
1105 true => SortOrder::SIGNED,
1106 false => SortOrder::UNSIGNED,
1107 },
1108 LogicalType::Map | LogicalType::List => SortOrder::UNDEFINED,
1109 LogicalType::Decimal(_) => SortOrder::SIGNED,
1110 LogicalType::Date => SortOrder::SIGNED,
1111 LogicalType::Time(_) => SortOrder::SIGNED,
1112 LogicalType::Timestamp(_) => SortOrder::SIGNED,
1113 LogicalType::Unknown => SortOrder::UNDEFINED,
1114 LogicalType::Uuid => SortOrder::UNSIGNED,
1115 LogicalType::Float16 => {
1116 if is_type_defined {
1117 SortOrder::SIGNED
1118 } else {
1119 SortOrder::TOTAL_ORDER
1120 }
1121 }
1122 LogicalType::Variant(_)
1123 | LogicalType::Geometry(_)
1124 | LogicalType::Geography(_)
1125 | LogicalType::File
1126 | LogicalType::_Unknown { .. } => SortOrder::UNDEFINED,
1127 },
1128 None => Self::get_converted_sort_order(converted_type, physical_type, is_type_defined),
1130 }
1131 }
1132
1133 fn get_converted_sort_order(
1134 converted_type: ConvertedType,
1135 physical_type: Type,
1136 is_type_defined: bool,
1137 ) -> SortOrder {
1138 match converted_type {
1139 ConvertedType::UTF8
1141 | ConvertedType::JSON
1142 | ConvertedType::BSON
1143 | ConvertedType::ENUM => SortOrder::UNSIGNED,
1144
1145 ConvertedType::INT_8
1146 | ConvertedType::INT_16
1147 | ConvertedType::INT_32
1148 | ConvertedType::INT_64 => SortOrder::SIGNED,
1149
1150 ConvertedType::UINT_8
1151 | ConvertedType::UINT_16
1152 | ConvertedType::UINT_32
1153 | ConvertedType::UINT_64 => SortOrder::UNSIGNED,
1154
1155 ConvertedType::DECIMAL => SortOrder::SIGNED,
1157
1158 ConvertedType::DATE => SortOrder::SIGNED,
1159
1160 ConvertedType::TIME_MILLIS
1161 | ConvertedType::TIME_MICROS
1162 | ConvertedType::TIMESTAMP_MILLIS
1163 | ConvertedType::TIMESTAMP_MICROS => SortOrder::SIGNED,
1164
1165 ConvertedType::INTERVAL => SortOrder::UNDEFINED,
1166
1167 ConvertedType::LIST | ConvertedType::MAP | ConvertedType::MAP_KEY_VALUE => {
1168 SortOrder::UNDEFINED
1169 }
1170
1171 ConvertedType::NONE => Self::get_default_sort_order(physical_type, is_type_defined),
1173 }
1174 }
1175
1176 fn get_default_sort_order(physical_type: Type, is_type_defined: bool) -> SortOrder {
1178 match physical_type {
1179 Type::BOOLEAN => SortOrder::UNSIGNED,
1181 Type::INT32 | Type::INT64 => SortOrder::SIGNED,
1182 Type::INT96 => {
1183 if is_type_defined {
1184 SortOrder::UNDEFINED
1185 } else {
1186 SortOrder::INT96_TIMESTAMP
1187 }
1188 }
1189 Type::FLOAT | Type::DOUBLE => {
1201 if is_type_defined {
1202 SortOrder::SIGNED
1203 } else {
1204 SortOrder::TOTAL_ORDER
1205 }
1206 }
1207 Type::BYTE_ARRAY | Type::FIXED_LEN_BYTE_ARRAY => SortOrder::UNSIGNED,
1209 }
1210 }
1211
1212 pub fn sort_order(&self) -> SortOrder {
1214 match *self {
1215 ColumnOrder::TYPE_DEFINED_ORDER(order) => order,
1216 ColumnOrder::IEEE_754_TOTAL_ORDER => SortOrder::TOTAL_ORDER,
1217 ColumnOrder::INT96_TIMESTAMP_ORDER => SortOrder::INT96_TIMESTAMP,
1218 ColumnOrder::UNDEFINED => SortOrder::SIGNED,
1219 ColumnOrder::UNKNOWN => SortOrder::UNDEFINED,
1220 }
1221 }
1222}
1223
1224impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for ColumnOrder {
1225 fn read_thrift(prot: &mut R) -> Result<Self> {
1226 let field_ident = prot.read_field_begin(0)?;
1227 if field_ident.field_type == FieldType::Stop {
1228 return Err(general_err!("Received empty union from remote ColumnOrder"));
1229 }
1230 let ret = match field_ident.id {
1231 1 => {
1232 prot.skip_empty_struct()?;
1234 Self::TYPE_DEFINED_ORDER(SortOrder::SIGNED)
1235 }
1236 2 => {
1237 prot.skip_empty_struct()?;
1238 Self::IEEE_754_TOTAL_ORDER
1239 }
1240 3 => {
1241 prot.skip_empty_struct()?;
1242 Self::INT96_TIMESTAMP_ORDER
1243 }
1244 _ => {
1245 prot.skip(field_ident.field_type)?;
1246 Self::UNKNOWN
1247 }
1248 };
1249 let field_ident = prot.read_field_begin(field_ident.id)?;
1250 if field_ident.field_type != FieldType::Stop {
1251 return Err(general_err!(
1252 "Received multiple fields for union from remote ColumnOrder"
1253 ));
1254 }
1255 Ok(ret)
1256 }
1257}
1258
1259impl WriteThrift for ColumnOrder {
1260 const ELEMENT_TYPE: ElementType = ElementType::Struct;
1261
1262 fn write_thrift<W: Write>(&self, writer: &mut ThriftCompactOutputProtocol<W>) -> Result<()> {
1263 match *self {
1264 Self::TYPE_DEFINED_ORDER(_) => {
1265 writer.write_field_begin(FieldType::Struct, 1, 0)?;
1266 writer.write_struct_end()?;
1267 }
1268 Self::IEEE_754_TOTAL_ORDER => {
1269 writer.write_field_begin(FieldType::Struct, 2, 0)?;
1270 writer.write_struct_end()?;
1271 }
1272 Self::INT96_TIMESTAMP_ORDER => {
1273 writer.write_field_begin(FieldType::Struct, 3, 0)?;
1274 writer.write_struct_end()?;
1275 }
1276 _ => return Err(general_err!("Attempt to write undefined ColumnOrder")),
1277 }
1278 writer.write_struct_end()
1280 }
1281}
1282
1283impl fmt::Display for Compression {
1287 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1288 write!(f, "{self:?}")
1289 }
1290}
1291
1292impl fmt::Display for SortOrder {
1293 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1294 write!(f, "{self:?}")
1295 }
1296}
1297
1298impl fmt::Display for ColumnOrder {
1299 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1300 write!(f, "{self:?}")
1301 }
1302}
1303
1304impl From<Option<LogicalType>> for ConvertedType {
1314 fn from(value: Option<LogicalType>) -> Self {
1315 match value {
1316 Some(value) => match value {
1317 LogicalType::String => ConvertedType::UTF8,
1318 LogicalType::Map => ConvertedType::MAP,
1319 LogicalType::List => ConvertedType::LIST,
1320 LogicalType::Enum => ConvertedType::ENUM,
1321 LogicalType::Decimal { .. } => ConvertedType::DECIMAL,
1322 LogicalType::Date => ConvertedType::DATE,
1323 LogicalType::Time(time) => match time.unit {
1324 TimeUnit::MILLIS => ConvertedType::TIME_MILLIS,
1325 TimeUnit::MICROS => ConvertedType::TIME_MICROS,
1326 TimeUnit::NANOS => ConvertedType::NONE,
1327 },
1328 LogicalType::Timestamp(time) => match time.unit {
1329 TimeUnit::MILLIS => ConvertedType::TIMESTAMP_MILLIS,
1330 TimeUnit::MICROS => ConvertedType::TIMESTAMP_MICROS,
1331 TimeUnit::NANOS => ConvertedType::NONE,
1332 },
1333 LogicalType::Integer(int_type) => match (int_type.bit_width, int_type.is_signed) {
1334 (8, true) => ConvertedType::INT_8,
1335 (16, true) => ConvertedType::INT_16,
1336 (32, true) => ConvertedType::INT_32,
1337 (64, true) => ConvertedType::INT_64,
1338 (8, false) => ConvertedType::UINT_8,
1339 (16, false) => ConvertedType::UINT_16,
1340 (32, false) => ConvertedType::UINT_32,
1341 (64, false) => ConvertedType::UINT_64,
1342 (bit_width, is_signed) => panic!(
1343 "Integer type bit_width={bit_width}, signed={is_signed} is not supported"
1344 ),
1345 },
1346 LogicalType::Json => ConvertedType::JSON,
1347 LogicalType::Bson => ConvertedType::BSON,
1348 LogicalType::Uuid
1349 | LogicalType::Float16
1350 | LogicalType::Variant(_)
1351 | LogicalType::Geometry(_)
1352 | LogicalType::Geography(_)
1353 | LogicalType::File
1354 | LogicalType::_Unknown { .. }
1355 | LogicalType::Unknown => ConvertedType::NONE,
1356 },
1357 None => ConvertedType::NONE,
1358 }
1359 }
1360}
1361
1362impl str::FromStr for Repetition {
1366 type Err = ParquetError;
1367
1368 fn from_str(s: &str) -> Result<Self> {
1369 match s {
1370 "REQUIRED" => Ok(Repetition::REQUIRED),
1371 "OPTIONAL" => Ok(Repetition::OPTIONAL),
1372 "REPEATED" => Ok(Repetition::REPEATED),
1373 other => Err(general_err!("Invalid parquet repetition {}", other)),
1374 }
1375 }
1376}
1377
1378impl str::FromStr for Type {
1379 type Err = ParquetError;
1380
1381 fn from_str(s: &str) -> Result<Self> {
1382 match s {
1383 "BOOLEAN" => Ok(Type::BOOLEAN),
1384 "INT32" => Ok(Type::INT32),
1385 "INT64" => Ok(Type::INT64),
1386 "INT96" => Ok(Type::INT96),
1387 "FLOAT" => Ok(Type::FLOAT),
1388 "DOUBLE" => Ok(Type::DOUBLE),
1389 "BYTE_ARRAY" | "BINARY" => Ok(Type::BYTE_ARRAY),
1390 "FIXED_LEN_BYTE_ARRAY" => Ok(Type::FIXED_LEN_BYTE_ARRAY),
1391 other => Err(general_err!("Invalid parquet type {}", other)),
1392 }
1393 }
1394}
1395
1396impl str::FromStr for ConvertedType {
1397 type Err = ParquetError;
1398
1399 fn from_str(s: &str) -> Result<Self> {
1400 match s {
1401 "NONE" => Ok(ConvertedType::NONE),
1402 "UTF8" => Ok(ConvertedType::UTF8),
1403 "MAP" => Ok(ConvertedType::MAP),
1404 "MAP_KEY_VALUE" => Ok(ConvertedType::MAP_KEY_VALUE),
1405 "LIST" => Ok(ConvertedType::LIST),
1406 "ENUM" => Ok(ConvertedType::ENUM),
1407 "DECIMAL" => Ok(ConvertedType::DECIMAL),
1408 "DATE" => Ok(ConvertedType::DATE),
1409 "TIME_MILLIS" => Ok(ConvertedType::TIME_MILLIS),
1410 "TIME_MICROS" => Ok(ConvertedType::TIME_MICROS),
1411 "TIMESTAMP_MILLIS" => Ok(ConvertedType::TIMESTAMP_MILLIS),
1412 "TIMESTAMP_MICROS" => Ok(ConvertedType::TIMESTAMP_MICROS),
1413 "UINT_8" => Ok(ConvertedType::UINT_8),
1414 "UINT_16" => Ok(ConvertedType::UINT_16),
1415 "UINT_32" => Ok(ConvertedType::UINT_32),
1416 "UINT_64" => Ok(ConvertedType::UINT_64),
1417 "INT_8" => Ok(ConvertedType::INT_8),
1418 "INT_16" => Ok(ConvertedType::INT_16),
1419 "INT_32" => Ok(ConvertedType::INT_32),
1420 "INT_64" => Ok(ConvertedType::INT_64),
1421 "JSON" => Ok(ConvertedType::JSON),
1422 "BSON" => Ok(ConvertedType::BSON),
1423 "INTERVAL" => Ok(ConvertedType::INTERVAL),
1424 other => Err(general_err!("Invalid parquet converted type {}", other)),
1425 }
1426 }
1427}
1428
1429impl str::FromStr for LogicalType {
1430 type Err = ParquetError;
1431
1432 fn from_str(s: &str) -> Result<Self> {
1433 match s {
1434 "INTEGER" => Ok(LogicalType::integer(8, false)),
1436 "MAP" => Ok(LogicalType::Map),
1437 "LIST" => Ok(LogicalType::List),
1438 "ENUM" => Ok(LogicalType::Enum),
1439 "DECIMAL" => Ok(LogicalType::decimal(-1, -1)),
1440 "DATE" => Ok(LogicalType::Date),
1441 "TIME" => Ok(LogicalType::time(false, TimeUnit::MILLIS)),
1442 "TIMESTAMP" => Ok(LogicalType::timestamp(false, TimeUnit::MILLIS)),
1443 "STRING" => Ok(LogicalType::String),
1444 "JSON" => Ok(LogicalType::Json),
1445 "BSON" => Ok(LogicalType::Bson),
1446 "UUID" => Ok(LogicalType::Uuid),
1447 "UNKNOWN" => Ok(LogicalType::Unknown),
1448 "INTERVAL" => Err(general_err!(
1449 "Interval parquet logical type not yet supported"
1450 )),
1451 "FLOAT16" => Ok(LogicalType::Float16),
1452 "VARIANT" => Ok(LogicalType::variant(None)),
1453 "FILE" => Ok(LogicalType::File),
1454 "GEOMETRY" => Ok(LogicalType::geometry(None)),
1455 "GEOGRAPHY" => Ok(LogicalType::geography(
1456 None,
1457 Some(EdgeInterpolationAlgorithm::SPHERICAL),
1458 )),
1459 other => Err(general_err!("Invalid parquet logical type {}", other)),
1460 }
1461 }
1462}
1463
1464#[cfg(test)]
1465#[expect(deprecated)] mod tests {
1467 use super::*;
1468 use crate::parquet_thrift::{ThriftSliceInputProtocol, tests::test_roundtrip};
1469
1470 #[test]
1471 fn test_display_type() {
1472 assert_eq!(Type::BOOLEAN.to_string(), "BOOLEAN");
1473 assert_eq!(Type::INT32.to_string(), "INT32");
1474 assert_eq!(Type::INT64.to_string(), "INT64");
1475 assert_eq!(Type::INT96.to_string(), "INT96");
1476 assert_eq!(Type::FLOAT.to_string(), "FLOAT");
1477 assert_eq!(Type::DOUBLE.to_string(), "DOUBLE");
1478 assert_eq!(Type::BYTE_ARRAY.to_string(), "BYTE_ARRAY");
1479 assert_eq!(
1480 Type::FIXED_LEN_BYTE_ARRAY.to_string(),
1481 "FIXED_LEN_BYTE_ARRAY"
1482 );
1483 }
1484
1485 #[test]
1486 fn test_from_string_into_type() {
1487 assert_eq!(
1488 Type::BOOLEAN.to_string().parse::<Type>().unwrap(),
1489 Type::BOOLEAN
1490 );
1491 assert_eq!(
1492 Type::INT32.to_string().parse::<Type>().unwrap(),
1493 Type::INT32
1494 );
1495 assert_eq!(
1496 Type::INT64.to_string().parse::<Type>().unwrap(),
1497 Type::INT64
1498 );
1499 assert_eq!(
1500 Type::INT96.to_string().parse::<Type>().unwrap(),
1501 Type::INT96
1502 );
1503 assert_eq!(
1504 Type::FLOAT.to_string().parse::<Type>().unwrap(),
1505 Type::FLOAT
1506 );
1507 assert_eq!(
1508 Type::DOUBLE.to_string().parse::<Type>().unwrap(),
1509 Type::DOUBLE
1510 );
1511 assert_eq!(
1512 Type::BYTE_ARRAY.to_string().parse::<Type>().unwrap(),
1513 Type::BYTE_ARRAY
1514 );
1515 assert_eq!("BINARY".parse::<Type>().unwrap(), Type::BYTE_ARRAY);
1516 assert_eq!(
1517 Type::FIXED_LEN_BYTE_ARRAY
1518 .to_string()
1519 .parse::<Type>()
1520 .unwrap(),
1521 Type::FIXED_LEN_BYTE_ARRAY
1522 );
1523 }
1524
1525 #[test]
1526 fn test_converted_type_roundtrip() {
1527 test_roundtrip(ConvertedType::UTF8);
1528 test_roundtrip(ConvertedType::MAP);
1529 test_roundtrip(ConvertedType::MAP_KEY_VALUE);
1530 test_roundtrip(ConvertedType::LIST);
1531 test_roundtrip(ConvertedType::ENUM);
1532 test_roundtrip(ConvertedType::DECIMAL);
1533 test_roundtrip(ConvertedType::DATE);
1534 test_roundtrip(ConvertedType::TIME_MILLIS);
1535 test_roundtrip(ConvertedType::TIME_MICROS);
1536 test_roundtrip(ConvertedType::TIMESTAMP_MILLIS);
1537 test_roundtrip(ConvertedType::TIMESTAMP_MICROS);
1538 test_roundtrip(ConvertedType::UINT_8);
1539 test_roundtrip(ConvertedType::UINT_16);
1540 test_roundtrip(ConvertedType::UINT_32);
1541 test_roundtrip(ConvertedType::UINT_64);
1542 test_roundtrip(ConvertedType::INT_8);
1543 test_roundtrip(ConvertedType::INT_16);
1544 test_roundtrip(ConvertedType::INT_32);
1545 test_roundtrip(ConvertedType::INT_64);
1546 test_roundtrip(ConvertedType::JSON);
1547 test_roundtrip(ConvertedType::BSON);
1548 test_roundtrip(ConvertedType::INTERVAL);
1549 }
1550
1551 #[test]
1552 fn test_read_invalid_converted_type() {
1553 let mut prot = ThriftSliceInputProtocol::new(&[0x7eu8]);
1554 let res = ConvertedType::read_thrift(&mut prot);
1555 assert!(res.is_err());
1556 assert_eq!(
1557 res.unwrap_err().to_string(),
1558 "Parquet error: Unexpected ConvertedType 63"
1559 );
1560 }
1561
1562 #[test]
1563 fn test_display_converted_type() {
1564 assert_eq!(ConvertedType::NONE.to_string(), "NONE");
1565 assert_eq!(ConvertedType::UTF8.to_string(), "UTF8");
1566 assert_eq!(ConvertedType::MAP.to_string(), "MAP");
1567 assert_eq!(ConvertedType::MAP_KEY_VALUE.to_string(), "MAP_KEY_VALUE");
1568 assert_eq!(ConvertedType::LIST.to_string(), "LIST");
1569 assert_eq!(ConvertedType::ENUM.to_string(), "ENUM");
1570 assert_eq!(ConvertedType::DECIMAL.to_string(), "DECIMAL");
1571 assert_eq!(ConvertedType::DATE.to_string(), "DATE");
1572 assert_eq!(ConvertedType::TIME_MILLIS.to_string(), "TIME_MILLIS");
1573 assert_eq!(ConvertedType::DATE.to_string(), "DATE");
1574 assert_eq!(ConvertedType::TIME_MICROS.to_string(), "TIME_MICROS");
1575 assert_eq!(
1576 ConvertedType::TIMESTAMP_MILLIS.to_string(),
1577 "TIMESTAMP_MILLIS"
1578 );
1579 assert_eq!(
1580 ConvertedType::TIMESTAMP_MICROS.to_string(),
1581 "TIMESTAMP_MICROS"
1582 );
1583 assert_eq!(ConvertedType::UINT_8.to_string(), "UINT_8");
1584 assert_eq!(ConvertedType::UINT_16.to_string(), "UINT_16");
1585 assert_eq!(ConvertedType::UINT_32.to_string(), "UINT_32");
1586 assert_eq!(ConvertedType::UINT_64.to_string(), "UINT_64");
1587 assert_eq!(ConvertedType::INT_8.to_string(), "INT_8");
1588 assert_eq!(ConvertedType::INT_16.to_string(), "INT_16");
1589 assert_eq!(ConvertedType::INT_32.to_string(), "INT_32");
1590 assert_eq!(ConvertedType::INT_64.to_string(), "INT_64");
1591 assert_eq!(ConvertedType::JSON.to_string(), "JSON");
1592 assert_eq!(ConvertedType::BSON.to_string(), "BSON");
1593 assert_eq!(ConvertedType::INTERVAL.to_string(), "INTERVAL");
1594 assert_eq!(ConvertedType::DECIMAL.to_string(), "DECIMAL")
1595 }
1596
1597 #[test]
1598 fn test_from_string_into_converted_type() {
1599 assert_eq!(
1600 ConvertedType::NONE
1601 .to_string()
1602 .parse::<ConvertedType>()
1603 .unwrap(),
1604 ConvertedType::NONE
1605 );
1606 assert_eq!(
1607 ConvertedType::UTF8
1608 .to_string()
1609 .parse::<ConvertedType>()
1610 .unwrap(),
1611 ConvertedType::UTF8
1612 );
1613 assert_eq!(
1614 ConvertedType::MAP
1615 .to_string()
1616 .parse::<ConvertedType>()
1617 .unwrap(),
1618 ConvertedType::MAP
1619 );
1620 assert_eq!(
1621 ConvertedType::MAP_KEY_VALUE
1622 .to_string()
1623 .parse::<ConvertedType>()
1624 .unwrap(),
1625 ConvertedType::MAP_KEY_VALUE
1626 );
1627 assert_eq!(
1628 ConvertedType::LIST
1629 .to_string()
1630 .parse::<ConvertedType>()
1631 .unwrap(),
1632 ConvertedType::LIST
1633 );
1634 assert_eq!(
1635 ConvertedType::ENUM
1636 .to_string()
1637 .parse::<ConvertedType>()
1638 .unwrap(),
1639 ConvertedType::ENUM
1640 );
1641 assert_eq!(
1642 ConvertedType::DECIMAL
1643 .to_string()
1644 .parse::<ConvertedType>()
1645 .unwrap(),
1646 ConvertedType::DECIMAL
1647 );
1648 assert_eq!(
1649 ConvertedType::DATE
1650 .to_string()
1651 .parse::<ConvertedType>()
1652 .unwrap(),
1653 ConvertedType::DATE
1654 );
1655 assert_eq!(
1656 ConvertedType::TIME_MILLIS
1657 .to_string()
1658 .parse::<ConvertedType>()
1659 .unwrap(),
1660 ConvertedType::TIME_MILLIS
1661 );
1662 assert_eq!(
1663 ConvertedType::TIME_MICROS
1664 .to_string()
1665 .parse::<ConvertedType>()
1666 .unwrap(),
1667 ConvertedType::TIME_MICROS
1668 );
1669 assert_eq!(
1670 ConvertedType::TIMESTAMP_MILLIS
1671 .to_string()
1672 .parse::<ConvertedType>()
1673 .unwrap(),
1674 ConvertedType::TIMESTAMP_MILLIS
1675 );
1676 assert_eq!(
1677 ConvertedType::TIMESTAMP_MICROS
1678 .to_string()
1679 .parse::<ConvertedType>()
1680 .unwrap(),
1681 ConvertedType::TIMESTAMP_MICROS
1682 );
1683 assert_eq!(
1684 ConvertedType::UINT_8
1685 .to_string()
1686 .parse::<ConvertedType>()
1687 .unwrap(),
1688 ConvertedType::UINT_8
1689 );
1690 assert_eq!(
1691 ConvertedType::UINT_16
1692 .to_string()
1693 .parse::<ConvertedType>()
1694 .unwrap(),
1695 ConvertedType::UINT_16
1696 );
1697 assert_eq!(
1698 ConvertedType::UINT_32
1699 .to_string()
1700 .parse::<ConvertedType>()
1701 .unwrap(),
1702 ConvertedType::UINT_32
1703 );
1704 assert_eq!(
1705 ConvertedType::UINT_64
1706 .to_string()
1707 .parse::<ConvertedType>()
1708 .unwrap(),
1709 ConvertedType::UINT_64
1710 );
1711 assert_eq!(
1712 ConvertedType::INT_8
1713 .to_string()
1714 .parse::<ConvertedType>()
1715 .unwrap(),
1716 ConvertedType::INT_8
1717 );
1718 assert_eq!(
1719 ConvertedType::INT_16
1720 .to_string()
1721 .parse::<ConvertedType>()
1722 .unwrap(),
1723 ConvertedType::INT_16
1724 );
1725 assert_eq!(
1726 ConvertedType::INT_32
1727 .to_string()
1728 .parse::<ConvertedType>()
1729 .unwrap(),
1730 ConvertedType::INT_32
1731 );
1732 assert_eq!(
1733 ConvertedType::INT_64
1734 .to_string()
1735 .parse::<ConvertedType>()
1736 .unwrap(),
1737 ConvertedType::INT_64
1738 );
1739 assert_eq!(
1740 ConvertedType::JSON
1741 .to_string()
1742 .parse::<ConvertedType>()
1743 .unwrap(),
1744 ConvertedType::JSON
1745 );
1746 assert_eq!(
1747 ConvertedType::BSON
1748 .to_string()
1749 .parse::<ConvertedType>()
1750 .unwrap(),
1751 ConvertedType::BSON
1752 );
1753 assert_eq!(
1754 ConvertedType::INTERVAL
1755 .to_string()
1756 .parse::<ConvertedType>()
1757 .unwrap(),
1758 ConvertedType::INTERVAL
1759 );
1760 assert_eq!(
1761 ConvertedType::DECIMAL
1762 .to_string()
1763 .parse::<ConvertedType>()
1764 .unwrap(),
1765 ConvertedType::DECIMAL
1766 )
1767 }
1768
1769 #[test]
1770 fn test_logical_to_converted_type() {
1771 let logical_none: Option<LogicalType> = None;
1772 assert_eq!(ConvertedType::from(logical_none), ConvertedType::NONE);
1773 assert_eq!(
1774 ConvertedType::from(Some(LogicalType::decimal(5, 20))),
1775 ConvertedType::DECIMAL
1776 );
1777 assert_eq!(
1778 ConvertedType::from(Some(LogicalType::Bson)),
1779 ConvertedType::BSON
1780 );
1781 assert_eq!(
1782 ConvertedType::from(Some(LogicalType::Json)),
1783 ConvertedType::JSON
1784 );
1785 assert_eq!(
1786 ConvertedType::from(Some(LogicalType::String)),
1787 ConvertedType::UTF8
1788 );
1789 assert_eq!(
1790 ConvertedType::from(Some(LogicalType::Date)),
1791 ConvertedType::DATE
1792 );
1793 assert_eq!(
1794 ConvertedType::from(Some(LogicalType::time(true, TimeUnit::MILLIS))),
1795 ConvertedType::TIME_MILLIS
1796 );
1797 assert_eq!(
1798 ConvertedType::from(Some(LogicalType::time(true, TimeUnit::MICROS))),
1799 ConvertedType::TIME_MICROS
1800 );
1801 assert_eq!(
1802 ConvertedType::from(Some(LogicalType::time(false, TimeUnit::NANOS))),
1803 ConvertedType::NONE
1804 );
1805 assert_eq!(
1806 ConvertedType::from(Some(LogicalType::timestamp(true, TimeUnit::MILLIS))),
1807 ConvertedType::TIMESTAMP_MILLIS
1808 );
1809 assert_eq!(
1810 ConvertedType::from(Some(LogicalType::timestamp(false, TimeUnit::MICROS))),
1811 ConvertedType::TIMESTAMP_MICROS
1812 );
1813 assert_eq!(
1814 ConvertedType::from(Some(LogicalType::timestamp(false, TimeUnit::NANOS))),
1815 ConvertedType::NONE
1816 );
1817 assert_eq!(
1818 ConvertedType::from(Some(LogicalType::integer(8, false))),
1819 ConvertedType::UINT_8
1820 );
1821 assert_eq!(
1822 ConvertedType::from(Some(LogicalType::integer(8, true))),
1823 ConvertedType::INT_8
1824 );
1825 assert_eq!(
1826 ConvertedType::from(Some(LogicalType::integer(16, false))),
1827 ConvertedType::UINT_16
1828 );
1829 assert_eq!(
1830 ConvertedType::from(Some(LogicalType::integer(16, true))),
1831 ConvertedType::INT_16
1832 );
1833 assert_eq!(
1834 ConvertedType::from(Some(LogicalType::integer(32, false))),
1835 ConvertedType::UINT_32
1836 );
1837 assert_eq!(
1838 ConvertedType::from(Some(LogicalType::integer(32, true))),
1839 ConvertedType::INT_32
1840 );
1841 assert_eq!(
1842 ConvertedType::from(Some(LogicalType::integer(64, false))),
1843 ConvertedType::UINT_64
1844 );
1845 assert_eq!(
1846 ConvertedType::from(Some(LogicalType::integer(64, true))),
1847 ConvertedType::INT_64
1848 );
1849 assert_eq!(
1850 ConvertedType::from(Some(LogicalType::List)),
1851 ConvertedType::LIST
1852 );
1853 assert_eq!(
1854 ConvertedType::from(Some(LogicalType::Map)),
1855 ConvertedType::MAP
1856 );
1857 assert_eq!(
1858 ConvertedType::from(Some(LogicalType::Uuid)),
1859 ConvertedType::NONE
1860 );
1861 assert_eq!(
1862 ConvertedType::from(Some(LogicalType::Enum)),
1863 ConvertedType::ENUM
1864 );
1865 assert_eq!(
1866 ConvertedType::from(Some(LogicalType::Float16)),
1867 ConvertedType::NONE
1868 );
1869 assert_eq!(
1870 ConvertedType::from(Some(LogicalType::variant(None))),
1871 ConvertedType::NONE
1872 );
1873 assert_eq!(
1874 ConvertedType::from(Some(LogicalType::geometry(None))),
1875 ConvertedType::NONE
1876 );
1877 assert_eq!(
1878 ConvertedType::from(Some(LogicalType::geography(None, Some(Default::default())))),
1879 ConvertedType::NONE
1880 );
1881 assert_eq!(
1882 ConvertedType::from(Some(LogicalType::Unknown)),
1883 ConvertedType::NONE
1884 );
1885 }
1886
1887 #[test]
1888 fn test_logical_type_roundtrip() {
1889 test_roundtrip(LogicalType::String);
1890 test_roundtrip(LogicalType::Map);
1891 test_roundtrip(LogicalType::List);
1892 test_roundtrip(LogicalType::Enum);
1893 test_roundtrip(LogicalType::decimal(0, 20));
1894 test_roundtrip(LogicalType::Date);
1895 test_roundtrip(LogicalType::time(true, TimeUnit::MICROS));
1896 test_roundtrip(LogicalType::time(false, TimeUnit::MILLIS));
1897 test_roundtrip(LogicalType::time(false, TimeUnit::NANOS));
1898 test_roundtrip(LogicalType::timestamp(false, TimeUnit::MICROS));
1899 test_roundtrip(LogicalType::timestamp(true, TimeUnit::MILLIS));
1900 test_roundtrip(LogicalType::timestamp(true, TimeUnit::NANOS));
1901 test_roundtrip(LogicalType::integer(8, true));
1902 test_roundtrip(LogicalType::integer(16, false));
1903 test_roundtrip(LogicalType::integer(32, true));
1904 test_roundtrip(LogicalType::integer(64, false));
1905 test_roundtrip(LogicalType::Json);
1906 test_roundtrip(LogicalType::Bson);
1907 test_roundtrip(LogicalType::Uuid);
1908 test_roundtrip(LogicalType::Float16);
1909 test_roundtrip(LogicalType::variant(Some(1)));
1910 test_roundtrip(LogicalType::variant(None));
1911 test_roundtrip(LogicalType::geometry(Some("foo".to_owned())));
1912 test_roundtrip(LogicalType::geometry(None));
1913 test_roundtrip(LogicalType::geography(
1914 Some("foo".to_owned()),
1915 Some(EdgeInterpolationAlgorithm::ANDOYER),
1916 ));
1917 test_roundtrip(LogicalType::geography(
1918 None,
1919 Some(EdgeInterpolationAlgorithm::KARNEY),
1920 ));
1921 test_roundtrip(LogicalType::geography(
1922 Some("foo".to_owned()),
1923 Some(EdgeInterpolationAlgorithm::SPHERICAL),
1924 ));
1925 test_roundtrip(LogicalType::geography(
1926 None,
1927 Some(EdgeInterpolationAlgorithm::SPHERICAL),
1928 ));
1929 }
1930
1931 #[test]
1932 fn test_display_repetition() {
1933 assert_eq!(Repetition::REQUIRED.to_string(), "REQUIRED");
1934 assert_eq!(Repetition::OPTIONAL.to_string(), "OPTIONAL");
1935 assert_eq!(Repetition::REPEATED.to_string(), "REPEATED");
1936 }
1937
1938 #[test]
1939 fn test_from_string_into_repetition() {
1940 assert_eq!(
1941 Repetition::REQUIRED
1942 .to_string()
1943 .parse::<Repetition>()
1944 .unwrap(),
1945 Repetition::REQUIRED
1946 );
1947 assert_eq!(
1948 Repetition::OPTIONAL
1949 .to_string()
1950 .parse::<Repetition>()
1951 .unwrap(),
1952 Repetition::OPTIONAL
1953 );
1954 assert_eq!(
1955 Repetition::REPEATED
1956 .to_string()
1957 .parse::<Repetition>()
1958 .unwrap(),
1959 Repetition::REPEATED
1960 );
1961 }
1962
1963 #[test]
1964 fn test_display_encoding() {
1965 assert_eq!(Encoding::PLAIN.to_string(), "PLAIN");
1966 assert_eq!(Encoding::PLAIN_DICTIONARY.to_string(), "PLAIN_DICTIONARY");
1967 assert_eq!(Encoding::RLE.to_string(), "RLE");
1968 assert_eq!(Encoding::BIT_PACKED.to_string(), "BIT_PACKED");
1969 assert_eq!(
1970 Encoding::DELTA_BINARY_PACKED.to_string(),
1971 "DELTA_BINARY_PACKED"
1972 );
1973 assert_eq!(
1974 Encoding::DELTA_LENGTH_BYTE_ARRAY.to_string(),
1975 "DELTA_LENGTH_BYTE_ARRAY"
1976 );
1977 assert_eq!(Encoding::DELTA_BYTE_ARRAY.to_string(), "DELTA_BYTE_ARRAY");
1978 assert_eq!(Encoding::RLE_DICTIONARY.to_string(), "RLE_DICTIONARY");
1979 assert_eq!(Encoding::ALP.to_string(), "ALP");
1980 }
1981
1982 #[test]
1983 fn test_compression_conversion() {
1984 assert_eq!(
1985 CompressionCodec::from(Compression::UNCOMPRESSED),
1986 CompressionCodec::UNCOMPRESSED
1987 );
1988 assert_eq!(
1989 CompressionCodec::from(Compression::SNAPPY),
1990 CompressionCodec::SNAPPY
1991 );
1992 assert_eq!(
1993 CompressionCodec::from(Compression::GZIP(Default::default())),
1994 CompressionCodec::GZIP
1995 );
1996 assert_eq!(
1997 CompressionCodec::from(Compression::LZO),
1998 CompressionCodec::LZO
1999 );
2000 assert_eq!(
2001 CompressionCodec::from(Compression::BROTLI(Default::default())),
2002 CompressionCodec::BROTLI
2003 );
2004 assert_eq!(
2005 CompressionCodec::from(Compression::LZ4),
2006 CompressionCodec::LZ4
2007 );
2008 assert_eq!(
2009 CompressionCodec::from(Compression::ZSTD(Default::default())),
2010 CompressionCodec::ZSTD
2011 );
2012 assert_eq!(
2013 CompressionCodec::from(Compression::LZ4_RAW),
2014 CompressionCodec::LZ4_RAW
2015 );
2016
2017 assert_eq!(
2018 Compression::from(CompressionCodec::UNCOMPRESSED),
2019 Compression::UNCOMPRESSED
2020 );
2021 assert_eq!(
2022 Compression::from(CompressionCodec::SNAPPY),
2023 Compression::SNAPPY
2024 );
2025 assert_eq!(
2026 Compression::from(CompressionCodec::GZIP),
2027 Compression::GZIP(Default::default())
2028 );
2029 assert_eq!(Compression::from(CompressionCodec::LZO), Compression::LZO);
2030 assert_eq!(
2031 Compression::from(CompressionCodec::BROTLI),
2032 Compression::BROTLI(Default::default())
2033 );
2034 assert_eq!(Compression::from(CompressionCodec::LZ4), Compression::LZ4);
2035 assert_eq!(
2036 Compression::from(CompressionCodec::ZSTD),
2037 Compression::ZSTD(Default::default())
2038 );
2039 assert_eq!(
2040 Compression::from(CompressionCodec::LZ4_RAW),
2041 Compression::LZ4_RAW
2042 );
2043 }
2044
2045 #[test]
2046 fn test_display_compression() {
2047 assert_eq!(Compression::UNCOMPRESSED.to_string(), "UNCOMPRESSED");
2048 assert_eq!(Compression::SNAPPY.to_string(), "SNAPPY");
2049 assert_eq!(
2050 Compression::GZIP(Default::default()).to_string(),
2051 "GZIP(GzipLevel(6))"
2052 );
2053 assert_eq!(Compression::LZO.to_string(), "LZO");
2054 assert_eq!(
2055 Compression::BROTLI(Default::default()).to_string(),
2056 "BROTLI(BrotliLevel(1))"
2057 );
2058 assert_eq!(Compression::LZ4.to_string(), "LZ4");
2059 assert_eq!(
2060 Compression::ZSTD(Default::default()).to_string(),
2061 "ZSTD(ZstdLevel(1))"
2062 );
2063 }
2064
2065 #[test]
2066 fn test_display_page_type() {
2067 assert_eq!(PageType::DATA_PAGE.to_string(), "DATA_PAGE");
2068 assert_eq!(PageType::INDEX_PAGE.to_string(), "INDEX_PAGE");
2069 assert_eq!(PageType::DICTIONARY_PAGE.to_string(), "DICTIONARY_PAGE");
2070 assert_eq!(PageType::DATA_PAGE_V2.to_string(), "DATA_PAGE_V2");
2071 }
2072
2073 #[test]
2074 fn test_display_sort_order() {
2075 assert_eq!(SortOrder::SIGNED.to_string(), "SIGNED");
2076 assert_eq!(SortOrder::UNSIGNED.to_string(), "UNSIGNED");
2077 assert_eq!(SortOrder::UNDEFINED.to_string(), "UNDEFINED");
2078 assert_eq!(SortOrder::TOTAL_ORDER.to_string(), "TOTAL_ORDER");
2079 assert_eq!(SortOrder::INT96_TIMESTAMP.to_string(), "INT96_TIMESTAMP");
2080 }
2081
2082 #[test]
2083 fn test_display_column_order() {
2084 assert_eq!(
2085 ColumnOrder::TYPE_DEFINED_ORDER(SortOrder::SIGNED).to_string(),
2086 "TYPE_DEFINED_ORDER(SIGNED)"
2087 );
2088 assert_eq!(
2089 ColumnOrder::TYPE_DEFINED_ORDER(SortOrder::UNSIGNED).to_string(),
2090 "TYPE_DEFINED_ORDER(UNSIGNED)"
2091 );
2092 assert_eq!(
2093 ColumnOrder::TYPE_DEFINED_ORDER(SortOrder::UNDEFINED).to_string(),
2094 "TYPE_DEFINED_ORDER(UNDEFINED)"
2095 );
2096 assert_eq!(
2097 ColumnOrder::IEEE_754_TOTAL_ORDER.to_string(),
2098 "IEEE_754_TOTAL_ORDER"
2099 );
2100 assert_eq!(
2101 ColumnOrder::INT96_TIMESTAMP_ORDER.to_string(),
2102 "INT96_TIMESTAMP_ORDER"
2103 );
2104 assert_eq!(ColumnOrder::UNDEFINED.to_string(), "UNDEFINED");
2105 }
2106
2107 #[test]
2108 fn test_column_order_roundtrip() {
2109 test_roundtrip(ColumnOrder::TYPE_DEFINED_ORDER(SortOrder::SIGNED))
2111 }
2112
2113 #[test]
2114 fn test_column_order_get_logical_type_sort_order() {
2115 fn check_sort_order(types: Vec<LogicalType>, expected_order: SortOrder) {
2118 for type_ in types {
2119 assert_eq!(
2120 ColumnOrder::column_order_for_type(
2121 Some(&type_),
2122 ConvertedType::NONE,
2123 Type::BYTE_ARRAY
2124 )
2125 .sort_order(),
2126 expected_order
2127 );
2128 }
2129 }
2130
2131 let unsigned = vec![
2133 LogicalType::String,
2134 LogicalType::Json,
2135 LogicalType::Bson,
2136 LogicalType::Enum,
2137 LogicalType::Uuid,
2138 LogicalType::integer(8, false),
2139 LogicalType::integer(16, false),
2140 LogicalType::integer(32, false),
2141 LogicalType::integer(64, false),
2142 ];
2143 check_sort_order(unsigned, SortOrder::UNSIGNED);
2144
2145 let signed = vec![
2147 LogicalType::integer(8, true),
2148 LogicalType::integer(16, true),
2149 LogicalType::integer(32, true),
2150 LogicalType::integer(64, true),
2151 LogicalType::decimal(20, 4),
2152 LogicalType::Date,
2153 LogicalType::time(false, TimeUnit::MILLIS),
2154 LogicalType::time(false, TimeUnit::MICROS),
2155 LogicalType::time(true, TimeUnit::NANOS),
2156 LogicalType::timestamp(false, TimeUnit::MILLIS),
2157 LogicalType::timestamp(false, TimeUnit::MICROS),
2158 LogicalType::timestamp(true, TimeUnit::NANOS),
2159 ];
2160 check_sort_order(signed, SortOrder::SIGNED);
2161
2162 let float = vec![LogicalType::Float16];
2163 check_sort_order(float, SortOrder::TOTAL_ORDER);
2164
2165 let undefined = vec![
2167 LogicalType::List,
2168 LogicalType::Map,
2169 LogicalType::variant(None),
2170 LogicalType::geometry(None),
2171 LogicalType::geography(None, Some(Default::default())),
2172 ];
2173 check_sort_order(undefined, SortOrder::UNDEFINED);
2174 }
2175
2176 #[test]
2177 fn test_column_order_get_converted_type_sort_order() {
2178 fn check_sort_order(types: Vec<ConvertedType>, expected_order: SortOrder) {
2181 for type_ in types {
2182 assert_eq!(
2183 ColumnOrder::column_order_for_type(None, type_, Type::BYTE_ARRAY).sort_order(),
2184 expected_order
2185 );
2186 }
2187 }
2188
2189 let unsigned = vec![
2191 ConvertedType::UTF8,
2192 ConvertedType::JSON,
2193 ConvertedType::BSON,
2194 ConvertedType::ENUM,
2195 ConvertedType::UINT_8,
2196 ConvertedType::UINT_16,
2197 ConvertedType::UINT_32,
2198 ConvertedType::UINT_64,
2199 ];
2200 check_sort_order(unsigned, SortOrder::UNSIGNED);
2201
2202 let signed = vec![
2204 ConvertedType::INT_8,
2205 ConvertedType::INT_16,
2206 ConvertedType::INT_32,
2207 ConvertedType::INT_64,
2208 ConvertedType::DECIMAL,
2209 ConvertedType::DATE,
2210 ConvertedType::TIME_MILLIS,
2211 ConvertedType::TIME_MICROS,
2212 ConvertedType::TIMESTAMP_MILLIS,
2213 ConvertedType::TIMESTAMP_MICROS,
2214 ];
2215 check_sort_order(signed, SortOrder::SIGNED);
2216
2217 let undefined = vec![
2219 ConvertedType::LIST,
2220 ConvertedType::MAP,
2221 ConvertedType::MAP_KEY_VALUE,
2222 ConvertedType::INTERVAL,
2223 ];
2224 check_sort_order(undefined, SortOrder::UNDEFINED);
2225
2226 check_sort_order(vec![ConvertedType::NONE], SortOrder::UNSIGNED);
2229 }
2230
2231 #[test]
2232 fn test_column_order_get_default_sort_order() {
2233 assert_eq!(
2235 ColumnOrder::get_default_sort_order(Type::BOOLEAN, true),
2236 SortOrder::UNSIGNED
2237 );
2238 assert_eq!(
2239 ColumnOrder::get_default_sort_order(Type::INT32, true),
2240 SortOrder::SIGNED
2241 );
2242 assert_eq!(
2243 ColumnOrder::get_default_sort_order(Type::INT64, true),
2244 SortOrder::SIGNED
2245 );
2246 assert_eq!(
2247 ColumnOrder::get_default_sort_order(Type::INT96, true),
2248 SortOrder::UNDEFINED
2249 );
2250 assert_eq!(
2251 ColumnOrder::get_default_sort_order(Type::INT96, false),
2252 SortOrder::INT96_TIMESTAMP
2253 );
2254 assert_eq!(
2255 ColumnOrder::get_default_sort_order(Type::FLOAT, false),
2256 SortOrder::TOTAL_ORDER
2257 );
2258 assert_eq!(
2259 ColumnOrder::get_default_sort_order(Type::DOUBLE, false),
2260 SortOrder::TOTAL_ORDER
2261 );
2262 assert_eq!(
2263 ColumnOrder::get_default_sort_order(Type::FLOAT, true),
2264 SortOrder::SIGNED
2265 );
2266 assert_eq!(
2267 ColumnOrder::get_default_sort_order(Type::DOUBLE, true),
2268 SortOrder::SIGNED
2269 );
2270 assert_eq!(
2271 ColumnOrder::get_default_sort_order(Type::BYTE_ARRAY, true),
2272 SortOrder::UNSIGNED
2273 );
2274 assert_eq!(
2275 ColumnOrder::get_default_sort_order(Type::FIXED_LEN_BYTE_ARRAY, true),
2276 SortOrder::UNSIGNED
2277 );
2278 }
2279
2280 #[test]
2281 fn test_column_order_sort_order() {
2282 assert_eq!(
2283 ColumnOrder::TYPE_DEFINED_ORDER(SortOrder::SIGNED).sort_order(),
2284 SortOrder::SIGNED
2285 );
2286 assert_eq!(
2287 ColumnOrder::TYPE_DEFINED_ORDER(SortOrder::UNSIGNED).sort_order(),
2288 SortOrder::UNSIGNED
2289 );
2290 assert_eq!(
2291 ColumnOrder::TYPE_DEFINED_ORDER(SortOrder::UNDEFINED).sort_order(),
2292 SortOrder::UNDEFINED
2293 );
2294 assert_eq!(
2295 ColumnOrder::IEEE_754_TOTAL_ORDER.sort_order(),
2296 SortOrder::TOTAL_ORDER
2297 );
2298 assert_eq!(
2299 ColumnOrder::INT96_TIMESTAMP_ORDER.sort_order(),
2300 SortOrder::INT96_TIMESTAMP
2301 );
2302 assert_eq!(ColumnOrder::UNDEFINED.sort_order(), SortOrder::SIGNED);
2303 }
2304
2305 #[test]
2306 fn test_parse_encoding() {
2307 let mut encoding: Encoding = "PLAIN".parse().unwrap();
2308 assert_eq!(encoding, Encoding::PLAIN);
2309 encoding = "PLAIN_DICTIONARY".parse().unwrap();
2310 assert_eq!(encoding, Encoding::PLAIN_DICTIONARY);
2311 encoding = "RLE".parse().unwrap();
2312 assert_eq!(encoding, Encoding::RLE);
2313 encoding = "BIT_PACKED".parse().unwrap();
2314 assert_eq!(encoding, Encoding::BIT_PACKED);
2315 encoding = "DELTA_BINARY_PACKED".parse().unwrap();
2316 assert_eq!(encoding, Encoding::DELTA_BINARY_PACKED);
2317 encoding = "DELTA_LENGTH_BYTE_ARRAY".parse().unwrap();
2318 assert_eq!(encoding, Encoding::DELTA_LENGTH_BYTE_ARRAY);
2319 encoding = "DELTA_BYTE_ARRAY".parse().unwrap();
2320 assert_eq!(encoding, Encoding::DELTA_BYTE_ARRAY);
2321 encoding = "RLE_DICTIONARY".parse().unwrap();
2322 assert_eq!(encoding, Encoding::RLE_DICTIONARY);
2323 encoding = "BYTE_STREAM_SPLIT".parse().unwrap();
2324 assert_eq!(encoding, Encoding::BYTE_STREAM_SPLIT);
2325 encoding = "alp".parse().unwrap();
2326 assert_eq!(encoding, Encoding::ALP);
2327
2328 encoding = "byte_stream_split".parse().unwrap();
2330 assert_eq!(encoding, Encoding::BYTE_STREAM_SPLIT);
2331
2332 match "plain_xxx".parse::<Encoding>() {
2334 Ok(e) => {
2335 panic!("Should not be able to parse {e:?}");
2336 }
2337 Err(e) => {
2338 assert_eq!(e.to_string(), "Parquet error: unknown encoding: plain_xxx");
2339 }
2340 }
2341 }
2342
2343 #[test]
2344 fn test_parse_compression() {
2345 let mut compress: Compression = "snappy".parse().unwrap();
2346 assert_eq!(compress, Compression::SNAPPY);
2347 compress = "lzo".parse().unwrap();
2348 assert_eq!(compress, Compression::LZO);
2349 compress = "zstd(3)".parse().unwrap();
2350 assert_eq!(compress, Compression::ZSTD(ZstdLevel::try_new(3).unwrap()));
2351 compress = "zstd(-3)".parse().unwrap();
2352 assert_eq!(compress, Compression::ZSTD(ZstdLevel::try_new(-3).unwrap()));
2353 compress = "LZ4_RAW".parse().unwrap();
2354 assert_eq!(compress, Compression::LZ4_RAW);
2355 compress = "uncompressed".parse().unwrap();
2356 assert_eq!(compress, Compression::UNCOMPRESSED);
2357 compress = "snappy".parse().unwrap();
2358 assert_eq!(compress, Compression::SNAPPY);
2359 compress = "gzip(9)".parse().unwrap();
2360 assert_eq!(compress, Compression::GZIP(GzipLevel::try_new(9).unwrap()));
2361 compress = "lzo".parse().unwrap();
2362 assert_eq!(compress, Compression::LZO);
2363 compress = "brotli(3)".parse().unwrap();
2364 assert_eq!(
2365 compress,
2366 Compression::BROTLI(BrotliLevel::try_new(3).unwrap())
2367 );
2368 compress = "lz4".parse().unwrap();
2369 assert_eq!(compress, Compression::LZ4);
2370
2371 let mut err = "plain_xxx".parse::<Encoding>().unwrap_err();
2373 assert_eq!(
2374 err.to_string(),
2375 "Parquet error: unknown encoding: plain_xxx"
2376 );
2377
2378 err = "gzip(-10)".parse::<Encoding>().unwrap_err();
2380 assert_eq!(
2381 err.to_string(),
2382 "Parquet error: unknown encoding: gzip(-10)"
2383 );
2384 }
2385
2386 #[test]
2387 fn test_display_boundary_order() {
2388 assert_eq!(BoundaryOrder::ASCENDING.to_string(), "ASCENDING");
2389 assert_eq!(BoundaryOrder::DESCENDING.to_string(), "DESCENDING");
2390 assert_eq!(BoundaryOrder::UNORDERED.to_string(), "UNORDERED");
2391 }
2392
2393 #[test]
2394 fn test_display_edge_algo() {
2395 assert_eq!(
2396 EdgeInterpolationAlgorithm::SPHERICAL.to_string(),
2397 "SPHERICAL"
2398 );
2399 assert_eq!(EdgeInterpolationAlgorithm::VINCENTY.to_string(), "VINCENTY");
2400 assert_eq!(EdgeInterpolationAlgorithm::THOMAS.to_string(), "THOMAS");
2401 assert_eq!(EdgeInterpolationAlgorithm::ANDOYER.to_string(), "ANDOYER");
2402 assert_eq!(EdgeInterpolationAlgorithm::KARNEY.to_string(), "KARNEY");
2403 }
2404
2405 #[test]
2406 fn test_from_str_edge_algo() {
2407 assert_eq!(
2408 "spHErical".parse::<EdgeInterpolationAlgorithm>().unwrap(),
2409 EdgeInterpolationAlgorithm::SPHERICAL
2410 );
2411 assert_eq!(
2412 "vinceNTY".parse::<EdgeInterpolationAlgorithm>().unwrap(),
2413 EdgeInterpolationAlgorithm::VINCENTY
2414 );
2415 assert_eq!(
2416 "tHOmas".parse::<EdgeInterpolationAlgorithm>().unwrap(),
2417 EdgeInterpolationAlgorithm::THOMAS
2418 );
2419 assert_eq!(
2420 "anDOYEr".parse::<EdgeInterpolationAlgorithm>().unwrap(),
2421 EdgeInterpolationAlgorithm::ANDOYER
2422 );
2423 assert_eq!(
2424 "kaRNey".parse::<EdgeInterpolationAlgorithm>().unwrap(),
2425 EdgeInterpolationAlgorithm::KARNEY
2426 );
2427 assert!(
2428 "does not exist"
2429 .parse::<EdgeInterpolationAlgorithm>()
2430 .is_err()
2431 );
2432 }
2433
2434 fn encodings_roundtrip(mut encodings: Vec<Encoding>) {
2435 encodings.sort();
2436 let mask = EncodingMask::new_from_encodings(encodings.iter());
2437 assert!(mask.all_set(encodings.iter()));
2438 let v = mask.encodings().collect::<Vec<_>>();
2439 assert_eq!(v, encodings);
2440 }
2441
2442 #[test]
2443 fn test_encoding_roundtrip() {
2444 encodings_roundtrip(
2445 [
2446 Encoding::RLE,
2447 Encoding::PLAIN,
2448 Encoding::DELTA_BINARY_PACKED,
2449 ]
2450 .into(),
2451 );
2452 encodings_roundtrip([Encoding::RLE_DICTIONARY, Encoding::PLAIN_DICTIONARY].into());
2453 encodings_roundtrip([].into());
2454 let encodings = [
2455 Encoding::PLAIN,
2456 Encoding::BIT_PACKED,
2457 Encoding::RLE,
2458 Encoding::DELTA_BINARY_PACKED,
2459 Encoding::DELTA_BYTE_ARRAY,
2460 Encoding::DELTA_LENGTH_BYTE_ARRAY,
2461 Encoding::PLAIN_DICTIONARY,
2462 Encoding::RLE_DICTIONARY,
2463 Encoding::BYTE_STREAM_SPLIT,
2464 Encoding::ALP,
2465 ];
2466 encodings_roundtrip(encodings.into());
2467 }
2468
2469 #[test]
2470 fn test_invalid_encoding_mask() {
2471 let res = EncodingMask::try_new(-1);
2473 assert!(res.is_err());
2474 let err = res.unwrap_err();
2475 assert_eq!(
2476 err.to_string(),
2477 "Parquet error: Attempt to create invalid mask: 0xffffffff"
2478 );
2479
2480 let res = EncodingMask::try_new(2);
2482 assert!(res.is_err());
2483 let err = res.unwrap_err();
2484 assert_eq!(
2485 err.to_string(),
2486 "Parquet error: Attempt to create invalid mask: 0x2"
2487 );
2488 }
2489
2490 #[test]
2491 fn test_encoding_mask_is_only() {
2492 let mask = EncodingMask::new_from_encodings([Encoding::PLAIN].iter());
2493 assert!(mask.is_only(Encoding::PLAIN));
2494
2495 let mask =
2496 EncodingMask::new_from_encodings([Encoding::PLAIN, Encoding::PLAIN_DICTIONARY].iter());
2497 assert!(!mask.is_only(Encoding::PLAIN));
2498 }
2499}